From 3ca24607fbf5c08f83243fc259dcd159bb0a24f2 Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Sat, 17 Jun 2023 09:37:03 +0100 Subject: [PATCH 01/31] add hours as sorting options --- src/shared/components/common/sort-select.tsx | 3 +++ src/shared/utils.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/shared/components/common/sort-select.tsx b/src/shared/components/common/sort-select.tsx index dac6e20d..1fd32076 100644 --- a/src/shared/components/common/sort-select.tsx +++ b/src/shared/components/common/sort-select.tsx @@ -66,6 +66,9 @@ export class SortSelect extends Component { + + + diff --git a/src/shared/utils.ts b/src/shared/utils.ts index c7fbca6b..abb30629 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -986,6 +986,9 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { export function convertCommentSortType(sort: SortType): CommentSortType { if ( sort == "TopAll" || + sort == "TopHour" || + sort == "TopSixHour" || + sort == "TopTwelveHour" || sort == "TopDay" || sort == "TopWeek" || sort == "TopMonth" || From 5e9a414dfcbde436d803953871bbe3ada464d90a Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Sun, 18 Jun 2023 00:51:32 +0100 Subject: [PATCH 02/31] clean code --- src/shared/utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/utils.ts b/src/shared/utils.ts index abb30629..86a32d16 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -986,9 +986,9 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { export function convertCommentSortType(sort: SortType): CommentSortType { if ( sort == "TopAll" || - sort == "TopHour" || - sort == "TopSixHour" || - sort == "TopTwelveHour" || + sort == "TopHour" || + sort == "TopSixHour" || + sort == "TopTwelveHour" || sort == "TopDay" || sort == "TopWeek" || sort == "TopMonth" || From 747bc943a966d45bb2547287a630f1714991e860 Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Wed, 21 Jun 2023 01:21:14 +0100 Subject: [PATCH 03/31] refactor if into switch case --- src/shared/utils.ts | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/shared/utils.ts b/src/shared/utils.ts index be7b11b0..d6946cce 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -853,24 +853,28 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { } export function convertCommentSortType(sort: SortType): CommentSortType { - if ( - sort == "TopAll" || - sort == "TopHour" || - sort == "TopSixHour" || - sort == "TopTwelveHour" || - sort == "TopDay" || - sort == "TopWeek" || - sort == "TopMonth" || - sort == "TopYear" - ) { - return "Top"; - } else if (sort == "New") { - return "New"; - } else if (sort == "Hot" || sort == "Active") { - return "Hot"; - } else { - return "Hot"; - } + switch(sort) { + case "TopAll": + case "TopHour": + case "TopSixHour": + case "TopTwelveHour": + case "TopDay": + case "TopWeek": + case "TopMonth": + case "TopYear": { + return "Top"; + } + case "New": { + return "New"; + } + case "Hot": + case "Active": { + return "Hot"; + } + default: { + return "Hot"; + } + } } export function buildCommentsTree( From 92482cbe6b1003d4c89ba12b628f163483752acb Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 00:48:09 -0300 Subject: [PATCH 07/31] Add local community link parser plugin for Markdown-It --- src/shared/markdown.ts | 75 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 8f4d5c23..c837dba6 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -14,6 +14,7 @@ import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; +import { getHttpBase } from "./env"; export let Tribute: any; @@ -72,6 +73,76 @@ const html5EmbedConfig = { }, }; +function localCommunityLinkParser(md) { + const pattern = + /(!\b[^@\s]+@[^@\s]+\.[^.\s]+\b)|\/c\/([^@\s]+)(@[^@\s]+\.[^.\s]+\b)?/g; + + md.core.ruler.push("replace-text", state => { + const tokens = state.tokens; + + for (let i = 0; i < tokens.length; i++) { + if (tokens[i].type === "inline") { + const token = tokens[i]; + + const originalContent = token.content; + + let lastIndex = 0; + originalContent.replace( + pattern, + (match, fullDomainMatch, name, domainTld, index) => { + let url; + // ex: !Testing@example.com + if (fullDomainMatch) { + const [name, domain, tld] = fullDomainMatch + .slice(1) + .split("@") + .join(".") + .split("."); + url = `${getHttpBase()}/c/${name}@${domain}.${tld}`; + } else { + // ex: /c/Testing or /c/Testing@example.com + url = `${getHttpBase()}/c/${name}${domainTld || ""}`; + } + + const beforeContent = originalContent.slice(lastIndex, index); + lastIndex = index + match.length; + + const beforeToken = new state.Token("text", "", 0); + beforeToken.content = beforeContent; + + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [["href", url]]; + + const textToken = new state.Token("text", "", 0); + textToken.content = match; + + const linkCloseToken = new state.Token("link_close", "a", -1); + + const afterContent = originalContent.slice(lastIndex); + const afterToken = new state.Token("text", "", 0); + afterToken.content = afterContent; + + tokens.splice(i, 1); + + tokens.splice( + i, + 0, + beforeToken, + linkOpenToken, + textToken, + linkCloseToken, + afterToken + ); + + // Update i to skip the newly added tokens + i += 4; + } + ); + } + } + }); +} + export function setupMarkdown() { const markdownItConfig: MarkdownIt.Options = { html: false, @@ -88,7 +159,8 @@ export function setupMarkdown() { .use(markdown_it_sup) .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) - .use(markdown_it_container, "spoiler", spoilerConfig); + .use(markdown_it_container, "spoiler", spoilerConfig) + .use(localCommunityLinkParser); // .use(markdown_it_emoji, { // defs: emojiDefs, // }); @@ -99,6 +171,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) + .use(localCommunityLinkParser) // .use(markdown_it_emoji, { // defs: emojiDefs, // }) From c06d38633766f466d8b744aa44c7418765ad57de Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Thu, 22 Jun 2023 04:52:04 +0100 Subject: [PATCH 08/31] prettier --- src/shared/components/common/sort-select.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shared/components/common/sort-select.tsx b/src/shared/components/common/sort-select.tsx index 33c5c85f..4d03ab5d 100644 --- a/src/shared/components/common/sort-select.tsx +++ b/src/shared/components/common/sort-select.tsx @@ -68,11 +68,17 @@ export class SortSelect extends Component { ───── - - + + - + From 02717be15c7aa94f6ef5e6fd1ecb97ac61d85ad6 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 01:07:33 -0300 Subject: [PATCH 09/31] Add community link class --- src/shared/markdown.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index c837dba6..6e6b504f 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -111,7 +111,10 @@ function localCommunityLinkParser(md) { beforeToken.content = beforeContent; const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [["href", url]]; + linkOpenToken.attrs = [ + ["href", url], + ["class", "community-link"], + ]; const textToken = new state.Token("text", "", 0); textToken.content = match; From 9fc3da0264cb7b7acc9ead19791bedb0dc567964 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 07:42:57 -0400 Subject: [PATCH 10/31] Fix grave `ReferenceError: fetch is not defined` error (#1460) * use cross-fetch * remove from utils usage --- src/server/handlers/catch-all-handler.tsx | 1 + src/server/handlers/manifest-handler.ts | 1 + src/server/utils/fetch-icon-png.ts | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/server/handlers/catch-all-handler.tsx b/src/server/handlers/catch-all-handler.tsx index b9ff13bf..efadee42 100644 --- a/src/server/handlers/catch-all-handler.tsx +++ b/src/server/handlers/catch-all-handler.tsx @@ -1,5 +1,6 @@ import { initializeSite, isAuthPath } from "@utils/app"; import { ErrorPageData } from "@utils/types"; +import fetch from "cross-fetch"; import type { Request, Response } from "express"; import { StaticRouter, matchPath } from "inferno-router"; import { renderToString } from "inferno-server"; diff --git a/src/server/handlers/manifest-handler.ts b/src/server/handlers/manifest-handler.ts index 6858cffd..b9a11089 100644 --- a/src/server/handlers/manifest-handler.ts +++ b/src/server/handlers/manifest-handler.ts @@ -1,3 +1,4 @@ +import fetch from "cross-fetch"; import type { Request, Response } from "express"; import { LemmyHttp } from "lemmy-js-client"; import { getHttpBaseExternal, getHttpBaseInternal } from "../../shared/env"; diff --git a/src/server/utils/fetch-icon-png.ts b/src/server/utils/fetch-icon-png.ts index 12b09e70..75497a21 100644 --- a/src/server/utils/fetch-icon-png.ts +++ b/src/server/utils/fetch-icon-png.ts @@ -1,3 +1,5 @@ +import fetch from "cross-fetch"; + export async function fetchIconPng(iconUrl: string) { return await fetch(iconUrl) .then(res => res.blob()) From 902930bb9ddd8ba35a057830b62997443115d2f2 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 22 Jun 2023 08:52:52 -0400 Subject: [PATCH 11/31] v0.18.0-rc.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1055d853..9e7a0f1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lemmy-ui", - "version": "0.18.0-rc.5", + "version": "0.18.0-rc.6", "description": "An isomorphic UI for lemmy", "repository": "https://github.com/LemmyNet/lemmy-ui", "license": "AGPL-3.0", From 0247f8a2cfa665d2ec96bbaa53cf9ed0f0c2ce9c Mon Sep 17 00:00:00 2001 From: Scott <97430840+scme0@users.noreply.github.com> Date: Thu, 22 Jun 2023 22:25:11 +0930 Subject: [PATCH 12/31] Fix buildThemeList() function to ensure no duplicates (#1466) Co-authored-by: Dessalines --- src/server/utils/build-themes-list.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/server/utils/build-themes-list.ts b/src/server/utils/build-themes-list.ts index 73dc53bc..74b910c7 100644 --- a/src/server/utils/build-themes-list.ts +++ b/src/server/utils/build-themes-list.ts @@ -4,15 +4,20 @@ import { readdir } from "fs/promises"; const extraThemesFolder = process.env["LEMMY_UI_EXTRA_THEMES_FOLDER"] || "./extra_themes"; -const themes = ["darkly", "darkly-red", "litely", "litely-red"]; +const themes: ReadonlyArray = [ + "darkly", + "darkly-red", + "litely", + "litely-red", +]; -export async function buildThemeList(): Promise { +export async function buildThemeList(): Promise> { if (existsSync(extraThemesFolder)) { const dirThemes = await readdir(extraThemesFolder); const cssThemes = dirThemes .filter(d => d.endsWith(".css")) .map(d => d.replace(".css", "")); - themes.push(...cssThemes); + return themes.concat(cssThemes); } return themes; } From 98cedb883297d4eab74c35a3cfde7f6c92f36f38 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:58:51 -0400 Subject: [PATCH 13/31] fix capitalization (#1467) Co-authored-by: Dessalines --- src/shared/components/post/post-listing.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index bbc02892..b9ad5ebc 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -1,6 +1,11 @@ import { myAuthRequired, newVote, showScores } from "@utils/app"; import { canShare, share } from "@utils/browser"; -import { futureDaysToUnixTime, hostname, numToSI } from "@utils/helpers"; +import { + capitalizeFirstLetter, + futureDaysToUnixTime, + hostname, + numToSI, +} from "@utils/helpers"; import { isImage, isVideo } from "@utils/media"; import { amAdmin, @@ -981,7 +986,7 @@ export class PostListing extends Component { classes={classNames("me-1", { "text-danger": locked })} inline /> - {label} + {capitalizeFirstLetter(label)} )} From fc40b473d734733a34b8d832b9c343a401e390e0 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 09:02:48 -0400 Subject: [PATCH 14/31] move env utils into folder --- src/server/handlers/catch-all-handler.tsx | 2 +- src/server/handlers/manifest-handler.ts | 2 +- src/server/utils/generate-manifest-json.ts | 2 +- src/shared/components/common/html-tags.tsx | 2 +- src/shared/components/post/post-listing.tsx | 2 +- src/shared/config.ts | 2 + src/shared/env.ts | 66 ------------------- src/shared/services/HttpService.ts | 2 +- src/shared/services/UserService.ts | 2 +- src/shared/utils/env/get-base-local.ts | 5 ++ src/shared/utils/env/get-external-host.ts | 14 ++++ src/shared/utils/env/get-host.ts | 6 ++ .../utils/env/get-http-base-external.ts | 5 ++ .../utils/env/get-http-base-internal.ts | 5 ++ src/shared/utils/env/get-http-base.ts | 5 ++ src/shared/utils/env/get-internal-host.ts | 8 +++ src/shared/utils/env/get-secure.ts | 11 ++++ src/shared/utils/env/http-external-path.ts | 9 +++ src/shared/utils/env/index.ts | 23 +++++++ src/shared/utils/env/is-https.ts | 5 ++ 20 files changed, 105 insertions(+), 73 deletions(-) delete mode 100644 src/shared/env.ts create mode 100644 src/shared/utils/env/get-base-local.ts create mode 100644 src/shared/utils/env/get-external-host.ts create mode 100644 src/shared/utils/env/get-host.ts create mode 100644 src/shared/utils/env/get-http-base-external.ts create mode 100644 src/shared/utils/env/get-http-base-internal.ts create mode 100644 src/shared/utils/env/get-http-base.ts create mode 100644 src/shared/utils/env/get-internal-host.ts create mode 100644 src/shared/utils/env/get-secure.ts create mode 100644 src/shared/utils/env/http-external-path.ts create mode 100644 src/shared/utils/env/index.ts create mode 100644 src/shared/utils/env/is-https.ts diff --git a/src/server/handlers/catch-all-handler.tsx b/src/server/handlers/catch-all-handler.tsx index b9ff13bf..e57f079d 100644 --- a/src/server/handlers/catch-all-handler.tsx +++ b/src/server/handlers/catch-all-handler.tsx @@ -1,4 +1,5 @@ import { initializeSite, isAuthPath } from "@utils/app"; +import { getHttpBaseInternal } from "@utils/env"; import { ErrorPageData } from "@utils/types"; import type { Request, Response } from "express"; import { StaticRouter, matchPath } from "inferno-router"; @@ -6,7 +7,6 @@ import { renderToString } from "inferno-server"; import IsomorphicCookie from "isomorphic-cookie"; import { GetSite, GetSiteResponse, LemmyHttp } from "lemmy-js-client"; import { App } from "../../shared/components/app/app"; -import { getHttpBaseInternal } from "../../shared/env"; import { InitialFetchRequest, IsoDataOptionalSite, diff --git a/src/server/handlers/manifest-handler.ts b/src/server/handlers/manifest-handler.ts index 6858cffd..014e0348 100644 --- a/src/server/handlers/manifest-handler.ts +++ b/src/server/handlers/manifest-handler.ts @@ -1,6 +1,6 @@ +import { getHttpBaseExternal, getHttpBaseInternal } from "@utils/env"; import type { Request, Response } from "express"; import { LemmyHttp } from "lemmy-js-client"; -import { getHttpBaseExternal, getHttpBaseInternal } from "../../shared/env"; import { wrapClient } from "../../shared/services/HttpService"; import generateManifestJson from "../utils/generate-manifest-json"; import { setForwardedHeaders } from "../utils/set-forwarded-headers"; diff --git a/src/server/utils/generate-manifest-json.ts b/src/server/utils/generate-manifest-json.ts index b03fd87b..2f9d8b80 100644 --- a/src/server/utils/generate-manifest-json.ts +++ b/src/server/utils/generate-manifest-json.ts @@ -1,8 +1,8 @@ +import { getHttpBaseExternal } from "@utils/env"; import { readFile } from "fs/promises"; import { GetSiteResponse } from "lemmy-js-client"; import path from "path"; import sharp from "sharp"; -import { getHttpBaseExternal } from "../../shared/env"; import { fetchIconPng } from "./fetch-icon-png"; const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512]; diff --git a/src/shared/components/common/html-tags.tsx b/src/shared/components/common/html-tags.tsx index 3a8b270a..5d532589 100644 --- a/src/shared/components/common/html-tags.tsx +++ b/src/shared/components/common/html-tags.tsx @@ -1,7 +1,7 @@ +import { httpExternalPath } from "@utils/env"; import { htmlToText } from "html-to-text"; import { Component } from "inferno"; import { Helmet } from "inferno-helmet"; -import { httpExternalPath } from "../../env"; import { md } from "../../markdown"; import { I18NextService } from "../../services"; diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index bbc02892..8e4d7303 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -1,5 +1,6 @@ import { myAuthRequired, newVote, showScores } from "@utils/app"; import { canShare, share } from "@utils/browser"; +import { getExternalHost, getHttpBase } from "@utils/env"; import { futureDaysToUnixTime, hostname, numToSI } from "@utils/helpers"; import { isImage, isVideo } from "@utils/media"; import { @@ -38,7 +39,6 @@ import { TransferCommunity, } from "lemmy-js-client"; import { relTags } from "../../config"; -import { getExternalHost, getHttpBase } from "../../env"; import { BanType, PostFormParams, PurgeType, VoteType } from "../../interfaces"; import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown"; import { I18NextService, UserService } from "../../services"; diff --git a/src/shared/config.ts b/src/shared/config.ts index 384e86c3..28e8ce51 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -24,3 +24,5 @@ export const updateUnreadCountsInterval = 30000; export const fetchLimit = 40; export const relTags = "noopener nofollow"; export const emDash = "\u2014"; + +export const testHost = "0.0.0.0:8536"; diff --git a/src/shared/env.ts b/src/shared/env.ts deleted file mode 100644 index 287912d1..00000000 --- a/src/shared/env.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { isBrowser } from "@utils/browser"; - -const testHost = "0.0.0.0:8536"; - -function getInternalHost() { - return !isBrowser() - ? process.env.LEMMY_UI_LEMMY_INTERNAL_HOST ?? testHost - : testHost; // used for local dev -} - -export function getExternalHost() { - return isBrowser() - ? `${window.location.hostname}${ - ["1234", "1235"].includes(window.location.port) - ? ":8536" - : window.location.port == "" - ? "" - : `:${window.location.port}` - }` - : process.env.LEMMY_UI_LEMMY_EXTERNAL_HOST || testHost; -} - -function getSecure() { - return ( - isBrowser() - ? window.location.protocol.includes("https") - : process.env.LEMMY_UI_HTTPS === "true" - ) - ? "s" - : ""; -} - -function getHost() { - return isBrowser() ? getExternalHost() : getInternalHost(); -} - -function getBaseLocal(s = "") { - return `http${s}://${getHost()}`; -} - -export function getHttpBaseInternal() { - return getBaseLocal(); // Don't use secure here -} - -export function getHttpBaseExternal() { - return `http${getSecure()}://${getExternalHost()}`; -} - -export function getHttpBase() { - return getBaseLocal(getSecure()); -} - -export function isHttps() { - return getSecure() === "s"; -} - -console.log(`httpbase: ${getHttpBase()}`); -console.log(`isHttps: ${isHttps()}`); - -// This is for html tags, don't include port -export function httpExternalPath(path: string) { - return `http${getSecure()}://${getExternalHost().replace( - /:\d+/g, - "" - )}${path}`; -} diff --git a/src/shared/services/HttpService.ts b/src/shared/services/HttpService.ts index 6f57ecb5..361ffbd3 100644 --- a/src/shared/services/HttpService.ts +++ b/src/shared/services/HttpService.ts @@ -1,5 +1,5 @@ +import { getHttpBase } from "@utils/env"; import { LemmyHttp } from "lemmy-js-client"; -import { getHttpBase } from "../../shared/env"; import { toast } from "../../shared/toast"; import { I18NextService } from "./I18NextService"; diff --git a/src/shared/services/UserService.ts b/src/shared/services/UserService.ts index df4f00a8..3d08e124 100644 --- a/src/shared/services/UserService.ts +++ b/src/shared/services/UserService.ts @@ -1,10 +1,10 @@ // import Cookies from 'js-cookie'; import { isAuthPath } from "@utils/app"; import { isBrowser } from "@utils/browser"; +import { isHttps } from "@utils/env"; import IsomorphicCookie from "isomorphic-cookie"; import jwt_decode from "jwt-decode"; import { LoginResponse, MyUserInfo } from "lemmy-js-client"; -import { isHttps } from "../env"; import { toast } from "../toast"; import { I18NextService } from "./I18NextService"; diff --git a/src/shared/utils/env/get-base-local.ts b/src/shared/utils/env/get-base-local.ts new file mode 100644 index 00000000..754d66d3 --- /dev/null +++ b/src/shared/utils/env/get-base-local.ts @@ -0,0 +1,5 @@ +import { getHost } from "@utils/env"; + +export default function getBaseLocal(s = "") { + return `http${s}://${getHost()}`; +} diff --git a/src/shared/utils/env/get-external-host.ts b/src/shared/utils/env/get-external-host.ts new file mode 100644 index 00000000..7e2635d8 --- /dev/null +++ b/src/shared/utils/env/get-external-host.ts @@ -0,0 +1,14 @@ +import { isBrowser } from "@utils/browser"; +import { testHost } from "../../config"; + +export default function getExternalHost() { + return isBrowser() + ? `${window.location.hostname}${ + ["1234", "1235"].includes(window.location.port) + ? ":8536" + : window.location.port == "" + ? "" + : `:${window.location.port}` + }` + : process.env.LEMMY_UI_LEMMY_EXTERNAL_HOST || testHost; +} diff --git a/src/shared/utils/env/get-host.ts b/src/shared/utils/env/get-host.ts new file mode 100644 index 00000000..0e361ac3 --- /dev/null +++ b/src/shared/utils/env/get-host.ts @@ -0,0 +1,6 @@ +import { isBrowser } from "@utils/browser"; +import { getExternalHost, getInternalHost } from "@utils/env"; + +export default function getHost() { + return isBrowser() ? getExternalHost() : getInternalHost(); +} diff --git a/src/shared/utils/env/get-http-base-external.ts b/src/shared/utils/env/get-http-base-external.ts new file mode 100644 index 00000000..c0ee3bb3 --- /dev/null +++ b/src/shared/utils/env/get-http-base-external.ts @@ -0,0 +1,5 @@ +import { getExternalHost, getSecure } from "@utils/env"; + +export default function getHttpBaseExternal() { + return `http${getSecure()}://${getExternalHost()}`; +} diff --git a/src/shared/utils/env/get-http-base-internal.ts b/src/shared/utils/env/get-http-base-internal.ts new file mode 100644 index 00000000..e30c14c2 --- /dev/null +++ b/src/shared/utils/env/get-http-base-internal.ts @@ -0,0 +1,5 @@ +import { getBaseLocal } from "@utils/env"; + +export default function getHttpBaseInternal() { + return getBaseLocal(); // Don't use secure here +} diff --git a/src/shared/utils/env/get-http-base.ts b/src/shared/utils/env/get-http-base.ts new file mode 100644 index 00000000..97fa0578 --- /dev/null +++ b/src/shared/utils/env/get-http-base.ts @@ -0,0 +1,5 @@ +import { getBaseLocal, getSecure } from "@utils/env"; + +export default function getHttpBase() { + return getBaseLocal(getSecure()); +} diff --git a/src/shared/utils/env/get-internal-host.ts b/src/shared/utils/env/get-internal-host.ts new file mode 100644 index 00000000..ee8fdbd3 --- /dev/null +++ b/src/shared/utils/env/get-internal-host.ts @@ -0,0 +1,8 @@ +import { isBrowser } from "@utils/browser"; +import { testHost } from "../../config"; + +export default function getInternalHost() { + return !isBrowser() + ? process.env.LEMMY_UI_LEMMY_INTERNAL_HOST ?? testHost + : testHost; // used for local dev +} diff --git a/src/shared/utils/env/get-secure.ts b/src/shared/utils/env/get-secure.ts new file mode 100644 index 00000000..7e78b4f5 --- /dev/null +++ b/src/shared/utils/env/get-secure.ts @@ -0,0 +1,11 @@ +import { isBrowser } from "@utils/browser"; + +export default function getSecure() { + return ( + isBrowser() + ? window.location.protocol.includes("https") + : process.env.LEMMY_UI_HTTPS === "true" + ) + ? "s" + : ""; +} diff --git a/src/shared/utils/env/http-external-path.ts b/src/shared/utils/env/http-external-path.ts new file mode 100644 index 00000000..f24ccace --- /dev/null +++ b/src/shared/utils/env/http-external-path.ts @@ -0,0 +1,9 @@ +import { getExternalHost, getSecure } from "@utils/env"; + +// This is for html tags, don't include port +export default function httpExternalPath(path: string) { + return `http${getSecure()}://${getExternalHost().replace( + /:\d+/g, + "" + )}${path}`; +} diff --git a/src/shared/utils/env/index.ts b/src/shared/utils/env/index.ts new file mode 100644 index 00000000..e14c6735 --- /dev/null +++ b/src/shared/utils/env/index.ts @@ -0,0 +1,23 @@ +import getBaseLocal from "./get-base-local"; +import getExternalHost from "./get-external-host"; +import getHost from "./get-host"; +import getHttpBase from "./get-http-base"; +import getHttpBaseExternal from "./get-http-base-external"; +import getHttpBaseInternal from "./get-http-base-internal"; +import getInternalHost from "./get-internal-host"; +import getSecure from "./get-secure"; +import httpExternalPath from "./http-external-path"; +import isHttps from "./is-https"; + +export { + getBaseLocal, + getExternalHost, + getHost, + getHttpBase, + getHttpBaseExternal, + getHttpBaseInternal, + getInternalHost, + getSecure, + httpExternalPath, + isHttps, +}; diff --git a/src/shared/utils/env/is-https.ts b/src/shared/utils/env/is-https.ts new file mode 100644 index 00000000..dd907570 --- /dev/null +++ b/src/shared/utils/env/is-https.ts @@ -0,0 +1,5 @@ +import { getSecure } from "@utils/env"; + +export default function isHttps() { + return getSecure() === "s"; +} From 5512ee205ad1b6ee40b99c66af3472db5acc019e Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:32:39 -0400 Subject: [PATCH 15/31] add fallback style tag --- src/server/utils/create-ssr-html.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index ae766b3a..a7a87ac9 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -8,6 +8,8 @@ import { fetchIconPng } from "./fetch-icon-png"; const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || ""; +const fallbackStyleTag = ``; + let appleTouchIcon: string | undefined = undefined; export async function createSsrHtml( @@ -85,7 +87,7 @@ export async function createSsrHtml( - ${helmet.link.toString()} + ${helmet.link.toString() || fallbackStyleTag} From a1d935991b04e491eab392e2115bda3c3442e830 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:43:03 -0400 Subject: [PATCH 16/31] rethink it a bit --- src/server/utils/create-ssr-html.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index a7a87ac9..39725fa5 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -4,12 +4,11 @@ import serialize from "serialize-javascript"; import sharp from "sharp"; import { favIconPngUrl, favIconUrl } from "../../shared/config"; import { ILemmyConfig, IsoDataOptionalSite } from "../../shared/interfaces"; +import { buildThemeList } from "./build-themes-list"; import { fetchIconPng } from "./fetch-icon-png"; const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || ""; -const fallbackStyleTag = ``; - let appleTouchIcon: string | undefined = undefined; export async function createSsrHtml( @@ -18,6 +17,10 @@ export async function createSsrHtml( ) { const site = isoData.site_res; + const fallbackTheme = ``; + if (!appleTouchIcon) { appleTouchIcon = site?.site_view.site.icon ? `data:image/png;base64,${sharp( @@ -87,7 +90,7 @@ export async function createSsrHtml( - ${helmet.link.toString() || fallbackStyleTag} + ${helmet.link.toString() || fallbackTheme} From 63b14accec80de9e440266f3e7d92235a85f24dd Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:22:36 -0400 Subject: [PATCH 17/31] rethink it a bit --- src/shared/components/community/community.tsx | 6 ------ src/shared/components/home/home.tsx | 6 ------ src/shared/utils/browser/restore-scroll-position.ts | 1 + src/shared/utils/browser/save-scroll-position.ts | 1 + 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 7eefe0eb..111b47cd 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -15,7 +15,6 @@ import { updateCommunityBlock, updatePersonBlock, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -229,10 +228,6 @@ export class Community extends Component< setupTippy(); } - componentWillUnmount() { - saveScrollPosition(this.context); - } - static async fetchInitialData({ client, path, @@ -609,7 +604,6 @@ export class Community extends Component< }); } - restoreScrollPosition(this.context); setupTippy(); } diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 0d91bdbc..4a84664b 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -13,7 +13,6 @@ import { showLocal, updatePersonBlock, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -293,10 +292,6 @@ export class Home extends Component { setupTippy(); } - componentWillUnmount() { - saveScrollPosition(this.context); - } - static async fetchInitialData({ client, auth, @@ -800,7 +795,6 @@ export class Home extends Component { }); } - restoreScrollPosition(this.context); setupTippy(); } diff --git a/src/shared/utils/browser/restore-scroll-position.ts b/src/shared/utils/browser/restore-scroll-position.ts index f1534644..6986ae59 100644 --- a/src/shared/utils/browser/restore-scroll-position.ts +++ b/src/shared/utils/browser/restore-scroll-position.ts @@ -1,5 +1,6 @@ export default function restoreScrollPosition(context: any) { const path: string = context.router.route.location.pathname; const y = Number(sessionStorage.getItem(`scrollPosition_${path}`)); + window.scrollTo(0, y); } diff --git a/src/shared/utils/browser/save-scroll-position.ts b/src/shared/utils/browser/save-scroll-position.ts index 48353287..596d5d9f 100644 --- a/src/shared/utils/browser/save-scroll-position.ts +++ b/src/shared/utils/browser/save-scroll-position.ts @@ -1,5 +1,6 @@ export default function saveScrollPosition(context: any) { const path: string = context.router.route.location.pathname; const y = window.scrollY; + sessionStorage.setItem(`scrollPosition_${path}`, y.toString()); } From 955ca826cd4d8e764578ddd37d302897c91340b8 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 12:28:27 -0400 Subject: [PATCH 18/31] Enable users to zoom on mobile --- src/server/utils/create-ssr-html.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index 39725fa5..55788ec5 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -73,7 +73,7 @@ export async function createSsrHtml( - + Date: Thu, 22 Jun 2023 13:44:43 -0300 Subject: [PATCH 19/31] Update getHttpBase dependency reference --- src/shared/markdown.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 6e6b504f..d35b469e 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -8,13 +8,13 @@ import { CustomEmojiView } from "lemmy-js-client"; import { default as MarkdownIt } from "markdown-it"; import markdown_it_container from "markdown-it-container"; // import markdown_it_emoji from "markdown-it-emoji/bare"; +import { getHttpBase } from "@utils/env"; import markdown_it_footnote from "markdown-it-footnote"; import markdown_it_html5_embed from "markdown-it-html5-embed"; import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; -import { getHttpBase } from "./env"; export let Tribute: any; From 51a6681d153cc398c1729a9f3972187a4b3581ac Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 12:50:05 -0400 Subject: [PATCH 20/31] Omit user-scalable to use default --- src/server/utils/create-ssr-html.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index 55788ec5..13775981 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -73,7 +73,7 @@ export async function createSsrHtml( - + Date: Thu, 22 Jun 2023 16:52:47 +0000 Subject: [PATCH 21/31] Fix avatar alignment issue (#1475) --- src/shared/components/common/pictrs-image.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/components/common/pictrs-image.tsx b/src/shared/components/common/pictrs-image.tsx index 74437490..31fb1229 100644 --- a/src/shared/components/common/pictrs-image.tsx +++ b/src/shared/components/common/pictrs-image.tsx @@ -22,7 +22,7 @@ export class PictrsImage extends Component { render() { return ( - + @@ -31,7 +31,7 @@ export class PictrsImage extends Component { alt={this.alt()} title={this.alt()} loading="lazy" - className={classNames({ + className={classNames("overflow-hidden pictrs-image", { "img-fluid": !this.props.icon && !this.props.iconOverlay, banner: this.props.banner, "thumbnail rounded": From c5779cd9b1e669fe6b8220e5c2dff0c125ed04e9 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 14:28:32 -0300 Subject: [PATCH 22/31] Update community link markdown parsing Remove links without remote servers, add kbin support, add user support --- src/shared/markdown.ts | 114 +++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 61 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index d35b469e..f56817e6 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -8,7 +8,6 @@ import { CustomEmojiView } from "lemmy-js-client"; import { default as MarkdownIt } from "markdown-it"; import markdown_it_container from "markdown-it-container"; // import markdown_it_emoji from "markdown-it-emoji/bare"; -import { getHttpBase } from "@utils/env"; import markdown_it_footnote from "markdown-it-footnote"; import markdown_it_html5_embed from "markdown-it-html5-embed"; import markdown_it_sub from "markdown-it-sub"; @@ -74,73 +73,66 @@ const html5EmbedConfig = { }; function localCommunityLinkParser(md) { - const pattern = - /(!\b[^@\s]+@[^@\s]+\.[^.\s]+\b)|\/c\/([^@\s]+)(@[^@\s]+\.[^.\s]+\b)?/g; - md.core.ruler.push("replace-text", state => { - const tokens = state.tokens; + /** + * Accepted formats: + * !community@server.com + * /c/community@server.com + * /m/community@server.com + * /u/username@server.com + */ + const pattern = + /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; - for (let i = 0; i < tokens.length; i++) { - if (tokens[i].type === "inline") { - const token = tokens[i]; + for (let i = 0; i < state.tokens.length; i++) { + if (state.tokens[i].type !== "inline") { + continue; + } + const inlineTokens = state.tokens[i].children; + for (let j = inlineTokens.length - 1; j >= 0; j--) { + if ( + inlineTokens[j].type === "text" && + pattern.test(inlineTokens[j].content) + ) { + const textParts = inlineTokens[j].content.split(pattern); + const newTokens: Token[] = []; - const originalContent = token.content; + for (const part of textParts) { + let linkClass = "community-link"; + if (pattern.test(part)) { + // Rewrite !community@server.com and KBin /m/community@server.com to local urls + let href; + if (part.startsWith("!")) { + href = "/c/" + part.substring(1); + } else if (part.startsWith("/m/")) { + href = "/c/" + part.substring(3); + } else { + href = part; + if (part.startsWith("/u/")) { + linkClass = "user-link"; + } + } - let lastIndex = 0; - originalContent.replace( - pattern, - (match, fullDomainMatch, name, domainTld, index) => { - let url; - // ex: !Testing@example.com - if (fullDomainMatch) { - const [name, domain, tld] = fullDomainMatch - .slice(1) - .split("@") - .join(".") - .split("."); - url = `${getHttpBase()}/c/${name}@${domain}.${tld}`; + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [ + ["href", href], + ["class", linkClass], + ]; + const textToken = new state.Token("text", "", 0); + textToken.content = part; + const linkCloseToken = new state.Token("link_close", "a", -1); + + newTokens.push(linkOpenToken, textToken, linkCloseToken); } else { - // ex: /c/Testing or /c/Testing@example.com - url = `${getHttpBase()}/c/${name}${domainTld || ""}`; + const textToken = new state.Token("text", "", 0); + textToken.content = part; + newTokens.push(textToken); } - - const beforeContent = originalContent.slice(lastIndex, index); - lastIndex = index + match.length; - - const beforeToken = new state.Token("text", "", 0); - beforeToken.content = beforeContent; - - const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [ - ["href", url], - ["class", "community-link"], - ]; - - const textToken = new state.Token("text", "", 0); - textToken.content = match; - - const linkCloseToken = new state.Token("link_close", "a", -1); - - const afterContent = originalContent.slice(lastIndex); - const afterToken = new state.Token("text", "", 0); - afterToken.content = afterContent; - - tokens.splice(i, 1); - - tokens.splice( - i, - 0, - beforeToken, - linkOpenToken, - textToken, - linkCloseToken, - afterToken - ); - - // Update i to skip the newly added tokens - i += 4; } - ); + + // Replace the original token with the new tokens + inlineTokens.splice(j, 1, ...newTokens); + } } } }); From fc0c0634269fb57dad2e75f6b5bf5c1aa06fabf8 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:17:34 -0300 Subject: [PATCH 23/31] Move regex pattern to config --- src/shared/config.ts | 10 ++++++++++ src/shared/markdown.ts | 17 ++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index 28e8ce51..6b462244 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -25,4 +25,14 @@ export const fetchLimit = 40; export const relTags = "noopener nofollow"; export const emDash = "\u2014"; +/** + * Accepted formats: + * !community@server.com + * /c/community@server.com + * /m/community@server.com + * /u/username@server.com + */ +export const instanceLinkRegex = + /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; + export const testHost = "0.0.0.0:8536"; diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index f56817e6..d8ed9d50 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -14,6 +14,7 @@ import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; +import { instanceLinkRegex } from "./config"; export let Tribute: any; @@ -74,16 +75,6 @@ const html5EmbedConfig = { function localCommunityLinkParser(md) { md.core.ruler.push("replace-text", state => { - /** - * Accepted formats: - * !community@server.com - * /c/community@server.com - * /m/community@server.com - * /u/username@server.com - */ - const pattern = - /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; - for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { continue; @@ -92,14 +83,14 @@ function localCommunityLinkParser(md) { for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && - pattern.test(inlineTokens[j].content) + instanceLinkRegex.test(inlineTokens[j].content) ) { - const textParts = inlineTokens[j].content.split(pattern); + const textParts = inlineTokens[j].content.split(instanceLinkRegex); const newTokens: Token[] = []; for (const part of textParts) { let linkClass = "community-link"; - if (pattern.test(part)) { + if (instanceLinkRegex.test(part)) { // Rewrite !community@server.com and KBin /m/community@server.com to local urls let href; if (part.startsWith("!")) { From 73147ae37c5ba930a4915fc704a01bfb2744b173 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:33:45 -0300 Subject: [PATCH 24/31] Use shorter regex in community link parser --- src/shared/config.ts | 2 +- src/shared/markdown.ts | 69 +++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index 6b462244..db7e688a 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -33,6 +33,6 @@ export const emDash = "\u2014"; * /u/username@server.com */ export const instanceLinkRegex = - /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; + /(\/[c|m|u]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; export const testHost = "0.0.0.0:8536"; diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index d8ed9d50..faab8756 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -73,7 +73,7 @@ const html5EmbedConfig = { }, }; -function localCommunityLinkParser(md) { +function localCommunityLinkParser(md: MarkdownIt) { md.core.ruler.push("replace-text", state => { for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { @@ -83,42 +83,49 @@ function localCommunityLinkParser(md) { for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && - instanceLinkRegex.test(inlineTokens[j].content) + new RegExp(instanceLinkRegex).test(inlineTokens[j].content) ) { - const textParts = inlineTokens[j].content.split(instanceLinkRegex); + const text = inlineTokens[j].content; + const matches = Array.from(text.matchAll(instanceLinkRegex)); + + let lastIndex = 0; const newTokens: Token[] = []; - for (const part of textParts) { - let linkClass = "community-link"; - if (instanceLinkRegex.test(part)) { - // Rewrite !community@server.com and KBin /m/community@server.com to local urls - let href; - if (part.startsWith("!")) { - href = "/c/" + part.substring(1); - } else if (part.startsWith("/m/")) { - href = "/c/" + part.substring(3); - } else { - href = part; - if (part.startsWith("/u/")) { - linkClass = "user-link"; - } - } - - const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [ - ["href", href], - ["class", linkClass], - ]; + for (const match: RegExpMatchArray of matches) { + // If there is plain text before the match, add it as a separate token + if (match.index !== undefined && match.index > lastIndex) { const textToken = new state.Token("text", "", 0); - textToken.content = part; - const linkCloseToken = new state.Token("link_close", "a", -1); - - newTokens.push(linkOpenToken, textToken, linkCloseToken); - } else { - const textToken = new state.Token("text", "", 0); - textToken.content = part; + textToken.content = text.slice(lastIndex, match.index); newTokens.push(textToken); } + + // Determine the new href + let href; + if (match[0].startsWith("!")) { + href = "/c/" + match[0].substring(1); + } else if (match[0].startsWith("/m/")) { + href = "/c/" + match[0].substring(3); + } else { + href = match[0]; + } + + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [["href", href]]; + const textToken = new state.Token("text", "", 0); + textToken.content = match[0]; + const linkCloseToken = new state.Token("link_close", "a", -1); + + newTokens.push(linkOpenToken, textToken, linkCloseToken); + + lastIndex = + (match.index !== undefined ? match.index : 0) + match[0].length; + } + + // If there is plain text after the last match, add it as a separate token + if (lastIndex < text.length) { + const textToken = new state.Token("text", "", 0); + textToken.content = text.slice(lastIndex); + newTokens.push(textToken); } // Replace the original token with the new tokens From d6e9b20a6ce29efdb4efe05014581ab5a4142f3b Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:40:06 -0300 Subject: [PATCH 25/31] Add missing classes --- src/shared/markdown.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index faab8756..062b150d 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -91,6 +91,8 @@ function localCommunityLinkParser(md: MarkdownIt) { let lastIndex = 0; const newTokens: Token[] = []; + let linkClass = "community-link"; + for (const match: RegExpMatchArray of matches) { // If there is plain text before the match, add it as a separate token if (match.index !== undefined && match.index > lastIndex) { @@ -109,8 +111,15 @@ function localCommunityLinkParser(md: MarkdownIt) { href = match[0]; } + if (match[0].startsWith("/u/")) { + linkClass = "user-link"; + } + const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [["href", href]]; + linkOpenToken.attrs = [ + ["href", href], + ["class", linkClass], + ]; const textToken = new state.Token("text", "", 0); textToken.content = match[0]; const linkCloseToken = new state.Token("link_close", "a", -1); From 773eef5126c8381b42bf1833dc7f040ad7f20b19 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:43:01 -0300 Subject: [PATCH 26/31] Remove pipe from community link regex --- src/shared/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index db7e688a..c56c64b0 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -33,6 +33,6 @@ export const emDash = "\u2014"; * /u/username@server.com */ export const instanceLinkRegex = - /(\/[c|m|u]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; + /(\/[cmu]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; export const testHost = "0.0.0.0:8536"; From 7571f7ac69e930e0f3c9758792fdc09b87da0f70 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:45:09 -0400 Subject: [PATCH 27/31] bandaid fix our video embeds --- src/shared/components/post/post-listing.tsx | 75 +++++++++++++-------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index 4d0951bb..93b8fff7 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -239,25 +239,40 @@ export class PostListing extends Component { } get img() { - return this.imageSrc ? ( - <> -
- - - + if (this.imageSrc) { + return ( + <> +
+ + + +
+
+ + + +
+ + ); + } + + const { post } = this.postView; + const { url } = post; + + if (url && isVideo(url)) { + return ( +
+
-
- - - -
- - ) : ( - <> - ); + ); + } + + return <>; } imgThumb(src: string) { @@ -325,17 +340,19 @@ export class PostListing extends Component { } else if (url) { if (!this.props.hideImage && isVideo(url)) { return ( -
- -
+ +
+ +
+
); } else { return ( From 110be607c5da59b14d285a8a8b597e202fa42473 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:51:25 -0300 Subject: [PATCH 28/31] Typescript linter fixes --- src/shared/markdown.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 062b150d..ececf479 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -79,7 +79,7 @@ function localCommunityLinkParser(md: MarkdownIt) { if (state.tokens[i].type !== "inline") { continue; } - const inlineTokens = state.tokens[i].children; + const inlineTokens: Token[] = state.tokens[i].children || []; for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && @@ -93,7 +93,7 @@ function localCommunityLinkParser(md: MarkdownIt) { let linkClass = "community-link"; - for (const match: RegExpMatchArray of matches) { + for (const match of matches) { // If there is plain text before the match, add it as a separate token if (match.index !== undefined && match.index > lastIndex) { const textToken = new state.Token("text", "", 0); From 7bd90da1f84bf1cfccfa192e4aebf93549685e4e Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 16:02:27 -0300 Subject: [PATCH 29/31] Rename function to be more generic, since it parses users --- src/shared/markdown.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index ececf479..adee474f 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -73,7 +73,7 @@ const html5EmbedConfig = { }, }; -function localCommunityLinkParser(md: MarkdownIt) { +function localInstanceLinkParser(md: MarkdownIt) { md.core.ruler.push("replace-text", state => { for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { From d58fd63113bc2933377ec2d90f8091b34b16e74f Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 16:05:20 -0300 Subject: [PATCH 30/31] Cleanup, only check for /u/ if /c/ and /m/ checks fail --- src/shared/markdown.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index adee474f..9f1ec733 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -101,7 +101,6 @@ function localInstanceLinkParser(md: MarkdownIt) { newTokens.push(textToken); } - // Determine the new href let href; if (match[0].startsWith("!")) { href = "/c/" + match[0].substring(1); @@ -109,10 +108,9 @@ function localInstanceLinkParser(md: MarkdownIt) { href = "/c/" + match[0].substring(3); } else { href = match[0]; - } - - if (match[0].startsWith("/u/")) { - linkClass = "user-link"; + if (match[0].startsWith("/u/")) { + linkClass = "user-link"; + } } const linkOpenToken = new state.Token("link_open", "a", 1); @@ -137,7 +135,6 @@ function localInstanceLinkParser(md: MarkdownIt) { newTokens.push(textToken); } - // Replace the original token with the new tokens inlineTokens.splice(j, 1, ...newTokens); } } @@ -162,7 +159,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) - .use(localCommunityLinkParser); + .use(localInstanceLinkParser); // .use(markdown_it_emoji, { // defs: emojiDefs, // }); @@ -173,7 +170,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) - .use(localCommunityLinkParser) + .use(localInstanceLinkParser) // .use(markdown_it_emoji, { // defs: emojiDefs, // }) From 374132923f7527f50b6b001c5683fafae7d6f917 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 22 Jun 2023 16:15:45 -0400 Subject: [PATCH 31/31] Adding jsit to codeowners. --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 76916e60..ee3d7a54 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @dessalines @SleeplessOne1917 @alectrocute +* @dessalines @SleeplessOne1917 @alectrocute @jsit