Fixing eslint.

This commit is contained in:
Dessalines 2024-10-14 19:03:42 -04:00
parent 5f98a6e9e3
commit e8dfff4da7
19 changed files with 1212 additions and 126 deletions

View file

@ -1,4 +0,0 @@
generate_translations.js
webpack.config.js
tailwind.config.js
src/api_tests

View file

@ -1,41 +0,0 @@
{
"root": true,
"env": {
"browser": true
},
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"warnOnUnsupportedTypeScriptVersion": false
},
"rules": {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"arrow-body-style": 0,
"curly": 0,
"eol-last": 0,
"eqeqeq": 0,
"func-style": 0,
"import/no-duplicates": 0,
"max-statements": 0,
"max-params": 0,
"new-cap": 0,
"no-console": 0,
"no-duplicate-imports": 0,
"no-extra-parens": 0,
"no-return-assign": 0,
"no-throw-literal": 0,
"no-trailing-spaces": 0,
"no-unused-expressions": 0,
"no-useless-constructor": 0,
"no-useless-escape": 0,
"no-var": 0,
"prefer-const": 0,
"prefer-rest-params": 0,
"quote-props": 0,
"unicorn/filename-case": 0
}
}

View file

@ -1,5 +1,5 @@
# Build the git includes for the docs # Build the git includes for the docs
FROM alpine:3 as docs_include FROM alpine:3 AS docs_include
RUN apk add --no-cache git bash curl RUN apk add --no-cache git bash curl
WORKDIR /app WORKDIR /app
COPY lemmy-docs ./lemmy-docs COPY lemmy-docs ./lemmy-docs
@ -7,7 +7,7 @@ WORKDIR /app/lemmy-docs
RUN ./update-includes.sh RUN ./update-includes.sh
# Build the docs # Build the docs
FROM alpine:3 as docs FROM alpine:3 AS docs
WORKDIR /app WORKDIR /app
RUN wget -O mdbook.tar.gz https://github.com/rust-lang/mdBook/releases/download/v0.4.30/mdbook-v0.4.30-x86_64-unknown-linux-musl.tar.gz RUN wget -O mdbook.tar.gz https://github.com/rust-lang/mdBook/releases/download/v0.4.30/mdbook-v0.4.30-x86_64-unknown-linux-musl.tar.gz
RUN tar -xzf mdbook.tar.gz RUN tar -xzf mdbook.tar.gz
@ -15,7 +15,7 @@ COPY lemmy-docs ./lemmy-docs
RUN ./mdbook build lemmy-docs -d ../docs RUN ./mdbook build lemmy-docs -d ../docs
# Build the typedoc API docs # Build the typedoc API docs
FROM node:alpine as api FROM node:alpine AS api
WORKDIR /app WORKDIR /app
COPY lemmy-js-client lemmy-js-client COPY lemmy-js-client lemmy-js-client
WORKDIR /app/lemmy-js-client WORKDIR /app/lemmy-js-client
@ -24,7 +24,7 @@ RUN pnpm i
RUN pnpm run docs RUN pnpm run docs
# Build the isomorphic app # Build the isomorphic app
FROM node:alpine as builder FROM node:alpine AS builder
RUN apk update && apk add python3 build-base gcc wget git curl --no-cache RUN apk update && apk add python3 build-base gcc wget git curl --no-cache
RUN curl -sf https://gobinaries.com/tj/node-prune | sh RUN curl -sf https://gobinaries.com/tj/node-prune | sh
RUN corepack enable pnpm RUN corepack enable pnpm
@ -63,7 +63,7 @@ RUN rm -rf ./node_modules/import-sort-parser-typescript
RUN rm -rf ./node_modules/typescript RUN rm -rf ./node_modules/typescript
RUN rm -rf ./node_modules/npm RUN rm -rf ./node_modules/npm
FROM node:alpine as runner FROM node:alpine AS runner
COPY --from=builder /app/dist /app/dist COPY --from=builder /app/dist /app/dist
COPY --from=builder /app/node_modules /app/node_modules COPY --from=builder /app/node_modules /app/node_modules

