Feat/pagefind search (#56)
* feat: pagefind search engine * fix: search now works * fixed layout --------- Co-authored-by: hugo <hugoms@me.com>
This commit is contained in:
@@ -18,7 +18,8 @@
|
|||||||
"Bash(npm test -- tests/renderer/i18nLocaleCompleteness.test.ts)",
|
"Bash(npm test -- tests/renderer/i18nLocaleCompleteness.test.ts)",
|
||||||
"WebFetch(domain:ricmac.org)",
|
"WebFetch(domain:ricmac.org)",
|
||||||
"WebFetch(domain:docs.mistral.ai)",
|
"WebFetch(domain:docs.mistral.ai)",
|
||||||
"Bash(npm uninstall dropbox date-fns @testing-library/user-event @types/dagre electron-store memfs)"
|
"Bash(npm uninstall dropbox date-fns @testing-library/user-event @types/dagre electron-store memfs)",
|
||||||
|
"WebSearch"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
167
package-lock.json
generated
167
package-lock.json
generated
@@ -44,6 +44,7 @@
|
|||||||
"marked-react": "^3.0.2",
|
"marked-react": "^3.0.2",
|
||||||
"monaco-editor": "^0.55.1",
|
"monaco-editor": "^0.55.1",
|
||||||
"node-scp": "^0.0.25",
|
"node-scp": "^0.0.25",
|
||||||
|
"pagefind": "^1.4.0",
|
||||||
"pyodide": "^0.29.3",
|
"pyodide": "^0.29.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-arborist": "^3.4.3",
|
"react-arborist": "^3.4.3",
|
||||||
@@ -286,6 +287,7 @@
|
|||||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.29.0",
|
"@babel/code-frame": "^7.29.0",
|
||||||
"@babel/generator": "^7.29.0",
|
"@babel/generator": "^7.29.0",
|
||||||
@@ -864,6 +866,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.1.tgz",
|
||||||
"integrity": "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==",
|
"integrity": "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.23.0",
|
"@codemirror/view": "^6.23.0",
|
||||||
@@ -940,6 +943,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz",
|
||||||
"integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==",
|
"integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@marijn/find-cluster-break": "^1.0.0"
|
"@marijn/find-cluster-break": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -961,6 +965,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.13.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.13.tgz",
|
||||||
"integrity": "sha512-QBO8ZsgJLCbI28KdY0/oDy5NQLqOQVZCozBknxc2/7L98V+TVYFHnfaCsnGh1U+alpd2LOkStVwYY7nW2R1xbw==",
|
"integrity": "sha512-QBO8ZsgJLCbI28KdY0/oDy5NQLqOQVZCozBknxc2/7L98V+TVYFHnfaCsnGh1U+alpd2LOkStVwYY7nW2R1xbw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.5.0",
|
"@codemirror/state": "^6.5.0",
|
||||||
"crelt": "^1.0.6",
|
"crelt": "^1.0.6",
|
||||||
@@ -1056,6 +1061,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=20.19.0"
|
||||||
},
|
},
|
||||||
@@ -1096,6 +1102,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=20.19.0"
|
||||||
}
|
}
|
||||||
@@ -1465,7 +1472,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-dirname": "^0.1.0",
|
"cross-dirname": "^0.1.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@@ -1487,7 +1493,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
@@ -1504,7 +1509,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -1519,7 +1523,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
@@ -3678,6 +3681,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.17.0.tgz",
|
||||||
"integrity": "sha512-TLjSU9Otdpq0SpKHl1tD1Nc9MKhrsZbCFGot3EbCxRa8m1E5R1mMwoOjKMMM31IyF7fr+hPNHLpYfwbMKNusmg==",
|
"integrity": "sha512-TLjSU9Otdpq0SpKHl1tD1Nc9MKhrsZbCFGot3EbCxRa8m1E5R1mMwoOjKMMM31IyF7fr+hPNHLpYfwbMKNusmg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@libsql/core": "^0.17.0",
|
"@libsql/core": "^0.17.0",
|
||||||
"@libsql/hrana-client": "^0.9.0",
|
"@libsql/hrana-client": "^0.9.0",
|
||||||
@@ -4317,6 +4321,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz",
|
||||||
"integrity": "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==",
|
"integrity": "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hono/node-server": "^1.19.9",
|
"@hono/node-server": "^1.19.9",
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
@@ -4614,6 +4619,84 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@pagefind/darwin-arm64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@pagefind/darwin-x64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@pagefind/freebsd-x64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@pagefind/linux-arm64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@pagefind/linux-x64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@pagefind/windows-x64": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@picocss/pico": {
|
"node_modules/@picocss/pico": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@picocss/pico/-/pico-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@picocss/pico/-/pico-2.1.1.tgz",
|
||||||
@@ -5184,8 +5267,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
|
||||||
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
|
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/babel__core": {
|
"node_modules/@types/babel__core": {
|
||||||
"version": "7.20.5",
|
"version": "7.20.5",
|
||||||
@@ -5409,6 +5491,7 @@
|
|||||||
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
}
|
}
|
||||||
@@ -5419,6 +5502,7 @@
|
|||||||
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.2.0"
|
"@types/react": "^19.2.0"
|
||||||
}
|
}
|
||||||
@@ -5526,6 +5610,7 @@
|
|||||||
"integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
|
"integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.56.0",
|
"@typescript-eslint/scope-manager": "8.56.0",
|
||||||
"@typescript-eslint/types": "8.56.0",
|
"@typescript-eslint/types": "8.56.0",
|
||||||
@@ -5914,6 +5999,7 @@
|
|||||||
"integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==",
|
"integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/utils": "4.0.18",
|
"@vitest/utils": "4.0.18",
|
||||||
"fflate": "^0.8.2",
|
"fflate": "^0.8.2",
|
||||||
@@ -6138,6 +6224,7 @@
|
|||||||
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -6189,6 +6276,7 @@
|
|||||||
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
@@ -6817,6 +6905,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
@@ -7543,8 +7632,7 @@
|
|||||||
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/cross-env": {
|
"node_modules/cross-env": {
|
||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
@@ -7680,7 +7768,8 @@
|
|||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/d3-cloud": {
|
"node_modules/d3-cloud": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
@@ -7936,6 +8025,7 @@
|
|||||||
"integrity": "sha512-uOOBA3f+kW3o4KpSoMQ6SNpdXU7WtxlJRb9vCZgOvqhTz4b3GjcoWKstdisizNZLsylhTMv8TLHFPFW0Uxsj/g==",
|
"integrity": "sha512-uOOBA3f+kW3o4KpSoMQ6SNpdXU7WtxlJRb9vCZgOvqhTz4b3GjcoWKstdisizNZLsylhTMv8TLHFPFW0Uxsj/g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "26.7.0",
|
"app-builder-lib": "26.7.0",
|
||||||
"builder-util": "26.4.1",
|
"builder-util": "26.4.1",
|
||||||
@@ -8037,8 +8127,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
||||||
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
|
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
@@ -8430,7 +8519,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/asar": "^3.2.1",
|
"@electron/asar": "^3.2.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -8451,7 +8539,6 @@
|
|||||||
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"jsonfile": "^4.0.0",
|
"jsonfile": "^4.0.0",
|
||||||
@@ -8487,16 +8574,6 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/encoding": {
|
|
||||||
"version": "0.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
|
||||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"iconv-lite": "^0.6.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/end-of-stream": {
|
"node_modules/end-of-stream": {
|
||||||
"version": "1.4.5",
|
"version": "1.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
@@ -8603,6 +8680,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
},
|
},
|
||||||
@@ -8685,6 +8763,7 @@
|
|||||||
"integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==",
|
"integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -9855,6 +9934,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
|
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
|
||||||
"integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
|
"integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
}
|
}
|
||||||
@@ -10381,6 +10461,7 @@
|
|||||||
"integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==",
|
"integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@acemir/cssom": "^0.9.31",
|
"@acemir/cssom": "^0.9.31",
|
||||||
"@asamuzakjp/dom-selector": "^6.7.6",
|
"@asamuzakjp/dom-selector": "^6.7.6",
|
||||||
@@ -10725,7 +10806,6 @@
|
|||||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"lz-string": "bin/bin.js"
|
"lz-string": "bin/bin.js"
|
||||||
}
|
}
|
||||||
@@ -11971,7 +12051,6 @@
|
|||||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": "^1.2.6"
|
"minimist": "^1.2.6"
|
||||||
},
|
},
|
||||||
@@ -11984,6 +12063,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz",
|
||||||
"integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==",
|
"integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dompurify": "3.2.7",
|
"dompurify": "3.2.7",
|
||||||
"marked": "14.0.0"
|
"marked": "14.0.0"
|
||||||
@@ -12514,6 +12594,23 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0"
|
"license": "BlueOak-1.0.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/pagefind": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"pagefind": "lib/runner/bin.cjs"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@pagefind/darwin-arm64": "1.4.0",
|
||||||
|
"@pagefind/darwin-x64": "1.4.0",
|
||||||
|
"@pagefind/freebsd-x64": "1.4.0",
|
||||||
|
"@pagefind/linux-arm64": "1.4.0",
|
||||||
|
"@pagefind/linux-x64": "1.4.0",
|
||||||
|
"@pagefind/windows-x64": "1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -12653,6 +12750,7 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -12788,7 +12886,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "^9.4.0"
|
"commander": "^9.4.0"
|
||||||
},
|
},
|
||||||
@@ -12806,7 +12903,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.20.0 || >=14"
|
"node": "^12.20.0 || >=14"
|
||||||
}
|
}
|
||||||
@@ -12827,7 +12923,6 @@
|
|||||||
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
|
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": "^5.0.1",
|
"ansi-regex": "^5.0.1",
|
||||||
"ansi-styles": "^5.0.0",
|
"ansi-styles": "^5.0.0",
|
||||||
@@ -12843,7 +12938,6 @@
|
|||||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
},
|
},
|
||||||
@@ -12998,6 +13092,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
|
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
|
||||||
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
|
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"orderedmap": "^2.0.0"
|
"orderedmap": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -13031,6 +13126,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
|
||||||
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
|
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prosemirror-model": "^1.0.0",
|
"prosemirror-model": "^1.0.0",
|
||||||
"prosemirror-transform": "^1.0.0",
|
"prosemirror-transform": "^1.0.0",
|
||||||
@@ -13064,6 +13160,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.6.tgz",
|
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.6.tgz",
|
||||||
"integrity": "sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==",
|
"integrity": "sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prosemirror-model": "^1.20.0",
|
"prosemirror-model": "^1.20.0",
|
||||||
"prosemirror-state": "^1.0.0",
|
"prosemirror-state": "^1.0.0",
|
||||||
@@ -13246,6 +13343,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||||
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -13311,6 +13409,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
||||||
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.27.0"
|
"scheduler": "^0.27.0"
|
||||||
},
|
},
|
||||||
@@ -13340,8 +13439,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
@@ -13645,7 +13743,6 @@
|
|||||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
},
|
},
|
||||||
@@ -14554,7 +14651,6 @@
|
|||||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"rimraf": "~2.6.2"
|
"rimraf": "~2.6.2"
|
||||||
@@ -15401,6 +15497,7 @@
|
|||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -15728,6 +15825,7 @@
|
|||||||
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -16287,6 +16385,7 @@
|
|||||||
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/expect": "4.0.18",
|
"@vitest/expect": "4.0.18",
|
||||||
"@vitest/mocker": "4.0.18",
|
"@vitest/mocker": "4.0.18",
|
||||||
@@ -16364,6 +16463,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz",
|
||||||
"integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==",
|
"integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.28",
|
"@vue/compiler-dom": "3.5.28",
|
||||||
"@vue/compiler-sfc": "3.5.28",
|
"@vue/compiler-sfc": "3.5.28",
|
||||||
@@ -16681,6 +16781,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
||||||
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,7 @@
|
|||||||
"marked-react": "^3.0.2",
|
"marked-react": "^3.0.2",
|
||||||
"monaco-editor": "^0.55.1",
|
"monaco-editor": "^0.55.1",
|
||||||
"node-scp": "^0.0.25",
|
"node-scp": "^0.0.25",
|
||||||
|
"pagefind": "^1.4.0",
|
||||||
"pyodide": "^0.29.3",
|
"pyodide": "^0.29.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-arborist": "^3.4.3",
|
"react-arborist": "^3.4.3",
|
||||||
@@ -132,7 +133,9 @@
|
|||||||
"asar": true,
|
"asar": true,
|
||||||
"asarUnpack": [
|
"asarUnpack": [
|
||||||
"node_modules/onnxruntime-node/**",
|
"node_modules/onnxruntime-node/**",
|
||||||
"node_modules/usearch/**"
|
"node_modules/usearch/**",
|
||||||
|
"node_modules/pagefind/**",
|
||||||
|
"node_modules/@pagefind/**"
|
||||||
],
|
],
|
||||||
"afterSign": "scripts/notarize.mjs",
|
"afterSign": "scripts/notarize.mjs",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { PICO_THEME_NAMES } from '../shared/picoThemes';
|
|||||||
import { CODE_ENHANCEMENTS_RUNTIME_JS } from './assets/codeEnhancementsRuntime';
|
import { CODE_ENHANCEMENTS_RUNTIME_JS } from './assets/codeEnhancementsRuntime';
|
||||||
import { CALENDAR_RUNTIME_JS } from './assets/calendarRuntime';
|
import { CALENDAR_RUNTIME_JS } from './assets/calendarRuntime';
|
||||||
import { TAG_CLOUD_RUNTIME_JS } from './assets/tagCloudRuntime';
|
import { TAG_CLOUD_RUNTIME_JS } from './assets/tagCloudRuntime';
|
||||||
|
import { SEARCH_RUNTIME_JS } from './assets/searchRuntime';
|
||||||
import { resolveRenderLanguageFromProjectPreferences, translateRender, getRenderTranslations } from '../shared/i18n';
|
import { resolveRenderLanguageFromProjectPreferences, translateRender, getRenderTranslations } from '../shared/i18n';
|
||||||
|
|
||||||
function readLocalAsset(filename: string): string {
|
function readLocalAsset(filename: string): string {
|
||||||
@@ -312,6 +313,10 @@ export const PREVIEW_ASSETS: Record<string, PreviewAssetDefinition> = {
|
|||||||
contentType: 'application/javascript; charset=utf-8',
|
contentType: 'application/javascript; charset=utf-8',
|
||||||
sourceText: CALENDAR_RUNTIME_JS,
|
sourceText: CALENDAR_RUNTIME_JS,
|
||||||
},
|
},
|
||||||
|
'search-runtime.js': {
|
||||||
|
contentType: 'application/javascript; charset=utf-8',
|
||||||
|
sourceText: SEARCH_RUNTIME_JS,
|
||||||
|
},
|
||||||
'bds.css': {
|
'bds.css': {
|
||||||
contentType: 'text/css; charset=utf-8',
|
contentType: 'text/css; charset=utf-8',
|
||||||
sourceText: readLocalAsset('bds.css'),
|
sourceText: readLocalAsset('bds.css'),
|
||||||
|
|||||||
107
src/main/engine/SearchIndexEngine.ts
Normal file
107
src/main/engine/SearchIndexEngine.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
import { spawn } from 'node:child_process';
|
||||||
|
|
||||||
|
export interface SearchIndexOptions {
|
||||||
|
htmlDir: string;
|
||||||
|
mainLanguage: string;
|
||||||
|
additionalLanguages: string[];
|
||||||
|
onProgress?: (progress: number, message?: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchIndexLanguageResult {
|
||||||
|
language: string;
|
||||||
|
pageCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchIndexResult {
|
||||||
|
languageIndexes: SearchIndexLanguageResult[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolvePagefindBinaryPath(): string {
|
||||||
|
const cpu = os.arch();
|
||||||
|
const platform = process.platform === 'win32' ? 'windows' : process.platform;
|
||||||
|
const execnames = ['pagefind_extended', 'pagefind'];
|
||||||
|
|
||||||
|
for (const execname of execnames) {
|
||||||
|
const executable = platform === 'windows' ? `${execname}.exe` : execname;
|
||||||
|
try {
|
||||||
|
let resolved = require.resolve(`@pagefind/${platform}-${cpu}/bin/${executable}`);
|
||||||
|
// In packaged Electron, require.resolve returns a path through app.asar
|
||||||
|
// but the binary is in the unpacked directory alongside it
|
||||||
|
resolved = resolved.replace(/app\.asar([/\\])/, 'app.asar.unpacked$1');
|
||||||
|
return resolved;
|
||||||
|
} catch {
|
||||||
|
// try next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Failed to find pagefind binary for ${platform}-${cpu}. ` +
|
||||||
|
`Ensure @pagefind/${platform}-${cpu} is installed.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPagefind(args: string[]): Promise<{ stdout: string; stderr: string }> {
|
||||||
|
const binaryPath = resolvePagefindBinaryPath();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const proc = spawn(binaryPath, args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
||||||
|
let stdout = '';
|
||||||
|
let stderr = '';
|
||||||
|
proc.stdout.on('data', (data: Buffer) => { stdout += data.toString(); });
|
||||||
|
proc.stderr.on('data', (data: Buffer) => { stderr += data.toString(); });
|
||||||
|
proc.on('error', reject);
|
||||||
|
proc.on('close', (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Pagefind exited with code ${code}: ${stderr}`));
|
||||||
|
} else {
|
||||||
|
resolve({ stdout, stderr });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePageCount(output: string): number {
|
||||||
|
const match = output.match(/indexed\s+(\d+)\s+page/i) ?? output.match(/(\d+)\s+page/i);
|
||||||
|
return match ? parseInt(match[1], 10) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build Pagefind search indexes for a generated static site.
|
||||||
|
*
|
||||||
|
* For single-language sites, creates one index at `{htmlDir}/pagefind/`.
|
||||||
|
* For multilingual sites, creates per-language indexes:
|
||||||
|
* - main language: `{htmlDir}/pagefind/` (indexes root html)
|
||||||
|
* - additional languages: `{htmlDir}/{lang}/pagefind/` (indexes `{htmlDir}/{lang}/`)
|
||||||
|
*/
|
||||||
|
export async function buildSearchIndex(options: SearchIndexOptions): Promise<SearchIndexResult> {
|
||||||
|
const { htmlDir, mainLanguage, additionalLanguages, onProgress } = options;
|
||||||
|
|
||||||
|
const languages = [mainLanguage, ...additionalLanguages];
|
||||||
|
const results: SearchIndexLanguageResult[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < languages.length; i++) {
|
||||||
|
const lang = languages[i];
|
||||||
|
const isMain = lang === mainLanguage;
|
||||||
|
const sourceDir = isMain ? htmlDir : path.join(htmlDir, lang);
|
||||||
|
const outputDir = isMain
|
||||||
|
? path.join(htmlDir, 'pagefind')
|
||||||
|
: path.join(htmlDir, lang, 'pagefind');
|
||||||
|
|
||||||
|
const progressBase = Math.floor((i / languages.length) * 100);
|
||||||
|
|
||||||
|
onProgress?.(progressBase, `Indexing search for ${lang}...`);
|
||||||
|
|
||||||
|
const { stdout, stderr } = await runPagefind([
|
||||||
|
'--site', sourceDir,
|
||||||
|
'--output-path', outputDir,
|
||||||
|
'--force-language', lang,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const pageCount = parsePageCount(stdout + stderr);
|
||||||
|
results.push({ language: lang, pageCount });
|
||||||
|
}
|
||||||
|
|
||||||
|
onProgress?.(100, 'Search indexes built');
|
||||||
|
return { languageIndexes: results };
|
||||||
|
}
|
||||||
@@ -148,3 +148,22 @@ main { display: grid; gap: 1rem; }
|
|||||||
.language-switcher-badge:hover,
|
.language-switcher-badge:hover,
|
||||||
.language-switcher-badge:focus-visible { opacity: 1; border-color: var(--pico-color, var(--color)); }
|
.language-switcher-badge:focus-visible { opacity: 1; border-color: var(--pico-color, var(--color)); }
|
||||||
.language-switcher-badge-current { opacity: 1; border-color: var(--pico-primary, var(--primary)); }
|
.language-switcher-badge-current { opacity: 1; border-color: var(--pico-primary, var(--primary)); }
|
||||||
|
.blog-search-widget, .blog-search-standalone { position: relative; margin-top: .15rem; }
|
||||||
|
.blog-search-standalone { position: fixed; right: .75rem; top: 1.5rem; z-index: 100; }
|
||||||
|
.blog-search-toggle { display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent; color: var(--pico-muted-color, var(--muted-color)); cursor: pointer; padding: .15rem; opacity: .7; transition: opacity .15s ease-in-out; }
|
||||||
|
.blog-search-toggle:hover, .blog-search-toggle:focus-visible { opacity: 1; color: var(--pico-color, var(--color)); }
|
||||||
|
.blog-search-toggle svg { display: block; }
|
||||||
|
.blog-search-panel { position: absolute; top: calc(100% + .25rem); right: 0; width: min(24rem, 90vw); z-index: 40; border: 1px solid var(--pico-muted-border-color, var(--muted-border-color)); background: var(--pico-card-background-color, var(--card-background-color)); padding: .5rem; border-radius: .35rem; box-shadow: 0 4px 24px rgba(0,0,0,.25); }
|
||||||
|
.blog-search-panel .pagefind-ui { --pagefind-ui-scale: .8; --pagefind-ui-primary: var(--pico-primary, var(--primary)); --pagefind-ui-text: var(--pico-color, var(--color)); --pagefind-ui-background: var(--pico-card-background-color, var(--card-background-color)); --pagefind-ui-border: var(--pico-muted-border-color, var(--muted-border-color)); --pagefind-ui-tag: var(--pico-muted-border-color, var(--muted-border-color)); --pagefind-ui-border-width: 1px; --pagefind-ui-border-radius: .2rem; --pagefind-ui-image-border-radius: .2rem; --pagefind-ui-image-box-ratio: 0; --pagefind-ui-font: inherit; font-size: .85rem; }
|
||||||
|
.blog-search-panel .pagefind-ui__search-input { font-size: .85rem; padding: .3rem .5rem; border: 1px solid var(--pico-muted-border-color, var(--muted-border-color)); background: var(--pico-background-color, var(--background-color)); color: var(--pico-color, var(--color)); border-radius: .2rem; width: 100%; }
|
||||||
|
.blog-search-panel .pagefind-ui__search-clear { color: var(--pico-muted-color, var(--muted-color)); background: none; font-size: .8rem; }
|
||||||
|
.blog-search-panel .pagefind-ui__search-clear:focus { outline-color: var(--pico-primary, var(--primary)); }
|
||||||
|
.blog-search-panel .pagefind-ui__drawer { max-height: min(60vh, 28rem); overflow-y: auto; }
|
||||||
|
.blog-search-panel .pagefind-ui__message { color: var(--pico-muted-color, var(--muted-color)); font-size: .78rem; padding: .25rem 0; }
|
||||||
|
.blog-search-panel .pagefind-ui__result { border-top: 1px solid var(--pico-muted-border-color, var(--muted-border-color)); padding: .4rem 0; }
|
||||||
|
.blog-search-panel .pagefind-ui__result-link { color: var(--pico-primary, var(--primary)); font-size: .85rem; }
|
||||||
|
.blog-search-panel .pagefind-ui__result-title { font-size: .85rem; }
|
||||||
|
.blog-search-panel .pagefind-ui__result-excerpt { font-size: .78rem; color: var(--pico-muted-color, var(--muted-color)); }
|
||||||
|
.blog-search-panel .pagefind-ui__result-excerpt mark { background-color: var(--pico-primary-focus, rgba(255,223,0,.35)); color: inherit; }
|
||||||
|
.blog-search-panel .pagefind-ui__button { color: var(--pico-primary, var(--primary)); background: none; border: 1px solid var(--pico-muted-border-color, var(--muted-border-color)); border-radius: .2rem; font-size: .78rem; cursor: pointer; }
|
||||||
|
.blog-search-panel .pagefind-ui__button:hover { border-color: var(--pico-primary, var(--primary)); }
|
||||||
|
|||||||
52
src/main/engine/assets/searchRuntime.ts
Normal file
52
src/main/engine/assets/searchRuntime.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export const SEARCH_RUNTIME_JS = String.raw`(() => {
|
||||||
|
const toggle = document.querySelector('[data-blog-search-toggle]');
|
||||||
|
const panel = document.querySelector('[data-blog-search-panel]');
|
||||||
|
const root = document.querySelector('[data-blog-search-root]');
|
||||||
|
|
||||||
|
if (!toggle || !panel || !root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let initialized = false;
|
||||||
|
|
||||||
|
function initSearch() {
|
||||||
|
if (initialized || typeof PagefindUI === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
var placeholder = root.getAttribute('data-search-placeholder') || 'Search...';
|
||||||
|
new PagefindUI({
|
||||||
|
element: root,
|
||||||
|
showSubResults: true,
|
||||||
|
showImages: false,
|
||||||
|
translations: { placeholder: placeholder }
|
||||||
|
});
|
||||||
|
var input = root.querySelector('input');
|
||||||
|
if (input) {
|
||||||
|
input.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle.addEventListener('click', function() {
|
||||||
|
var isHidden = panel.hasAttribute('hidden');
|
||||||
|
if (isHidden) {
|
||||||
|
panel.removeAttribute('hidden');
|
||||||
|
initSearch();
|
||||||
|
} else {
|
||||||
|
panel.setAttribute('hidden', '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
if (!panel.hasAttribute('hidden') && !panel.contains(e.target) && !toggle.contains(e.target)) {
|
||||||
|
panel.setAttribute('hidden', '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Escape' && !panel.hasAttribute('hidden')) {
|
||||||
|
panel.setAttribute('hidden', '');
|
||||||
|
toggle.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();`;
|
||||||
@@ -21,4 +21,7 @@
|
|||||||
<script defer src="/assets/lightbox.min.js"></script>
|
<script defer src="/assets/lightbox.min.js"></script>
|
||||||
<script defer src="/assets/vanilla-calendar.min.js"></script>
|
<script defer src="/assets/vanilla-calendar.min.js"></script>
|
||||||
<script defer src="/assets/calendar-runtime.js"></script>
|
<script defer src="/assets/calendar-runtime.js"></script>
|
||||||
|
<script defer src="/assets/search-runtime.js"></script>
|
||||||
|
<link rel="stylesheet" href="{{ language_prefix }}/pagefind/pagefind-ui.css" />
|
||||||
|
<script defer src="{{ language_prefix }}/pagefind/pagefind-ui.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -7,6 +7,17 @@
|
|||||||
<a class="language-switcher-badge" href="{{ lang.href_prefix | default: '/' }}" data-lang-prefix="{{ lang.href_prefix }}" title="{{ lang.code }}">{{ lang.flag }}</a>
|
<a class="language-switcher-badge" href="{{ lang.href_prefix | default: '/' }}" data-lang-prefix="{{ lang.href_prefix }}" title="{{ lang.code }}">{{ lang.flag }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<div class="blog-search-widget" aria-label="{{ 'render.search.ariaLabel' | i18n: language }}">
|
||||||
|
<button type="button" class="blog-search-toggle" data-blog-search-toggle aria-label="{{ 'render.search.ariaLabel' | i18n: language }}">
|
||||||
|
<svg aria-hidden="true" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="blog-search-panel" data-blog-search-panel hidden>
|
||||||
|
<div id="blog-search" data-blog-search-root data-search-placeholder="{{ 'render.search.placeholder' | i18n: language }}"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
@@ -15,4 +26,16 @@
|
|||||||
links.forEach(function(a){a.href=(a.dataset.langPrefix||'')+path;});
|
links.forEach(function(a){a.href=(a.dataset.langPrefix||'')+path;});
|
||||||
}());
|
}());
|
||||||
</script>
|
</script>
|
||||||
|
{% else %}
|
||||||
|
<div class="blog-search-standalone" aria-label="{{ 'render.search.ariaLabel' | i18n: language }}">
|
||||||
|
<button type="button" class="blog-search-toggle" data-blog-search-toggle aria-label="{{ 'render.search.ariaLabel' | i18n: language }}">
|
||||||
|
<svg aria-hidden="true" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="blog-search-panel" data-blog-search-panel hidden>
|
||||||
|
<div id="blog-search" data-blog-search-root data-search-placeholder="{{ 'render.search.placeholder' | i18n: language }}"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<article class="single-post" data-template="single-post">
|
<article class="single-post" data-template="single-post" data-pagefind-body>
|
||||||
<div class="post">{{ post.content | markdown: post.id, post_data_json_by_id, canonical_post_path_by_slug, canonical_media_path_by_source_path, language, language_prefix }}</div>
|
<div class="post">{{ post.content | markdown: post.id, post_data_json_by_id, canonical_post_path_by_slug, canonical_media_path_by_source_path, language, language_prefix }}</div>
|
||||||
</article>
|
</article>
|
||||||
{% if backlinks.size > 0 %}
|
{% if backlinks.size > 0 %}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import * as path from 'path';
|
||||||
import { dialog } from 'electron';
|
import { dialog } from 'electron';
|
||||||
import {
|
import {
|
||||||
resolvePublicBaseUrl,
|
resolvePublicBaseUrl,
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
type ApplyValidationPreparation,
|
type ApplyValidationPreparation,
|
||||||
} from '../engine/BlogGenerationEngine';
|
} from '../engine/BlogGenerationEngine';
|
||||||
import { resolvePageTitle } from '../engine/PageRenderer';
|
import { resolvePageTitle } from '../engine/PageRenderer';
|
||||||
|
import { buildSearchIndex } from '../engine/SearchIndexEngine';
|
||||||
import type { EngineBundle } from '../engine/EngineBundle';
|
import type { EngineBundle } from '../engine/EngineBundle';
|
||||||
import type { TranslationValidationReport } from '../shared/electronApi';
|
import type { TranslationValidationReport } from '../shared/electronApi';
|
||||||
import { autoTranslatePost, autoTranslateMediaMetadata } from './chatHandlers';
|
import { autoTranslatePost, autoTranslateMediaMetadata } from './chatHandlers';
|
||||||
@@ -152,6 +154,26 @@ export function registerBlogHandlers(safeHandle: SafeHandle, bundle: EngineBundl
|
|||||||
runSectionTask('date', 'Render Date Archives', 'site-render-date'),
|
runSectionTask('date', 'Render Date Archives', 'site-render-date'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await bundle.taskManager.runTask({
|
||||||
|
id: `site-render-search-index-${taskTimestamp}`,
|
||||||
|
name: 'Build Search Index',
|
||||||
|
groupId: taskGroupId,
|
||||||
|
groupName: taskGroupName,
|
||||||
|
execute: async (onProgress) => {
|
||||||
|
const htmlDir = path.join(baseOptions.dataDir, 'html');
|
||||||
|
const mainLanguage = (baseOptions.language ?? 'en').trim().toLowerCase();
|
||||||
|
const additionalLanguages = (baseOptions.blogLanguages ?? [])
|
||||||
|
.map((lang) => lang.trim().toLowerCase())
|
||||||
|
.filter((lang) => lang.length > 0 && lang !== mainLanguage);
|
||||||
|
return buildSearchIndex({
|
||||||
|
htmlDir,
|
||||||
|
mainLanguage,
|
||||||
|
additionalLanguages,
|
||||||
|
onProgress: (progress, message) => onProgress(progress, message || 'Building search index...'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return mergeResults([coreResult, singleResult, categoryResult, tagResult, dateResult]);
|
return mergeResults([coreResult, singleResult, categoryResult, tagResult, dateResult]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -388,6 +410,27 @@ export function registerBlogHandlers(safeHandle: SafeHandle, bundle: EngineBundl
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Phase 4: Rebuild search index
|
||||||
|
await bundle.taskManager.runTask({
|
||||||
|
id: `site-validate-search-index-${taskTimestamp}`,
|
||||||
|
name: 'Build Search Index',
|
||||||
|
groupId: taskGroupId,
|
||||||
|
groupName: taskGroupName,
|
||||||
|
execute: async (onProgress) => {
|
||||||
|
const htmlDir = path.join(baseOptions.dataDir, 'html');
|
||||||
|
const mainLanguage = (baseOptions.language ?? 'en').trim().toLowerCase();
|
||||||
|
const additionalLanguages = (baseOptions.blogLanguages ?? [])
|
||||||
|
.map((lang) => lang.trim().toLowerCase())
|
||||||
|
.filter((lang) => lang.length > 0 && lang !== mainLanguage);
|
||||||
|
return buildSearchIndex({
|
||||||
|
htmlDir,
|
||||||
|
mainLanguage,
|
||||||
|
additionalLanguages,
|
||||||
|
onProgress: (progress, message) => onProgress(progress, message || 'Building search index...'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -94,5 +94,7 @@
|
|||||||
"task.rebuildEmbeddingIndex.clearing": "Index wird geleert…",
|
"task.rebuildEmbeddingIndex.clearing": "Index wird geleert…",
|
||||||
"task.duplicateSearch.name": "Doppelte Beiträge finden",
|
"task.duplicateSearch.name": "Doppelte Beiträge finden",
|
||||||
"task.duplicateSearch.searching": "Prüfe: {checked}/{total}",
|
"task.duplicateSearch.searching": "Prüfe: {checked}/{total}",
|
||||||
"menu.item.fillMissingTranslations": "Fehlende Übersetzungen ausfüllen"
|
"menu.item.fillMissingTranslations": "Fehlende Übersetzungen ausfüllen",
|
||||||
|
"render.search.placeholder": "Suchen...",
|
||||||
|
"render.search.ariaLabel": "Seitensuche"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,5 +94,7 @@
|
|||||||
"task.rebuildEmbeddingIndex.clearing": "Clearing index…",
|
"task.rebuildEmbeddingIndex.clearing": "Clearing index…",
|
||||||
"task.duplicateSearch.name": "Find Duplicate Posts",
|
"task.duplicateSearch.name": "Find Duplicate Posts",
|
||||||
"task.duplicateSearch.searching": "Checking: {checked}/{total}",
|
"task.duplicateSearch.searching": "Checking: {checked}/{total}",
|
||||||
"menu.item.fillMissingTranslations": "Fill Missing Translations"
|
"menu.item.fillMissingTranslations": "Fill Missing Translations",
|
||||||
|
"render.search.placeholder": "Search...",
|
||||||
|
"render.search.ariaLabel": "Site search"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,5 +94,7 @@
|
|||||||
"task.rebuildEmbeddingIndex.clearing": "Vaciando índice…",
|
"task.rebuildEmbeddingIndex.clearing": "Vaciando índice…",
|
||||||
"task.duplicateSearch.name": "Buscar entradas duplicadas",
|
"task.duplicateSearch.name": "Buscar entradas duplicadas",
|
||||||
"task.duplicateSearch.searching": "Comprobando: {checked}/{total}",
|
"task.duplicateSearch.searching": "Comprobando: {checked}/{total}",
|
||||||
"menu.item.fillMissingTranslations": "Completar traducciones faltantes"
|
"menu.item.fillMissingTranslations": "Completar traducciones faltantes",
|
||||||
|
"render.search.placeholder": "Buscar...",
|
||||||
|
"render.search.ariaLabel": "Buscar en el sitio"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,5 +94,7 @@
|
|||||||
"task.rebuildEmbeddingIndex.clearing": "Vidage de l'index…",
|
"task.rebuildEmbeddingIndex.clearing": "Vidage de l'index…",
|
||||||
"task.duplicateSearch.name": "Trouver les articles en double",
|
"task.duplicateSearch.name": "Trouver les articles en double",
|
||||||
"task.duplicateSearch.searching": "Vérification : {checked}/{total}",
|
"task.duplicateSearch.searching": "Vérification : {checked}/{total}",
|
||||||
"menu.item.fillMissingTranslations": "Compléter les traductions manquantes"
|
"menu.item.fillMissingTranslations": "Compléter les traductions manquantes",
|
||||||
|
"render.search.placeholder": "Rechercher...",
|
||||||
|
"render.search.ariaLabel": "Recherche du site"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,5 +94,7 @@
|
|||||||
"task.rebuildEmbeddingIndex.clearing": "Svuotamento indice…",
|
"task.rebuildEmbeddingIndex.clearing": "Svuotamento indice…",
|
||||||
"task.duplicateSearch.name": "Trova post duplicati",
|
"task.duplicateSearch.name": "Trova post duplicati",
|
||||||
"task.duplicateSearch.searching": "Controllo: {checked}/{total}",
|
"task.duplicateSearch.searching": "Controllo: {checked}/{total}",
|
||||||
"menu.item.fillMissingTranslations": "Completa le traduzioni mancanti"
|
"menu.item.fillMissingTranslations": "Completa le traduzioni mancanti",
|
||||||
|
"render.search.placeholder": "Cerca...",
|
||||||
|
"render.search.ariaLabel": "Ricerca nel sito"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1074,7 +1074,7 @@ describe('PreviewServer', () => {
|
|||||||
|
|
||||||
const mainIndex = html.indexOf('<main>');
|
const mainIndex = html.indexOf('<main>');
|
||||||
const h1Index = html.indexOf('<h1>Explicit Single Post Title</h1>');
|
const h1Index = html.indexOf('<h1>Explicit Single Post Title</h1>');
|
||||||
const articleIndex = html.indexOf('<article class="single-post" data-template="single-post">');
|
const articleIndex = html.indexOf('<article class="single-post" data-template="single-post" data-pagefind-body>');
|
||||||
expect(mainIndex).toBeGreaterThan(-1);
|
expect(mainIndex).toBeGreaterThan(-1);
|
||||||
expect(h1Index).toBeGreaterThan(mainIndex);
|
expect(h1Index).toBeGreaterThan(mainIndex);
|
||||||
expect(articleIndex).toBeGreaterThan(mainIndex);
|
expect(articleIndex).toBeGreaterThan(mainIndex);
|
||||||
|
|||||||
148
tests/engine/SearchIndexEngine.test.ts
Normal file
148
tests/engine/SearchIndexEngine.test.ts
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
||||||
|
|
||||||
|
const { mockSpawn } = vi.hoisted(() => ({
|
||||||
|
mockSpawn: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('node:child_process', () => ({
|
||||||
|
spawn: mockSpawn,
|
||||||
|
default: { spawn: mockSpawn },
|
||||||
|
}));
|
||||||
|
|
||||||
|
function createMockProc(exitCode = 0, stdout = 'Indexed 5 pages\n', stderr = '') {
|
||||||
|
const stdoutCbs: ((data: Buffer) => void)[] = [];
|
||||||
|
const stderrCbs: ((data: Buffer) => void)[] = [];
|
||||||
|
const closeCbs: ((...args: unknown[]) => void)[] = [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
stdout: {
|
||||||
|
on: vi.fn((_event: string, cb: (data: Buffer) => void) => {
|
||||||
|
stdoutCbs.push(cb);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
stderr: {
|
||||||
|
on: vi.fn((_event: string, cb: (data: Buffer) => void) => {
|
||||||
|
stderrCbs.push(cb);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
on: vi.fn((event: string, cb: (...args: unknown[]) => void) => {
|
||||||
|
if (event === 'error') return;
|
||||||
|
if (event === 'close') {
|
||||||
|
closeCbs.push(cb);
|
||||||
|
Promise.resolve().then(() => {
|
||||||
|
for (const fn of stdoutCbs) fn(Buffer.from(stdout));
|
||||||
|
for (const fn of stderrCbs) if (stderr) fn(Buffer.from(stderr));
|
||||||
|
for (const fn of closeCbs) fn(exitCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
mockSpawn.mockImplementation(() => createMockProc(0, 'Indexed 5 pages\n'));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SearchIndexEngine', () => {
|
||||||
|
describe('buildSearchIndex', () => {
|
||||||
|
it('spawns pagefind binary for a single language', async () => {
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
|
||||||
|
const result = await buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockSpawn).toHaveBeenCalledTimes(1);
|
||||||
|
const args = mockSpawn.mock.calls[0][1] as string[];
|
||||||
|
expect(args).toEqual(expect.arrayContaining([
|
||||||
|
'--site', '/site/html',
|
||||||
|
'--force-language', 'en',
|
||||||
|
'--output-path', '/site/html/pagefind',
|
||||||
|
]));
|
||||||
|
expect(result.languageIndexes).toHaveLength(1);
|
||||||
|
expect(result.languageIndexes[0]).toEqual({ language: 'en', pageCount: 5 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('spawns pagefind once per language for multilingual sites', async () => {
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
|
||||||
|
const result = await buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: ['de', 'fr'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockSpawn).toHaveBeenCalledTimes(3);
|
||||||
|
const calls = mockSpawn.mock.calls;
|
||||||
|
|
||||||
|
expect(calls[0][1]).toContain('en');
|
||||||
|
expect(calls[1][1]).toContain('de');
|
||||||
|
expect(calls[2][1]).toContain('fr');
|
||||||
|
|
||||||
|
expect(result.languageIndexes).toHaveLength(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('writes per-language output to language subdirectories', async () => {
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
|
||||||
|
await buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: ['de'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const calls = mockSpawn.mock.calls;
|
||||||
|
|
||||||
|
const mainArgs = calls[0][1] as string[];
|
||||||
|
const mainOutputIdx = mainArgs.indexOf('--output-path');
|
||||||
|
expect(mainArgs[mainOutputIdx + 1]).toBe('/site/html/pagefind');
|
||||||
|
|
||||||
|
const deArgs = calls[1][1] as string[];
|
||||||
|
const deOutputIdx = deArgs.indexOf('--output-path');
|
||||||
|
expect(deArgs[deOutputIdx + 1]).toBe('/site/html/de/pagefind');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when pagefind exits with non-zero code', async () => {
|
||||||
|
mockSpawn.mockImplementation(() => createMockProc(1, '', 'Something went wrong'));
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
|
||||||
|
await expect(buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: [],
|
||||||
|
})).rejects.toThrow('Pagefind exited with code 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses page count from pagefind output', async () => {
|
||||||
|
mockSpawn.mockImplementation(() => createMockProc(0, 'Running Pagefind\nIndexed 42 pages\nDone'));
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
|
||||||
|
const result = await buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.languageIndexes[0].pageCount).toBe(42);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reports progress via onProgress callback', async () => {
|
||||||
|
const { buildSearchIndex } = await import('../../src/main/engine/SearchIndexEngine');
|
||||||
|
const onProgress = vi.fn();
|
||||||
|
|
||||||
|
await buildSearchIndex({
|
||||||
|
htmlDir: '/site/html',
|
||||||
|
mainLanguage: 'en',
|
||||||
|
additionalLanguages: ['de'],
|
||||||
|
onProgress,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(onProgress).toHaveBeenCalled();
|
||||||
|
const calls = onProgress.mock.calls;
|
||||||
|
expect(calls[calls.length - 1][0]).toBe(100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -321,6 +321,10 @@ vi.mock('../../src/main/engine/TaskManager', () => ({
|
|||||||
TaskProgress: {},
|
TaskProgress: {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../src/main/engine/SearchIndexEngine', () => ({
|
||||||
|
buildSearchIndex: vi.fn().mockResolvedValue({ languageIndexes: [] }),
|
||||||
|
}));
|
||||||
|
|
||||||
vi.mock('../../src/main/database', () => ({
|
vi.mock('../../src/main/database', () => ({
|
||||||
getDatabase: vi.fn(() => mockDatabase),
|
getDatabase: vi.fn(() => mockDatabase),
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user