From c77e60e16176773224f577edb72ea0b89e39ee18 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:11:44 +0800 Subject: [PATCH 01/24] release(desktop): release v1.11.0 --- apps/desktop/changelog/1.11.0.md | 13 +++++++++++++ apps/desktop/changelog/next.md | 8 +++----- apps/desktop/package.json | 6 +++--- apps/desktop/release.json | 8 ++++---- 4 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 apps/desktop/changelog/1.11.0.md diff --git a/apps/desktop/changelog/1.11.0.md b/apps/desktop/changelog/1.11.0.md new file mode 100644 index 000000000..1c8e9d434 --- /dev/null +++ b/apps/desktop/changelog/1.11.0.md @@ -0,0 +1,13 @@ +# What's new in v1.11.0 + +## Improvements + +- Upgraded the desktop runtime to Electron 43 and refreshed core dependencies + +## No longer broken + +- Fixed YouTube embeds in entry content and readability view failing to play due to a missing referrer + +## Thanks + +Special thanks to volunteer contributor @TonyRL for the YouTube embed fix diff --git a/apps/desktop/changelog/next.md b/apps/desktop/changelog/next.md index fefb84147..8f5eac449 100644 --- a/apps/desktop/changelog/next.md +++ b/apps/desktop/changelog/next.md @@ -1,13 +1,11 @@ # What's new in vNEXT_VERSION +## Shiny new things + ## Improvements -- Upgraded the desktop runtime to Electron 43 and refreshed core dependencies - ## No longer broken -- Fixed YouTube embeds in entry content and readability view failing to play due to a missing referrer - ## Thanks -Special thanks to volunteer contributor @TonyRL for the YouTube embed fix +Special thanks to volunteer contributors @ for their valuable contributions diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 0a2706089..eff667961 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "Folo", "type": "module", - "version": "1.10.0", + "version": "1.11.0", "private": true, "description": "Follow everything in one place", "author": "Folo Team", @@ -99,7 +99,7 @@ "workbox-build": "7.4.1", "workbox-window": "7.4.1" }, - "runtimeVersion": "1.9.0", + "runtimeVersion": "1.11.0", "productName": "Folo", - "mainHash": "79b9a1c73ebea4fc92b28cc4952a2fe92557557141b1de0c81074622d8a1f404" + "mainHash": "b672f321b6478cbaad0ad6e354d73ca3c8a79f90aaadb41c119499639ec66e87" } diff --git a/apps/desktop/release.json b/apps/desktop/release.json index 53251c263..599812e85 100644 --- a/apps/desktop/release.json +++ b/apps/desktop/release.json @@ -1,6 +1,6 @@ { - "version": "1.10.0", - "mode": "ota", - "runtimeVersion": "1.9.0", - "channel": "stable" + "version": "1.11.0", + "mode": "build", + "runtimeVersion": null, + "channel": null } From c3fae852aa6747f6f6f9a2a00a88384e2fd2ffa0 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:13:00 +0800 Subject: [PATCH 02/24] docs(desktop): restore mobile release inputs --- apps/mobile/changelog/next.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/mobile/changelog/next.md b/apps/mobile/changelog/next.md index 8c3affe62..000f858e3 100644 --- a/apps/mobile/changelog/next.md +++ b/apps/mobile/changelog/next.md @@ -1,14 +1,11 @@ # What's New in vNEXT_VERSION +## Shiny new things + ## Improvements -- Upgraded the app to Expo SDK 57, React Native 0.86, and updated native integrations - ## No longer broken -- Fixed social sign-in callbacks and legacy session migration using the Folo app scheme -- Fixed signed-out launches not opening the login screen -- Fixed two-factor authentication cookies being dropped during session updates -- Fixed push notification registration after sign-in, including retries and token refreshes -- Fixed the timeline view selector overflowing on narrow screens -- Restored the header background after scrolling +## Thanks + +Special thanks to volunteer contributors @ for their valuable contributions From d726ccccb2df4cb15997d614886b333b58ed976d Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:32:42 +0800 Subject: [PATCH 03/24] fix(desktop): use js-yaml ESM exports --- apps/desktop/scripts/merge-yml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/merge-yml.ts b/apps/desktop/scripts/merge-yml.ts index f28562c8c..12d124382 100644 --- a/apps/desktop/scripts/merge-yml.ts +++ b/apps/desktop/scripts/merge-yml.ts @@ -1,6 +1,6 @@ import fs from "node:fs" -import yaml from "js-yaml" +import * as yaml from "js-yaml" import path from "pathe" const outDir = "./out/make" From 57fd759f258ae8312ff3521efc238d5008e72c2c Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:32:42 +0800 Subject: [PATCH 04/24] fix(desktop): use js-yaml ESM exports --- apps/desktop/scripts/merge-yml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/merge-yml.ts b/apps/desktop/scripts/merge-yml.ts index f28562c8c..12d124382 100644 --- a/apps/desktop/scripts/merge-yml.ts +++ b/apps/desktop/scripts/merge-yml.ts @@ -1,6 +1,6 @@ import fs from "node:fs" -import yaml from "js-yaml" +import * as yaml from "js-yaml" import path from "pathe" const outDir = "./out/make" From 713c53352d905af80a7ec1cf44fc9cff1e5f62dd Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 12:12:50 +0800 Subject: [PATCH 05/24] fix(desktop): package jsdom runtime dependencies --- apps/desktop/forge.config.cts | 43 +++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/apps/desktop/forge.config.cts b/apps/desktop/forge.config.cts index 8237ffa68..ea509deee 100644 --- a/apps/desktop/forge.config.cts +++ b/apps/desktop/forge.config.cts @@ -36,7 +36,43 @@ const ymlMapsMap = { win32: "latest.yml", } -const keepModules = new Set(["font-list", "vscode-languagedetection"]) +// Keep external runtime modules and their production dependency trees in app.asar. +// Scoped packages are copied as a whole because cleanSources operates on top-level entries. +const keepModules = new Set([ + "@asamuzakjp", + "@bramus", + "@csstools", + "@exodus", + "bidi-js", + "css-tree", + "data-urls", + "decimal.js", + "entities", + "font-list", + "html-encoding-sniffer", + "is-potential-custom-element-name", + "jsdom", + "lru-cache", + "mdn-data", + "parse5", + "punycode", + "require-from-string", + "saxes", + "source-map-js", + "symbol-tree", + "tldts", + "tldts-core", + "tough-cookie", + "tr46", + "undici", + "vscode-languagedetection", + "w3c-xmlserializer", + "webidl-conversions", + "whatwg-mimetype", + "whatwg-url", + "xml-name-validator", + "xmlchars", +]) const keepLanguages = new Set(["en", "en_GB", "en-US", "en_US"]) // remove folders & files not to be included in the app @@ -93,7 +129,10 @@ async function cleanSources(buildPath, _electronVersion, platform, _arch, callba const noopAfterCopy = (_buildPath, _electronVersion, _platform, _arch, callback) => callback() -const ignorePattern = new RegExp(`^/node_modules/(?!${[...keepModules].join("|")})`) +const keepModulePattern = [...keepModules] + .map((item) => item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")) + .join("|") +const ignorePattern = new RegExp(`^/node_modules/(?!(?:${keepModulePattern})(?:/|$))`) const config: ForgeConfig = { packagerConfig: { From d90cdfe2b376e3481ce17c9d143e88e1af15a646 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 12:12:50 +0800 Subject: [PATCH 06/24] fix(desktop): package jsdom runtime dependencies --- apps/desktop/forge.config.cts | 43 +++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/apps/desktop/forge.config.cts b/apps/desktop/forge.config.cts index 8237ffa68..ea509deee 100644 --- a/apps/desktop/forge.config.cts +++ b/apps/desktop/forge.config.cts @@ -36,7 +36,43 @@ const ymlMapsMap = { win32: "latest.yml", } -const keepModules = new Set(["font-list", "vscode-languagedetection"]) +// Keep external runtime modules and their production dependency trees in app.asar. +// Scoped packages are copied as a whole because cleanSources operates on top-level entries. +const keepModules = new Set([ + "@asamuzakjp", + "@bramus", + "@csstools", + "@exodus", + "bidi-js", + "css-tree", + "data-urls", + "decimal.js", + "entities", + "font-list", + "html-encoding-sniffer", + "is-potential-custom-element-name", + "jsdom", + "lru-cache", + "mdn-data", + "parse5", + "punycode", + "require-from-string", + "saxes", + "source-map-js", + "symbol-tree", + "tldts", + "tldts-core", + "tough-cookie", + "tr46", + "undici", + "vscode-languagedetection", + "w3c-xmlserializer", + "webidl-conversions", + "whatwg-mimetype", + "whatwg-url", + "xml-name-validator", + "xmlchars", +]) const keepLanguages = new Set(["en", "en_GB", "en-US", "en_US"]) // remove folders & files not to be included in the app @@ -93,7 +129,10 @@ async function cleanSources(buildPath, _electronVersion, platform, _arch, callba const noopAfterCopy = (_buildPath, _electronVersion, _platform, _arch, callback) => callback() -const ignorePattern = new RegExp(`^/node_modules/(?!${[...keepModules].join("|")})`) +const keepModulePattern = [...keepModules] + .map((item) => item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")) + .join("|") +const ignorePattern = new RegExp(`^/node_modules/(?!(?:${keepModulePattern})(?:/|$))`) const config: ForgeConfig = { packagerConfig: { From 192a7139ce0adbff37f964bdbd52f737a16ede81 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 13:03:25 +0800 Subject: [PATCH 07/24] fix(desktop): use js-yaml ESM exports for Windows metadata --- apps/desktop/scripts/update-windows-yml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/update-windows-yml.ts b/apps/desktop/scripts/update-windows-yml.ts index 45afd2775..5c04c075c 100644 --- a/apps/desktop/scripts/update-windows-yml.ts +++ b/apps/desktop/scripts/update-windows-yml.ts @@ -2,7 +2,7 @@ import crypto from "node:crypto" import fs from "node:fs" import { fileURLToPath, resolve } from "node:url" -import yaml from "js-yaml" +import * as yaml from "js-yaml" const __dirname = fileURLToPath(new URL(".", import.meta.url)) const basePath = resolve(__dirname, "../out/make/squirrel.windows/x64/") From 773f1bfe218ac349b9fb9b5cbd982c320f6b414f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 09:00:49 +0800 Subject: [PATCH 08/24] build(deps): bump actions/setup-node from 6 to 7 (#5046) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-desktop.yml | 4 ++-- .github/workflows/build-ios-development.yml | 4 ++-- .github/workflows/build-ios.yml | 2 +- .github/workflows/build-web.yml | 2 +- .github/workflows/deploy-cloudflare-desktop.yml | 2 +- .github/workflows/deploy-cloudflare-landing.yml | 2 +- .github/workflows/deploy-cloudflare-ssr.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-ota.yml | 2 +- .github/workflows/tag.yml | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 9ab5b3225..fb381dd0b 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -57,7 +57,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index fe1417385..3816beb22 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -83,7 +83,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Use Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" @@ -407,7 +407,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Use Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-ios-development.yml b/.github/workflows/build-ios-development.yml index 46ca32ba3..5c16f9eca 100644 --- a/.github/workflows/build-ios-development.yml +++ b/.github/workflows/build-ios-development.yml @@ -97,7 +97,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" @@ -148,7 +148,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml index cd5defeeb..d790be1dc 100644 --- a/.github/workflows/build-ios.yml +++ b/.github/workflows/build-ios.yml @@ -117,7 +117,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 9b3c504fe..368b2cfd6 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -34,7 +34,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-desktop.yml b/.github/workflows/deploy-cloudflare-desktop.yml index 877486508..c0a0fa672 100644 --- a/.github/workflows/deploy-cloudflare-desktop.yml +++ b/.github/workflows/deploy-cloudflare-desktop.yml @@ -35,7 +35,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-landing.yml b/.github/workflows/deploy-cloudflare-landing.yml index a9cd90314..187ccd4f4 100644 --- a/.github/workflows/deploy-cloudflare-landing.yml +++ b/.github/workflows/deploy-cloudflare-landing.yml @@ -39,7 +39,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-ssr.yml b/.github/workflows/deploy-cloudflare-ssr.yml index 1671fe558..32ae35df2 100644 --- a/.github/workflows/deploy-cloudflare-ssr.yml +++ b/.github/workflows/deploy-cloudflare-ssr.yml @@ -42,7 +42,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ff1af2bad..4b7ba8eac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,7 +39,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} cache: "pnpm" diff --git a/.github/workflows/publish-ota.yml b/.github/workflows/publish-ota.yml index c09ad4733..100a5aed7 100644 --- a/.github/workflows/publish-ota.yml +++ b/.github/workflows/publish-ota.yml @@ -60,7 +60,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index a9d6abf63..24f1c7c0a 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v7 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* From cf224d63f5dc336c5751d532a3cbf861531e67da Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sat, 25 Jul 2026 12:38:49 +0800 Subject: [PATCH 09/24] fix(ssr): escape hydration data in inline scripts --- apps/ssr/package.json | 1 + apps/ssr/src/lib/hydration-script.test.ts | 109 ++++++++++++++++++++++ apps/ssr/src/lib/hydration-script.ts | 38 ++++++++ apps/ssr/src/router/global.ts | 9 +- apps/ssr/src/router/og/index.ts | 3 +- apps/ssr/tsconfig.json | 1 + apps/ssr/vitest.config.ts | 7 ++ apps/ssr/worker-entry.ts | 10 +- 8 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 apps/ssr/src/lib/hydration-script.test.ts create mode 100644 apps/ssr/src/lib/hydration-script.ts create mode 100644 apps/ssr/vitest.config.ts diff --git a/apps/ssr/package.json b/apps/ssr/package.json index 87ae4d16b..8628f10d9 100644 --- a/apps/ssr/package.json +++ b/apps/ssr/package.json @@ -10,6 +10,7 @@ "dev": "cross-env NODE_ENV=development tsx watch --include \"src/**/*.ts\" --exclude \"./*.ts\" --exclude \"./*.mjs\" index.ts", "meta": "tsx helper/meta-map.ts --watch", "start": "tsx index.ts", + "test": "vitest run --config vitest.config.ts", "typecheck": "tsc --noEmit" }, "dependencies": { diff --git a/apps/ssr/src/lib/hydration-script.test.ts b/apps/ssr/src/lib/hydration-script.test.ts new file mode 100644 index 000000000..a270043ef --- /dev/null +++ b/apps/ssr/src/lib/hydration-script.test.ts @@ -0,0 +1,109 @@ +import { runInNewContext } from "node:vm" + +import { minify } from "html-minifier-terser" +import { parseHTML } from "linkedom" +import { describe, expect, it } from "vitest" + +import { createHydrationScript, injectHydrationScript } from "./hydration-script" + +describe("hydration script", () => { + it("keeps attacker-controlled keys and data inside a single script element", () => { + const key = `profile