98
eslint.config.mjs Normal file
View file

@ -0,0 +1,98 @@
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-plugin-prettier/recommended";
import jsxa11y from "eslint-plugin-jsx-a11y";
import inferno from "eslint-plugin-inferno";
export default [
pluginJs.configs.recommended,
...tseslint.configs.recommended,
prettier,
{
plugins: {
inferno: inferno,
rules: inferno.configs.recommended,
},
},
{
plugins: {
"jsx-a11y": jsxa11y,
},
rules: jsxa11y.configs.recommended.rules,
},
{
languageOptions: {
parser: tseslint.parser,
},
},
// For some reason this has to be in its own block
{
ignores: [
"crawl.mjs",
"generate_rss_feed.mjs",
"generate_translations.mjs",
"lemmy-js-client",
"webpack.config.js",
"tailwind.config.js",
"src/shared/build-config.js",
"src/api_tests",
"**/*.png",
"**/*.css",
"**/*.scss",
"**/*.svg",
"dist/*",
".yalc/*",
],
},
{
files: ["src/**/*.js", "src/**/*.mjs", "src/**/*.ts", "src/**/*.tsx"],
rules: {
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
"explicit-module-boundary-types": 0,
"no-empty-function": 0,
"no-non-null-assertion": 0,
"arrow-body-style": 0,
curly: 0,
"eol-last": 0,
eqeqeq: "error",
"func-style": 0,
"import/no-duplicates": 0,
"max-statements": 0,
"max-params": 0,
"new-cap": 0,
"no-console": 0,
"no-duplicate-imports": 0,
"no-extra-parens": 0,
"no-return-assign": 0,
"no-throw-literal": 0,
"no-trailing-spaces": 0,
"no-unused-expressions": 0,
"no-useless-constructor": 0,
"no-useless-escape": 0,
"no-var": 0,
"prefer-const": "error",
"prefer-rest-params": 0,
"prettier/prettier": "error",
"quote-props": 0,
"unicorn/filename-case": 0,
"jsx-a11y/media-has-caption": 0,
"jsx-a11y/label-has-associated-control": 0,
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["assets/*", "client/*", "server/*", "shared/*"],
message: "Use relative import instead.",
},
],
},
],
},
},
];

View file

@ -11,10 +11,13 @@
"clean": "rimraf dist", "clean": "rimraf dist",
"crawl": "node crawl.mjs", "crawl": "node crawl.mjs",
"update-donations": "node update_donations.mjs", "update-donations": "node update_donations.mjs",
"lint": "node generate_translations.mjs && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"", "lint": "pnpm translations:generate && tsc --noEmit && pnpm eslint --report-unused-disable-directives && pnpm prettier --check \"src/**/*.{ts,tsx,js,mjs,css,scss}\"",
"prebuild:dev": "pnpm clean && node generate_translations.mjs && pnpm tailwind && pnpm generate_rss_feed", "prebuild:dev": "pnpm clean && pnpm translations:generate && pnpm tailwind && pnpm generate_rss_feed",
"prebuild:prod": "pnpm clean && node generate_translations.mjs && pnpm tailwind && pnpm generate_rss_feed", "prebuild:prod": "pnpm clean && pnpm translations:generate && pnpm tailwind && pnpm generate_rss_feed",
"generate_rss_feed": "node generate_rss_feed.mjs", "generate_rss_feed": "node generate_rss_feed.mjs",
"translations:generate": "node generate_translations.mjs",
"translations:init": "git submodule init && pnpm translations:update",
"translations:update": "git submodule update --remote --recursive",
"tailwind": "tailwindcss -i ./src/style.css -o ./dist/styles/styles.css --minify", "tailwind": "tailwindcss -i ./src/style.css -o ./dist/styles/styles.css --minify",
"prepare": "husky", "prepare": "husky",
"start": "pnpm build:dev --watch & tailwind --watch" "start": "pnpm build:dev --watch & tailwind --watch"
@ -27,7 +30,7 @@
"@babel/preset-env": "7.25.8", "@babel/preset-env": "7.25.8",
"@babel/preset-typescript": "^7.23.2", "@babel/preset-typescript": "^7.23.2",
"@babel/runtime": "^7.23.2", "@babel/runtime": "^7.23.2",
"@glidejs/glide": "3.6.2", "@glidejs/glide": "3.5.2",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"babel-loader": "^9.1.3", "babel-loader": "^9.1.3",
"babel-plugin-inferno": "^6.7.0", "babel-plugin-inferno": "^6.7.0",
@ -73,6 +76,9 @@
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"css-loader": "^7.0.0", "css-loader": "^7.0.0",
"eslint": "^9.0.0", "eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-inferno": "^7.34.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-prettier": "^5.0.1", "eslint-plugin-prettier": "^5.0.1",
"husky": "^9.0.6", "husky": "^9.0.6",
"lint-staged": "^15.0.2", "lint-staged": "^15.0.2",
@ -84,6 +90,7 @@
"style-loader": "^4.0.0", "style-loader": "^4.0.0",
"terser": "^5.24.0", "terser": "^5.24.0",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"typescript-eslint": "^8.9.0",
"webpack-dev-server": "5.1.0" "webpack-dev-server": "5.1.0"
}, },
"engines": { "engines": {

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ import { getLanguageFromCookie, i18n } from "../shared/i18next";
// If query param is set, server updates cookie automatically, // If query param is set, server updates cookie automatically,
// so no need to check the query here // so no need to check the query here
const languageCookie = getLanguageFromCookie(document.cookie); const languageCookie = getLanguageFromCookie(document.cookie);
if (languageCookie != null) { if (languageCookie !== undefined) {
i18n.changeLanguage(languageCookie); i18n.changeLanguage(languageCookie);
} else { } else {
i18n.changeLanguage(navigator.language); i18n.changeLanguage(navigator.language);

View file

@ -35,7 +35,7 @@ server.use(
server.use("/feed.xml", express.static(path.resolve("./dist/feed.xml"))); server.use("/feed.xml", express.static(path.resolve("./dist/feed.xml")));
function erudaInit(): string { function erudaInit(): string {
if (process.env["NODE_ENV"] == "development") { if (process.env["NODE_ENV"] === "development") {
return ` return `
<script src="//cdn.jsdelivr.net/npm/eruda"></script> <script src="//cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script> <script>eruda.init();</script>
@ -49,12 +49,12 @@ function setLanguage(req: Request, res: Response): string {
// Setting the language for non-js browsers // Setting the language for non-js browsers
const cookieLang = getLanguageFromCookie(req.headers.cookie); const cookieLang = getLanguageFromCookie(req.headers.cookie);
let language: string; let language: string;
if (req.query["lang"] != null) { if (req.query["lang"] !== undefined) {
language = req.query["lang"].toString(); language = req.query["lang"].toString();
res.cookie("lang", language, { res.cookie("lang", language, {
expires: new Date(Date.now() + 60 * 60 * 24 * 7), expires: new Date(Date.now() + 60 * 60 * 24 * 7),
}); });
} else if (cookieLang != null) { } else if (cookieLang !== undefined) {
language = cookieLang; language = cookieLang;
} else { } else {
language = req.headers["accept-language"] language = req.headers["accept-language"]

View file

@ -37,6 +37,7 @@ const AppDetailsTitle = ({ app }: AppDetailsCardProps) => (
<img <img
src={app.icon || "/static/assets/images/lemmy.svg"} src={app.icon || "/static/assets/images/lemmy.svg"}
className="rounded-xl w-7 h-7" className="rounded-xl w-7 h-7"
alt=""
/> />
<a href={app.link} className={`card-title text-2xl ${TEXT_GRADIENT}`}> <a href={app.link} className={`card-title text-2xl ${TEXT_GRADIENT}`}>
{app.name} {app.name}
@ -68,9 +69,10 @@ const AppDetailsCard = ({ app }: AppDetailsCardProps) => (
<img <img
src={app.banner || "/static/assets/images/lemmy.svg"} src={app.banner || "/static/assets/images/lemmy.svg"}
className="rounded-xl max-h-96 mb-2" className="rounded-xl max-h-96 mb-2"
alt=""
/> />
<p className="text-sm text-gray-300 mb-2">{app.description}</p> <p className="text-sm text-gray-300 mb-2">{app.description}</p>
{app.sourceType == SourceType.Closed && ( {app.sourceType === SourceType.Closed && (
<div className="alert alert-warning"> <div className="alert alert-warning">
<Icon icon="alert-octagon" /> <Icon icon="alert-octagon" />
<span>{i18n.t("closed_source_warning")}</span> <span>{i18n.t("closed_source_warning")}</span>
@ -209,7 +211,7 @@ export class Apps extends Component<any, State> {
} }
function handlePlatformChange(i: Apps, event: any) { function handlePlatformChange(i: Apps, event: any) {
let platform: Platform = (event.target.value as Platform) ?? Platform.All; const platform: Platform = (event.target.value as Platform) ?? Platform.All;
i.setState({ i.setState({
platform, platform,
}); });

View file

@ -39,7 +39,7 @@ const QrModal = ({ name, imgData }) => (
</button> </button>
</form> </form>
<div className="container mx-auto"> <div className="container mx-auto">
<img className="w-auto" src={imgData} /> <img className="w-auto" src={imgData} alt="" />
</div> </div>
</div> </div>
</dialog> </dialog>
@ -56,7 +56,7 @@ export class Crypto extends Component<any, State> {
} }
async componentDidMount() { async componentDidMount() {
let cryptoQr = new Map<string, string>(); const cryptoQr = new Map<string, string>();
for (const c of CRYPTOS) { for (const c of CRYPTOS) {
cryptoQr.set(c.name, await QRCode.toDataURL(c.address)); cryptoQr.set(c.name, await QRCode.toDataURL(c.address));
} }

View file

@ -149,7 +149,7 @@ const GoldSponsorCards = ({ title, sponsors, color }: GoldSponsorCardsProps) =>
<div className="flex flex-wrap flex-row justify-center"> <div className="flex flex-wrap flex-row justify-center">
{s.avatar && ( {s.avatar && (
<div className="avatar w-auto h-8"> <div className="avatar w-auto h-8">
<img src={s.avatar} className="rounded" /> <img src={s.avatar} className="rounded" alt="" />
</div> </div>
)} )}
<span className="text-xs">{s.name}</span> <span className="text-xs">{s.name}</span>
@ -268,13 +268,13 @@ export class Donate extends Component<any, any> {
} }
function convertTranslators(): Translation[] { function convertTranslators(): Translation[] {
let trans: Translation[] = []; const trans: Translation[] = [];
for (const [key, value] of Object.entries(translators)) { for (const [key, value] of Object.entries(translators)) {
let split = key.split("_"); const split = key.split("_");
let lang = split[0]; const lang = split[0];
let country = split[1] !== undefined ? split[1].toUpperCase() : undefined; const country = split[1] !== undefined ? split[1].toUpperCase() : undefined;
let t: Translation = { const t: Translation = {
lang, lang,
country, country,
translators: value, translators: value,

View file

@ -48,7 +48,7 @@ export class InstancePicker extends Component<Props, State> {
</button> </button>
</form> </form>
<div className="container mx-auto"> <div className="container mx-auto">
{this.state.activeStep == Step.Interest && ( {this.state.activeStep === Step.Interest && (
<> <>
<p className="text-2xl font-bold text-center pb-4"> <p className="text-2xl font-bold text-center pb-4">
{i18n.t("what_topic")} {i18n.t("what_topic")}
@ -67,7 +67,7 @@ export class InstancePicker extends Component<Props, State> {
</div> </div>
</> </>
)} )}
{this.state.activeStep == Step.Language && ( {this.state.activeStep === Step.Language && (
<> <>
<p className="text-2xl font-bold text-center pb-4"> <p className="text-2xl font-bold text-center pb-4">
{i18n.t("what_language")} {i18n.t("what_language")}
@ -94,21 +94,25 @@ export class InstancePicker extends Component<Props, State> {
)} )}
<ul className="steps steps-vertical lg:steps-horizontal w-full"> <ul className="steps steps-vertical lg:steps-horizontal w-full">
<li <li>
onClick={linkEvent(this, handleResetInterests)} <button
className={classNames("step text-gray-300", { onClick={linkEvent(this, handleResetInterests)}
"step-primary": this.state.activeStep == Step.Interest, className={classNames("step text-gray-300", {
})} "step-primary": this.state.activeStep === Step.Interest,
> })}
{i18n.t("interests")} >
{i18n.t("interests")}
</button>
</li> </li>
<li <li>
onClick={linkEvent(this, handleResetInterests)} <button
className={classNames("step text-gray-300", { onClick={linkEvent(this, handleResetInterests)}
"step-primary": this.state.activeStep == Step.Language, className={classNames("step text-gray-300", {
})} "step-primary": this.state.activeStep === Step.Language,
> })}
{i18n.t("languages")} >
{i18n.t("languages")}
</button>
</li> </li>
</ul> </ul>
</div> </div>
@ -120,7 +124,7 @@ export class InstancePicker extends Component<Props, State> {
function handleTopicChange(i: InstancePicker, event: any) { function handleTopicChange(i: InstancePicker, event: any) {
i.setState({ i.setState({
topic: TOPICS.find(c => c.name == event.target.value) ?? ALL_TOPIC, topic: TOPICS.find(c => c.name === event.target.value) ?? ALL_TOPIC,
activeStep: Step.Language, activeStep: Step.Language,
}); });
} }

View file

@ -194,7 +194,7 @@ const imgError =
const InstanceIcon = ({ domain, icon }) => ( const InstanceIcon = ({ domain, icon }) => (
<a className="rounded-xl bg-neutral-800 p-4" href={buildUrl(domain)}> <a className="rounded-xl bg-neutral-800 p-4" href={buildUrl(domain)}>
<img className="w-24 h-24" src={icon} onError={imgError} /> <img className="w-24 h-24" src={icon} onError={imgError} alt="" />
</a> </a>
); );
@ -257,11 +257,11 @@ export const StatsBadges = ({ users, comments, monthlyUsers }) => (
); );
function registrationModeToString(registrationMode: string): string { function registrationModeToString(registrationMode: string): string {
if (registrationMode == "Open") { if (registrationMode === "Open") {
return i18n.t("registrations_open"); return i18n.t("registrations_open");
} else if (registrationMode == "Closed") { } else if (registrationMode === "Closed") {
return i18n.t("registrations_closed"); return i18n.t("registrations_closed");
} else if (registrationMode == "RequireApplication") { } else if (registrationMode === "RequireApplication") {
return i18n.t("requires_application"); return i18n.t("requires_application");
} else { } else {
return i18n.t("registrations_open"); return i18n.t("registrations_open");
@ -293,10 +293,13 @@ export const DetailsModal = ({
<img <img
src={banner} src={banner}
className="object-cover w-full h-48 rounded-xl mb-3" className="object-cover w-full h-48 rounded-xl mb-3"
alt=""
/> />
)} )}
<div className="flex flex-row flex-wrap gap-4 mb-3 items-center"> <div className="flex flex-row flex-wrap gap-4 mb-3 items-center">
{icon && <img className="w-8 h-8" src={icon} onError={imgError} />} {icon && (
<img className="w-8 h-8" src={icon} onError={imgError} alt="" />
)}
<StatsBadges <StatsBadges
users={users} users={users}
comments={comments} comments={comments}
@ -375,11 +378,11 @@ interface Props {
} }
function getSortFromQuery(sort?: string): Sort { function getSortFromQuery(sort?: string): Sort {
return SORTS.find(s => s.name == sort) ?? RANDOM_SORT; return SORTS.find(s => s.name === sort) ?? RANDOM_SORT;
} }
function getTopicFromQuery(topic?: string): Topic { function getTopicFromQuery(topic?: string): Topic {
return TOPICS.find(c => c.name == topic) ?? ALL_TOPIC; return TOPICS.find(c => c.name === topic) ?? ALL_TOPIC;
} }
function getInstancesQueryParams() { function getInstancesQueryParams() {
@ -459,9 +462,9 @@ export class Instances extends Component<Props, State> {
instances = instances.filter(i => !this.isOpenInstance(i)); instances = instances.filter(i => !this.isOpenInstance(i));
// Sort // Sort
if (this.state.sort == RANDOM_SORT) { if (this.state.sort === RANDOM_SORT) {
instances = sortRandom(instances); instances = sortRandom(instances);
} else if (this.state.sort == MOST_ACTIVE_SORT) { } else if (this.state.sort === MOST_ACTIVE_SORT) {
instances = sortActive(instances); instances = sortActive(instances);
} else { } else {
instances = sortActive(instances).reverse(); instances = sortActive(instances).reverse();
@ -570,14 +573,14 @@ export class Instances extends Component<Props, State> {
function handleSortChange(i: Instances, event: any) { function handleSortChange(i: Instances, event: any) {
i.setState({ i.setState({
sort: SORTS.find(s => s.name == event.target.value) ?? RANDOM_SORT, sort: SORTS.find(s => s.name === event.target.value) ?? RANDOM_SORT,
}); });
i.buildInstanceList(); i.buildInstanceList();
} }
function handleTopicChange(i: Instances, event: any) { function handleTopicChange(i: Instances, event: any) {
i.setState({ i.setState({
topic: TOPICS.find(c => c.name == event.target.value) ?? ALL_TOPIC, topic: TOPICS.find(c => c.name === event.target.value) ?? ALL_TOPIC,
}); });
i.buildInstanceList(); i.buildInstanceList();
} }

View file

@ -50,6 +50,7 @@ const CarouselBlock = () => (
"border-primary/[.15]": i & 1, "border-primary/[.15]": i & 1,
"border-secondary/[.15]": !(i & 1), "border-secondary/[.15]": !(i & 1),
})} })}
alt=""
/> />
))} ))}
</ul> </ul>
@ -116,7 +117,11 @@ const FollowCommunitiesBlock = ({ i }: MainProps) => (
const FeatureCard = ({ pic, title, subtitle, classes }) => ( const FeatureCard = ({ pic, title, subtitle, classes }) => (
<div className={`card ${CARD_GRADIENT} shadow-xl ${classes}`}> <div className={`card ${CARD_GRADIENT} shadow-xl ${classes}`}>
<div className="p-4"> <div className="p-4">
<img src={pic} className="rounded-xl w-full object-fill min-h-[300px]" /> <img
src={pic}
className="rounded-xl w-full object-fill min-h-[300px]"
alt=""
/>
</div> </div>
<div className="card-body pt-0"> <div className="card-body pt-0">
<h2 className="card-title text-secondary">{title}</h2> <h2 className="card-title text-secondary">{title}</h2>
@ -500,6 +505,7 @@ export class Main extends Component<Props, State> {
<img <img
src="/static/assets/images/world_background.svg" src="/static/assets/images/world_background.svg"
className="bg-top bg-no-repeat bg-contain opacity-20 absolute" className="bg-top bg-no-repeat bg-contain opacity-20 absolute"
alt=""
/> />
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">
<TitleBlock i={this} /> <TitleBlock i={this} />

View file

@ -72,7 +72,11 @@ export const Navbar = ({ footer = false }) => (
> >
<div className="navbar-start"> <div className="navbar-start">
<Link className="btn btn-ghost normal-case text-xl" to="/"> <Link className="btn btn-ghost normal-case text-xl" to="/">
<img src="/static/assets/images/lemmy.svg" className="h-12 w-12" /> <img
src="/static/assets/images/lemmy.svg"
className="h-12 w-12"
alt=""
/>
</Link> </Link>
</div> </div>
<div className="navbar-center hidden lg:flex"> <div className="navbar-center hidden lg:flex">
@ -111,13 +115,10 @@ export const Navbar = ({ footer = false }) => (
"dropdown-top": footer, "dropdown-top": footer,
})} })}
> >
<label tabIndex={0} className="btn btn-ghost lg:hidden"> <label className="btn btn-ghost lg:hidden">
<Icon icon="align-right" size={IconSize.Large} /> <Icon icon="align-right" size={IconSize.Large} />
</label> </label>
<ul <ul className="menu menu-sm dropdown-content z-[1] p-2 shadow bg-neutral-800 rounded-box w-52 items-center mt-3 ">
tabIndex={0}
className="menu menu-sm dropdown-content z-[1] p-2 shadow bg-neutral-800 rounded-box w-52 items-center mt-3 "
>
<NavLinks /> <NavLinks />
</ul> </ul>
</div> </div>

View file

@ -22,7 +22,7 @@ export class NewsItem extends Component<any, any> {
} }
get markdown(): string { get markdown(): string {
return news_md.find(v => v.title == this.title)?.markdown ?? ""; return news_md.find(v => v.title === this.title)?.markdown ?? "";
} }
render() { render() {

View file

@ -18,7 +18,7 @@ interface NewsInfo {
function buildNewsInfoArray(): Array<NewsInfo> { function buildNewsInfoArray(): Array<NewsInfo> {
return news_reversed.map(n => { return news_reversed.map(n => {
let split = n.title.split(" - "); const split = n.title.split(" - ");
return { return {
dateStr: split[0], dateStr: split[0],
@ -48,7 +48,11 @@ const TitleBlock = () => (
<div className="pt-16 text-center text-4xl font-bold mb-8"> <div className="pt-16 text-center text-4xl font-bold mb-8">
{title} {title}
<a href="/feed.xml" className="ml-4 inline-block"> <a href="/feed.xml" className="ml-4 inline-block">
<img src="/static/assets/images/rss.svg" width={24} /> <img
src="/static/assets/images/rss.svg"
width={24}
alt={i18n.t("rss_feeds")}
/>
</a> </a>
</div> </div>
); );

View file

@ -72,17 +72,11 @@ export const i18n = i18next as i18nTyped;
export { resources }; export { resources };
// https://gist.github.com/hunan-rostomyan/28e8702c1cecff41f7fe64345b76f2ca // https://gist.github.com/hunan-rostomyan/28e8702c1cecff41f7fe64345b76f2ca
export function getLanguageFromCookie(cookies?: string): string | null { export function getLanguageFromCookie(cookies?: string): string | undefined {
if (cookies == null) {
return null;
}
const key = "lang="; const key = "lang=";
return ( return cookies
cookies ?.split(";")
.split(";") .map(c => c.trim())
.map(c => c.trim()) .filter(cookie => cookie.substring(0, key.length) === key)
.filter(cookie => cookie.substring(0, key.length) === key) .map(cookie => cookie.substring(key.length))[0];
.map(cookie => cookie.substring(key.length))[0] || null
);
} }

View file

@ -6,7 +6,7 @@ import markdown_it_ruby from "markdown-it-ruby";
import markdown_it_sub from "markdown-it-sub"; import markdown_it_sub from "markdown-it-sub";
import markdown_it_sup from "markdown-it-sup"; import markdown_it_sup from "markdown-it-sup";
let SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", { const SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", {
maximumFractionDigits: 1, maximumFractionDigits: 1,
//@ts-ignore //@ts-ignore
notation: "compact", notation: "compact",