oceanpress 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/cli.js +84 -9
- package/dist-cli/cli.js.map +1 -1
- package/package.json +6 -5
package/dist-cli/cli.js
CHANGED
|
@@ -4,7 +4,70 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
|
|
5
5
|
// src/cli/deploy.ts
|
|
6
6
|
import { readFile } from "fs/promises";
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
// ../rpc/dist/index.js
|
|
9
|
+
async function createRPC(...[type, options]) {
|
|
10
|
+
const apiModule = type === "apiProvider" ? await options.genApiModule() : void 0;
|
|
11
|
+
const remoteCall = type === "apiConsumer" ? options.remoteCall : void 0;
|
|
12
|
+
async function RC(method, data) {
|
|
13
|
+
async function executeMiddleware(index) {
|
|
14
|
+
if (options.middleware && index < options.middleware.length) {
|
|
15
|
+
return options.middleware[index](method, data, () => executeMiddleware(index + 1));
|
|
16
|
+
} else {
|
|
17
|
+
return executeCall();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function executeCall() {
|
|
21
|
+
try {
|
|
22
|
+
if (type === "apiProvider") {
|
|
23
|
+
const methodParts = method.split(".");
|
|
24
|
+
let currentObj = apiModule;
|
|
25
|
+
for (const part of methodParts) {
|
|
26
|
+
if (currentObj && typeof currentObj === "object" && part in currentObj) {
|
|
27
|
+
currentObj = currentObj[part];
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error(`Method ${method} not found`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (typeof currentObj === "function") {
|
|
33
|
+
return await currentObj(...data);
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error(`${method} is not a function`);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
return await remoteCall(method, data);
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error("API call failed:", error);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return await executeMiddleware(0);
|
|
46
|
+
}
|
|
47
|
+
function createNestedProxy(path = []) {
|
|
48
|
+
return {
|
|
49
|
+
get(target, prop) {
|
|
50
|
+
if (prop === "then") {
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
const newPath = [...path, prop];
|
|
54
|
+
return new Proxy(function(...args) {
|
|
55
|
+
const method = newPath.join(".");
|
|
56
|
+
return RC(method, args);
|
|
57
|
+
}, createNestedProxy(newPath));
|
|
58
|
+
},
|
|
59
|
+
apply(target, thisArg, args) {
|
|
60
|
+
const method = path.join(".");
|
|
61
|
+
return RC(method, args);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const API2 = new Proxy(function() {
|
|
66
|
+
}, createNestedProxy());
|
|
67
|
+
return { API: API2, RC };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/cli/deploy.ts
|
|
8
71
|
import { stringify as stringify2 } from "superjson";
|
|
9
72
|
|
|
10
73
|
// src/core/dependency.ts
|
|
@@ -49,8 +112,7 @@ import { computed, reactive, watch } from "vue";
|
|
|
49
112
|
// package.json
|
|
50
113
|
var package_default = {
|
|
51
114
|
name: "oceanpress",
|
|
52
|
-
|
|
53
|
-
version: "1.0.2",
|
|
115
|
+
version: "1.0.4",
|
|
54
116
|
type: "module",
|
|
55
117
|
scripts: {
|
|
56
118
|
dev: "vite",
|
|
@@ -58,13 +120,27 @@ var package_default = {
|
|
|
58
120
|
cli_watch: "tsx watch ./src/cli.ts",
|
|
59
121
|
build: "vite build && npm run build_lib",
|
|
60
122
|
build_lib: "vite build --config vite.sw.config.ts",
|
|
61
|
-
|
|
123
|
+
build_app: "vite build --mode library",
|
|
124
|
+
build_cli: "tsup",
|
|
62
125
|
build_plugin_ui: "vite build --config vite.plugin.config.ts",
|
|
63
126
|
dev_plugin_ui: "vite build --watch --config vite.plugin.config.ts",
|
|
64
127
|
generate_dependency_graph: "depcruise src --include-only '^src' --output-type dot > ./assets/dep.dot",
|
|
65
128
|
preview: "vite preview"
|
|
66
129
|
},
|
|
67
|
-
bin:
|
|
130
|
+
bin: {
|
|
131
|
+
oceanpress: "./dist-cli/cli.js"
|
|
132
|
+
},
|
|
133
|
+
files: [
|
|
134
|
+
"dist/assets",
|
|
135
|
+
"dist/dev",
|
|
136
|
+
"dist/index.html",
|
|
137
|
+
"dist/ocean_press-log.png",
|
|
138
|
+
"dist-app/assets",
|
|
139
|
+
"dist-app/dev",
|
|
140
|
+
"dist-app/app.*",
|
|
141
|
+
"dist-cli",
|
|
142
|
+
"*.md"
|
|
143
|
+
],
|
|
68
144
|
dependencies: {
|
|
69
145
|
"@aws-sdk/client-s3": "^3.758.0",
|
|
70
146
|
"@hono/node-server": "^1.13.8",
|
|
@@ -75,8 +151,6 @@ var package_default = {
|
|
|
75
151
|
jszip: "^3.10.1",
|
|
76
152
|
meilisearch: "^0.49.0",
|
|
77
153
|
"naive-ui": "^2.41.0",
|
|
78
|
-
"oceanpress-rpc": "workspace:*",
|
|
79
|
-
"oceanpress-server": "workspace:*",
|
|
80
154
|
octokit: "^4.1.2",
|
|
81
155
|
superjson: "^2.2.2",
|
|
82
156
|
tsx: "^4.19.3",
|
|
@@ -86,6 +160,8 @@ var package_default = {
|
|
|
86
160
|
"zstd-codec": "^0.1.5"
|
|
87
161
|
},
|
|
88
162
|
devDependencies: {
|
|
163
|
+
"oceanpress-rpc": "workspace:*",
|
|
164
|
+
"oceanpress-server": "workspace:*",
|
|
89
165
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
90
166
|
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
|
91
167
|
"dependency-cruiser": "^16.10.0",
|
|
@@ -1607,7 +1683,6 @@ function useSkipBuilds() {
|
|
|
1607
1683
|
}
|
|
1608
1684
|
|
|
1609
1685
|
// src/plugins/publish/OceanPressServer.ts
|
|
1610
|
-
import { createRPC } from "oceanpress-rpc";
|
|
1611
1686
|
import { stringify } from "superjson";
|
|
1612
1687
|
function deployOceanPressServer_plugin(config) {
|
|
1613
1688
|
const plugin = {
|
|
@@ -1764,7 +1839,7 @@ program.command("deploy").description("\u90E8\u7F72\u7AD9\u70B9").option("-c, --
|
|
|
1764
1839
|
}
|
|
1765
1840
|
const config = await readFile(opt.config, "utf-8");
|
|
1766
1841
|
loadConfigFile(JSON.parse(config));
|
|
1767
|
-
const client = await
|
|
1842
|
+
const client = await createRPC("apiConsumer", {
|
|
1768
1843
|
remoteCall(method, data) {
|
|
1769
1844
|
let body;
|
|
1770
1845
|
let content_type;
|
package/dist-cli/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/deploy.ts","../src/core/dependency.ts","../src/util/deep_assign.ts","../src/core/config.ts","../package.json","../src/core/genZip.ts","../src/plugins/meilisearch_plugin/meilisearch_upload.ts","../src/core/plugin.ts","../src/plugins/publish/s3.ts","../src/core/htmlTemplate.ts","../src/util/escaping.ts","../src/components/data_promise/index.ts","../src/core/siyuan_api.ts","../src/core/render.ts","../src/core/siyuan_type.ts","../src/core/cache.ts","../src/core/genRssXml.ts","../src/core/build.ts","../src/plugins/publish/OceanPressServer.ts","../src/core/ocean_press.ts","../src/core/render.api.dep.ts","../src/util/store.node.dep.ts","../src/cli/common.ts","../src/cli/build.ts","../src/cli/server.ts","../src/server.ts","../src/core/hono_server.ts","../src/cli.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { createRPC } from 'oceanpress-rpc'\nimport type { API } from 'oceanpress-server'\nimport { stringify } from 'superjson'\nimport { currentConfig, loadConfigFile } from '~/core/config.ts'\nimport { genZIP } from '~/core/genZip.ts'\nimport { OceanPress } from '~/core/ocean_press.ts'\nimport { program } from './common.ts'\n\nprogram\n .command('deploy')\n .description('部署站点')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-h, --apiBase <string>', 'OceanPress server 地址')\n .option('-k, --apiKey <string>', 'OceanPress server Api 密钥')\n .action(async (opt: { config: string; apiBase: string; apiKey: string }) => {\n if (!opt.apiBase || !opt.apiKey) {\n return console.error(`请配置 apiBase 和 apiKey`)\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n const client = await createRPC<API>('apiConsumer', {\n remoteCall(method, data) {\n let body: ReadableStream | string\n // 如果第一参数是 ReadableStream 的时候,直接使用 ReadableStream 作为 body,不用考虑其他参数,因为这种情况只支持一个参数\n let content_type\n if (data[0] instanceof ReadableStream) {\n body = data[0]\n content_type = 'application/octet-stream'\n } else {\n body = stringify(data)\n console.log('[body]', body)\n content_type = 'application/json'\n }\n return fetch(`${opt.apiBase}/api/${method}`, {\n method: 'POST',\n body,\n headers: {\n 'x-api-key': opt.apiKey,\n 'Content-Type': content_type,\n },\n // @ts-expect-error 在 node 运行的时候需要声明双工模式才能正确发送 ReadableStream,TODO 需要验证浏览器端可以这样运行吗\n duplex: 'half', // 关键:显式声明半双工模式\n })\n .then((res) => res.json())\n .then((r) => {\n if (r.error) {\n console.log('[r]', r)\n throw new Error()\n }\n return r.result\n })\n },\n })\n const ocean_press = new OceanPress(currentConfig.value)\n\n ocean_press.pluginCenter.registerPlugin({\n async build_onFileTree([tree], next) {\n const zip = await genZIP(tree, { withoutZip: true })\n const sizeInMB = zip.size / (1024 * 1024)\n console.log('[zip.size in MB]', sizeInMB.toFixed(2))\n // 将 Blob 转换为 ReadableStream\n const readableStream = zip.stream()\n const { chunkCount, fileId } = await client.API.upload(readableStream)\n\n console.log('[res]', { chunkCount, fileId })\n const res = await client.API.deploy({ zipFileId: fileId })\n console.log('[deploy res]', res)\n },\n })\n\n await ocean_press.build({\n log: (msg) => {\n if (msg.startsWith('渲染:')) {\n process.stdout.write(`\\r\\x1b[K${msg}`)\n } else {\n process.stdout.write(`\\n${msg}`)\n }\n },\n percentage: (n) => {\n process.stdout.write(`\\r\\x1b[K进度:${n}%`)\n },\n })\n })\n","import type { S_Node } from './siyuan_type.ts'\r\n\r\n/** 默认填充函数,不应当被调用 */\r\nconst nullDep: any = () => {\r\n throw new Error('不可调用未填充的依赖')\r\n}\r\n\r\n/** ════════════════════════🏳🌈 全局依赖 🏳🌈════════════════════════\r\n * 供不同入口注入不同依赖实现\r\n ** ════════════════════════🚧 全局依赖 🚧════════════════════════ */\r\nexport const storeDep = {\r\n // 读写配置文件所依赖的副作用\r\n setItem: nullDep as (key: string, value: string) => void,\r\n getItem: nullDep as (key: string) => string | undefined,\r\n\r\n // render功能依赖的副作用\r\n getNodeByID: nullDep as (id?: string) => Promise<S_Node | undefined>,\r\n getDocPathBySY: nullDep as (sy?: S_Node) => Promise<string | undefined>,\r\n getDocByChildID: nullDep as (id: string) => Promise<S_Node | undefined>,\r\n getHPathByID_Node: nullDep as (id_node: string | S_Node) => Promise<string>,\r\n}\r\n","export function deepAssign<T>(target: any, source: any, config = { add: true, update: true }): T {\r\n for (let key in source) {\r\n if (source.hasOwnProperty(key)) {\r\n if (source[key] instanceof Object && !Array.isArray(source[key])) {\r\n // 如果属性是对象且不是数组,则递归执行深度合并\r\n if (!target.hasOwnProperty(key)) {\r\n // 目标对象不存在该属性则创建空对象\r\n target[key] = {};\r\n }\r\n deepAssign(target[key], source[key], config);\r\n } else {\r\n // 如果属性不是对象或者是数组,则直接赋值\r\n if (!target.hasOwnProperty(key) && config.add) {\r\n // 目标属性不存在属于新增\r\n target[key] = source[key];\r\n } else if (config.update) {\r\n // 更新\r\n target[key] = source[key];\r\n }\r\n }\r\n }\r\n }\r\n return target;\r\n }\r\n","import { storeDep } from '~/core/dependency.ts'\r\nimport { deepAssign } from '~/util/deep_assign.ts'\r\nimport { computed, reactive, watch } from 'vue'\r\nimport { notebook } from './siyuan_type.ts'\r\nimport packageJson from '~/../package.json' with { type: 'json' };\r\nconst version = packageJson.version\r\n\r\n/** 不要在运行时修改这个对象,他只应该在代码中配置 */\r\nconst defaultConfig = {\r\n name: 'default',\r\n /** 需要编译的笔记本 */\r\n notebook: {} as notebook,\r\n /** 思源的鉴权key */\r\n authorized: '',\r\n /** 思源的api服务地址 */\r\n apiPrefix: 'http://127.0.0.1:6806',\r\n /** 打包成 zip */\r\n compressedZip: true,\r\n /** 不将 publicZip 打包到 zip 包中 */\r\n // withoutPublicZip: true,\r\n /** 不复制 assets/ ,勾选此选项则需要自行处理资源文件 */\r\n excludeAssetsCopy: false,\r\n /** 输出站点地图相关 */\r\n sitemap: {\r\n /** 控制是否输出 sitemap.xml,不影响 rss 选项 */\r\n enable: true,\r\n /** 默认为 \".\" 生成路径例如 \"./record/思源笔记.html\"\r\n * 但 sitemap 并不建议采用相对路径所以应该替换成例如 \"https://shenzilong.cn\"\r\n * 则会生成 \"https://shenzilong.cn/record/思源笔记.html\" 这样的绝对路径\r\n * 参见 https://www.sitemaps.org/protocol.html#escaping\r\n */\r\n sitePrefix: '.',\r\n /** 站点地址 */\r\n siteLink: '',\r\n /** 站点描述 */\r\n description: '',\r\n /** 站点标题 */\r\n title: '',\r\n /** 开启 rss 生成,对于文件名为 .rss.xml 结尾的文档生效 */\r\n rss: true,\r\n },\r\n /** 开启增量编译,当开启增量编译时,\r\n * 在编译过程中会依据 __skipBuilds__ 的内容来跳过一些没有变化不需要重新输出的内容\r\n */\r\n enableIncrementalCompilation: false,\r\n /**\r\n * 要全量编译文档时将此选项设置为false,当OceanPress版本和上次编译时不同时会忽略此属性全量编译文档\r\n */\r\n enableIncrementalCompilation_doc: true,\r\n /** 跳过编译的资源 */\r\n __skipBuilds__: {} as {\r\n [id: string]:\r\n | {\r\n hash?: string\r\n /** 此文档正向引用的其他文档的id */ refs?: string[]\r\n /** 挂件快照的更新时间 */ updated?: string\r\n }\r\n | undefined\r\n },\r\n\r\n // cdn: {\r\n // /** 思源 js、css等文件的前缀 */\r\n // siyuanPrefix:\r\n // 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/notebook/',\r\n // /** 思源 js、css等文件zip包地址 */\r\n // publicZip:\r\n // 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/public.zip',\r\n // },\r\n /** s3 上传配置\r\n * https://help.aliyun.com/zh/oss/developer-reference/use-amazon-s3-sdks-to-access-oss#section-2ri-suq-pb3\r\n */\r\n s3: {\r\n enable: false,\r\n bucket: '',\r\n region: '',\r\n pathPrefix: '',\r\n endpoint: '',\r\n accessKeyId: '',\r\n secretAccessKey: '',\r\n },\r\n /** 部署到 oceanPressServer 的配置 */\r\n oceanPressServer:{\r\n enable: false,\r\n apiBase:'',\r\n apiKey:'',\r\n },\r\n meilisearch: {\r\n enable: false,\r\n host: '',\r\n apiKey: '',\r\n indexName: '',\r\n },\r\n /** html模板嵌入代码块,会将此处配置中的代码嵌入到生成的html所对应的位置 */\r\n embedCode: {\r\n head: '',\r\n beforeBody: '',\r\n afterBody: `<footer>\r\n<p style=\"text-align:center;margin:15px 0;\">\r\n 技术支持:\r\n <a target=\"_blank\" href=\"https://github.com/2234839/oceanPress_js\">OceanPress</a> |\r\n 开发者:\r\n <a target=\"_blank\" href=\"https://shenzilong.cn\">崮生(子虚)</a>\r\n</p>\r\n</footer>`,\r\n },\r\n OceanPress: {\r\n /** 此配置文件编译时的版本 */\r\n version: version,\r\n },\r\n}\r\nexport type Config = typeof defaultConfig\r\nexport const configs = reactive({\r\n /** 当前所使用的配置项的 key */\r\n __current__: 'default' as const,\r\n /** 为true是表示是代码中设置的默认值,不会保存到本地,避免覆盖之前保存的数据,在加载本地配置后会自动修改为false */\r\n __init__: true,\r\n default: deepAssign<typeof defaultConfig>({}, defaultConfig),\r\n})\r\n\r\nexport function addConfig(name: string, value?: typeof defaultConfig) {\r\n configs[name as 'default'] = deepAssign<typeof defaultConfig>(\r\n {},\r\n value ?? defaultConfig,\r\n )\r\n}\r\n/** 加载配置文件 */\r\nexport const loadConfigFile = (c?: typeof configs) => {\r\n if (c) {\r\n deepAssign(configs, c)\r\n } else {\r\n const localConfig = storeDep.getItem('configs')\r\n if (localConfig) {\r\n /** 从本地存储加载配置 */\r\n deepAssign(configs, JSON.parse(localConfig))\r\n }\r\n }\r\n\r\n Object.entries(configs)\r\n .filter(([key]) => key.startsWith('__') === false)\r\n .forEach(([_key, obj]) => {\r\n /** 将新增配置项更新到旧配置上 */\r\n deepAssign(obj, defaultConfig, { update: false, add: true })\r\n })\r\n}\r\nexport const currentConfig = computed(() => configs[configs.__current__])\r\n\r\n/** 应该要给用户配置的,但目前没有什么好方法,所以暂时不给配置 */\r\nexport const tempConfig = {\r\n cdn: {\r\n /** 思源 js、css等文件的前缀 */\r\n siyuanPrefix:\r\n 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@latest/apps/frontend/public/notebook/',\r\n /** 思源 js、css等文件zip包地址 */\r\n publicZip:\r\n 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/public.zip',\r\n },\r\n withoutPublicZip:true,\r\n}\r\n\r\nexport const saveConfig = () => {\r\n if (configs.__init__ === false)\r\n storeDep.setItem('configs', JSON.stringify(configs, null, 2))\r\n}\r\n\r\nlet timer: ReturnType<typeof setTimeout> | null = null\r\n/** 防抖的保存配置 */\r\nexport const debounceSaveConfig = () => {\r\n if (timer) {\r\n clearTimeout(timer)\r\n }\r\n timer = setTimeout(() => {\r\n saveConfig()\r\n timer = null\r\n }, 700)\r\n}\r\nwatch(configs, debounceSaveConfig, { deep: true })\r\n\r\nconfigs.__init__ = false\r\n\r\n/** 浏览器环境下,直接尝试加载配置 */\r\nif (globalThis.document) {\r\n loadConfigFile()\r\n}\r\n","{\n \"name\": \"oceanpress\",\n \"private\": true,\n \"version\": \"1.0.2\",\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"cli\": \"tsx ./src/cli.ts\",\n \"cli_watch\": \"tsx watch ./src/cli.ts\",\n \"build\": \"vite build && npm run build_lib\",\n \"build_lib\": \"vite build --config vite.sw.config.ts\",\n \"build_npmlib\": \"vite build --mode library\",\n \"build_plugin_ui\": \"vite build --config vite.plugin.config.ts\",\n \"dev_plugin_ui\": \"vite build --watch --config vite.plugin.config.ts\",\n \"generate_dependency_graph\": \"depcruise src --include-only '^src' --output-type dot > ./assets/dep.dot\",\n \"preview\": \"vite preview\"\n },\n \"bin\": \"./dist/cli.js\",\n \"dependencies\": {\n \"@aws-sdk/client-s3\": \"^3.758.0\",\n \"@hono/node-server\": \"^1.13.8\",\n \"cheerio\": \"1.0.0\",\n \"commander\": \"^13.1.0\",\n \"fzstd\": \"^0.1.1\",\n \"hono\": \"^4.7.4\",\n \"jszip\": \"^3.10.1\",\n \"meilisearch\": \"^0.49.0\",\n \"naive-ui\": \"^2.41.0\",\n \"oceanpress-rpc\": \"workspace:*\",\n \"oceanpress-server\": \"workspace:*\",\n \"octokit\": \"^4.1.2\",\n \"superjson\": \"^2.2.2\",\n \"tsx\": \"^4.19.3\",\n \"vditor\": \"^3.10.9\",\n \"vue\": \"^3.5.13\",\n \"vue-router\": \"^4.5.0\",\n \"zstd-codec\": \"^0.1.5\"\n },\n \"devDependencies\": {\n \"@vitejs/plugin-vue\": \"^5.2.1\",\n \"@vitejs/plugin-vue-jsx\": \"^4.1.1\",\n \"dependency-cruiser\": \"^16.10.0\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.2\",\n \"vite\": \"^6.2.2\",\n \"vite-plugin-vue-devtools\": \"^7.7.2\",\n \"vue-tsc\": \"^2.2.8\"\n }\n}","import JSZip from 'jszip'\n\n/** 下载zip */\nexport async function downloadZIP(\n docTree: { [htmlPath: string]: string | ArrayBuffer },\n config?: { publicZip?: string; withoutZip?: boolean },\n) {\n const content = await genZIP(docTree, config)\n if (globalThis.document) {\n // 将ZIP文件保存为下载\n const link = document.createElement('a')\n link.href = URL.createObjectURL(content)\n link.download = `notebook.zip`\n link.click()\n } else {\n //TODO node 环境下需要写文件\n }\n}\n\nexport async function genZIP(\n docTree: { [htmlPath: string]: string | ArrayBuffer },\n config?: {\n /** 默认的public.zip压缩包内容路径,默认为/public.zip */\n publicZip?: string\n /** 是否不包含默认的public.zip压缩包内容,设置为 true 则会不下载 public.zip 内容合并使用 */\n withoutZip?: boolean\n },\n) {\n const zip = new JSZip()\n if (config?.withoutZip !== true) {\n const presetZip = await (\n await fetch(config?.publicZip ?? '/public.zip')\n ).arrayBuffer()\n await zip.loadAsync(presetZip)\n }\n for (const [path, html] of Object.entries(docTree)) {\n const newPath = path.startsWith('/') ? path.slice(1) : path\n zip.file(newPath, html)\n }\n return await zip.generateAsync({ type: 'blob' })\n}\n","import { Meilisearch, Index } from 'meilisearch'\r\nimport { OceanPressPlugin } from '~/core/ocean_press.ts'\r\nimport { load } from 'cheerio'\r\ntype doc = {\r\n id: string\r\n title?: string\r\n content: string\r\n url: string\r\n lvl0?: string\r\n lvl1?: string\r\n lvl2?: string\r\n lvl3?: string\r\n lvl4?: string\r\n lvl5?: string\r\n lvl6?: string\r\n}\r\nexport class MeilisearchPlugin implements OceanPressPlugin {\r\n _melisearch: Meilisearch | undefined\r\n _index: Index | undefined\r\n _indexName: string\r\n host: string\r\n apiKey: string\r\n constructor(option: { host: string; apiKey: string; indexName: string }) {\r\n this.host = option.host\r\n this.apiKey = option.apiKey\r\n this._indexName = option.indexName\r\n }\r\n async _getMeliSearch() {\r\n if (this._melisearch === undefined) {\r\n this._melisearch = new Meilisearch({\r\n host: this.host,\r\n apiKey: this.apiKey,\r\n })\r\n }\r\n return this._melisearch!\r\n }\r\n async _getIndex() {\r\n if (this._index === undefined) {\r\n const meilisearch = await this._getMeliSearch()\r\n this._index = meilisearch.index(this._indexName)\r\n }\r\n return this._index!\r\n }\r\n docs: { [id: string]: doc } = {}\r\n async addDocument(doc: doc) {\r\n this.docs[doc.id] = doc\r\n }\r\n async updateDocument() {\r\n console.log(`开始上传数据到 ${this.host}`)\r\n const index = await this._getIndex()\r\n const res = await index.addDocuments(Object.values(this.docs))\r\n console.log(`上传结果`, res)\r\n }\r\n build_onFileTree: OceanPressPlugin['build_onFileTree'] = (c, next) => {\r\n const [tree] = c\r\n console.log('开始生成 meilisearch 所需数据结构')\r\n\r\n const htmlTree = Object.keys(tree)\r\n .filter((path) => path.endsWith('.html'))\r\n .map((path) => [path, tree[path]] as const)\r\n for (const [path, html] of htmlTree) {\r\n const $ = load(html.toString())\r\n const entries = $('.h1,.h2,.h3,.h4,.h5,.h6,.p').toArray()\r\n const level: Record<string, string> = { lvl0: $('title').text() }\r\n for (const el of entries) {\r\n /** h1~h6、p */\r\n const c = el.attribs.class\r\n if (c !== 'p') {\r\n Object.keys(level).forEach((lv) => {\r\n if (lv.substring(3, 4) > c.substring(1, 2)) {\r\n /** 跳出层级 */\r\n delete level[lv]\r\n }\r\n })\r\n /** 进入层级 */\r\n level[`lvl${c.substring(1, 2)}`] = $(el).text()\r\n }\r\n this.addDocument({\r\n id: el.attribs.id,\r\n content: $(el).text(),\r\n url: `${path}#${el.attribs.id}`,\r\n ...level,\r\n })\r\n }\r\n\r\n if (path.endsWith('index.html')) break\r\n }\r\n this.updateDocument()\r\n return next(tree)\r\n }\r\n}\r\n","/** 基于洋葱 HOOk 机制的插件管理器\r\n * 我感觉这个手搓的插件机制还可以,类型完备,可拓展性强,\r\n */\r\nexport class PluginCenter<T extends Record<string, (...args: any[]) => any>> {\r\n plugins: PluginCenter<T>['pluginType'][] = []\r\n registerPlugin(plugin: PluginCenter<T>['pluginType']) {\r\n this.plugins.push(plugin)\r\n }\r\n removePlugin(plugin: PluginCenter<T>['pluginType']) {\r\n this.plugins = this.plugins.filter((p) => p !== plugin)\r\n }\r\n /** 洋葱hook调用机制的实现 */\r\n callFn<R extends keyof PluginCenter<T>['pluginType']>(\r\n name: R,\r\n fn: GetMiddlewareFunc<Required<PluginCenter<T>['pluginType']>[R]>,\r\n ) {\r\n return ((...arg: any) => {\r\n // 此处可优化,不必每次都重新生成 middlewareRunner\r\n const m = new middlewareRunner(fn)\r\n // 注入 plugins 中的对应中间件\r\n for (const plugin of this.plugins) {\r\n const middleware = plugin[name]\r\n if (middleware) {\r\n m.use(middleware)\r\n }\r\n }\r\n return m.runMiddlewareHandel(...arg)\r\n }) as GetMiddlewareFunc<Required<PluginCenter<T>['pluginType']>[R]>\r\n }\r\n /** 辅助类型,不可调用! */\r\n pluginType: {\r\n [key in keyof PluginCenter<T>['_funMap']]?: FuncMiddlewares<\r\n PluginCenter<T>['_funMap'][key]\r\n >\r\n } = 0 as any\r\n /** 对需要调用的函数进行代理,完成插件hook介入。 */\r\n fun: PluginCenter<T>['_funMap']\r\n constructor(\r\n /** 原始函数映射表,这里的函数全部可以被插件处理 */\r\n public _funMap: T,\r\n ) {\r\n const that = this\r\n // 可以改成生成对象 {} 的方式,比 proxy 开销要小\r\n this.fun = new Proxy({} as T, {\r\n get(_target, propertyKey, receiver) {\r\n const method = Reflect.get(that._funMap, propertyKey, receiver)\r\n if (typeof method === 'function') {\r\n return (...args: any) => {\r\n return that.callFn(\r\n propertyKey as keyof T,\r\n //@ts-ignore 懒得推类型了。属于内部实现,就直接忽略掉吧\r\n method,\r\n )(...args)\r\n }\r\n }\r\n return method\r\n },\r\n })\r\n }\r\n}\r\n\r\ntype GetMiddlewareFunc<T> = T extends FuncMiddlewares<infer R> ? R : never\r\n\r\n// 小中间件实现,接收一个函数 handel 作为最终执行的函数,当执行 runMiddlewareHandel 时等价于执行 Handel\r\n// 通过 use 注册中间件,类似于洋葱路由,先注册的先执行\r\ntype FuncMiddlewares<Handel extends (...args: any[]) => any> = (\r\n ctx: Parameters<Handel>,\r\n next: Handel,\r\n) => ReturnType<Handel>\r\nclass middlewareRunner<Handel extends (...args: any[]) => any> {\r\n middlewares: FuncMiddlewares<Handel>[] = []\r\n constructor(public handel: Handel) {}\r\n use(middleware: FuncMiddlewares<Handel>) {\r\n this.middlewares.push(middleware)\r\n }\r\n runMiddlewareHandel(...ctx: Parameters<typeof this.handel>) {\r\n let index = 0\r\n const next = ((...ctx2: Parameters<Handel>) => {\r\n const middleware = this.middlewares[index]\r\n index++\r\n if (middleware === undefined) {\r\n return this.handel.call(this, ...ctx2)\r\n }\r\n return middleware(ctx2, next)\r\n }) as Handel\r\n return next.call(this, ...ctx)\r\n }\r\n}\r\n","import type { OceanPressPlugin } from '~/core/ocean_press.ts'\r\nimport type { uploadFiles } from './interface.ts'\r\nimport { S3 } from '@aws-sdk/client-s3'\r\n\r\n/** 上传数据到 s3 适配云端 */\r\nexport const s3Upload_plugin: OceanPressPlugin = {\r\n build: async function ([config, effect, other], next) {\r\n const res = await next(config, effect, {\r\n ...other,\r\n\r\n onFileTree: async (tree) => {\r\n if (other?.onFileTree) {\r\n // 维持原有其他监听程序\r\n await other.onFileTree(tree)\r\n }\r\n for await (const [fileName, ETag] of s3_uploads(tree, config)) {\r\n effect.log(`上传: ${fileName} ${ETag}`)\r\n }\r\n },\r\n })\r\n effect.log(`s3 上传完毕`)\r\n return res\r\n },\r\n}\r\nconst s3_uploads: uploadFiles = async function* (tree, config) {\r\n // https://help.aliyun.com/zh/oss/developer-reference/use-amazon-s3-sdks-to-access-oss#section-2ri-suq-pb3\r\n\r\n const s3 = new S3({\r\n region: config.s3.region,\r\n endpoint: config.s3.endpoint,\r\n credentials: {\r\n accessKeyId: config.s3.accessKeyId,\r\n secretAccessKey: config.s3.secretAccessKey,\r\n },\r\n })\r\n // 将文件逐个上传至 s3\r\n // TODO 可改成并发上传,以缩短时间\r\n const encoder = new TextEncoder()\r\n for (const [path, value] of Object.entries(tree)) {\r\n let buffer: Uint8Array\r\n if (typeof value === 'string') {\r\n buffer = encoder.encode(value)\r\n } else {\r\n buffer = new Uint8Array(value)\r\n }\r\n const r = await s3.putObject({\r\n Bucket: config.s3.bucket,\r\n Key: (config.s3.pathPrefix + path).replace(/\\/\\//g, '/'),\r\n Body: buffer,\r\n })\r\n yield [path, r.ETag] as const\r\n }\r\n}\r\n","export async function htmlTemplate(\r\n p: { htmlContent: string; title: string; level: number },\r\n config?: {\r\n siyuanPrefix: string\r\n embedCode?: { head?: string; beforeBody?: string; afterBody?: string }\r\n },\r\n) {\r\n /** 根据level有几级返回多少个 '../' ,用于解决 file协议打开html文档无法正常加载资源 */\r\n let prePath = ''\r\n if (config?.siyuanPrefix) {\r\n prePath = config.siyuanPrefix\r\n } else {\r\n for (let i = 0; i < p.level; i++) {\r\n prePath += '../'\r\n }\r\n }\r\n const version = '2.10.5'\r\n /** 思源中导出 html 代码: https://github1s.com/siyuan-note/siyuan/blob/HEAD/app/src/protyle/export/index.ts#L652 */\r\n //data-theme-mode=\"dark\" data-light-theme=\"daylight\" data-dark-theme=\"midnight\"\r\n return `<!DOCTYPE html>\r\n<html lang=\"zh_CN\" data-theme-mode=\"light\" data-light-theme=\"daylight\" data-dark-theme=\"midnight\">\r\n<head>\r\n ${config?.embedCode?.head ?? ''}\r\n <meta charset=\"utf-8\" />\r\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\r\n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\r\n <meta name=\"mobile-web-app-capable\" content=\"yes\" />\r\n <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\" />\r\n <link rel=\"stylesheet\" type=\"text/css\" id=\"baseStyle\" href=\"${prePath}stage/build/export/base.css?${version}\"/>\r\n <script>\r\n function isNightTime() {\r\n const currentHour = new Date().getHours();\r\n return currentHour >= 18 || currentHour < 6;\r\n }\r\n document.write('<link rel=\"stylesheet\" type=\"text/css\" id=\"themeDefaultStyle\" href=\"${prePath}appearance/themes/'+(isNightTime()?'midnight':'daylight')+'/theme.css?${version}\"/>');\r\n </script>\r\n <link rel=\"stylesheet\" type=\"text/css\" href=\"${prePath}appearance/oceanpress.css\"/>\r\n <title>${p.title}</title>\r\n</head>\r\n<body>\r\n ${config?.embedCode?.beforeBody ?? ''}\r\n <div class=\"protyle-wysiwyg protyle-wysiwyg--attr\" id=\"preview\">\r\n ${p.htmlContent}\r\n </div>\r\n <script src=\"${prePath}appearance/icons/material/icon.js?${version}\"></script>\r\n <script src=\"${prePath}stage/build/export/protyle-method.js?${version}\"></script>\r\n <script src=\"${prePath}stage/protyle/js/lute/lute.min.js?${version}\"></script>\r\n <script>\r\n window.siyuan = {\r\n config: {\r\n appearance: {\r\n mode: isNightTime()?1:0,//主题 明亮=0 暗黑=1\r\n codeBlockThemeDark: \"base16/dracula\",\r\n codeBlockThemeLight: \"github\",\r\n },\r\n editor: {\r\n codeLineWrap: true,\r\n codeLigatures: false,\r\n plantUMLServePath: \"https://www.plantuml.com/plantuml/svg/~1\",\r\n codeSyntaxHighlightLineNum: true,\r\n katexMacros: JSON.stringify({}),\r\n },\r\n },\r\n languages: { copy: \"复制\" },\r\n };\r\n const cdn = \"${prePath}stage/protyle\";\r\n const previewElement = document.getElementById(\"preview\");\r\n\r\n Protyle.highlightRender(previewElement, cdn);\r\n Protyle.mathRender(previewElement, cdn, false);\r\n Protyle.mermaidRender(previewElement, cdn);\r\n Protyle.flowchartRender(previewElement, cdn);\r\n Protyle.graphvizRender(previewElement, cdn);\r\n Protyle.chartRender(previewElement, cdn);\r\n Protyle.mindmapRender(previewElement, cdn);\r\n Protyle.abcRender(previewElement, cdn);\r\n Protyle.htmlRender(previewElement);\r\n Protyle.plantumlRender(previewElement, cdn);\r\n document.querySelectorAll(\".protyle-action__copy\").forEach((item) => {\r\n item.addEventListener(\"click\", (event) => {\r\n navigator.clipboard.writeText(\r\n item.parentElement.nextElementSibling.textContent.trimEnd(),\r\n );\r\n event.preventDefault();\r\n event.stopPropagation();\r\n });\r\n });\r\n </script>\r\n ${config?.embedCode?.afterBody ?? ''}\r\n</body>\r\n</html>`\r\n}\r\n","/** html 实体转义 https://www.sitemaps.org/protocol.html#escaping */\r\nexport function escaping(s: string) {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/\"/g, \""\")\r\n .replace(/'/g, \"&apos\");\r\n}\r\nexport function unescaping(s: string) {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/&#(\\d+);/g, (_sub,code) => {\r\n return String.fromCharCode(Number(code));\r\n });\r\n}\r\n","/** ════════════════════════🏳🌈 实用功能 🏳🌈════════════════════════\r\n * 利用 composition-api 实现的一些实用功能\r\n ** ════════════════════════🚧 实用功能 🚧════════════════════════ */\r\nimport { customRef, nextTick, watch, watchEffect, WatchSource } from \"vue\";\r\n\r\nexport class PromiseObj<T, Err = Error> {\r\n pending = false;\r\n fulfilled = false;\r\n rejected = false;\r\n data = {} as T;\r\n error = {} as Err;\r\n _p = Promise.resolve() as Promise<unknown>;\r\n setP(p: Promise<unknown>) {\r\n this._p = p;\r\n }\r\n equalP(p: Promise<unknown>) {\r\n return this._p === p;\r\n }\r\n reLoad() {}\r\n setValue(_data: T) {}\r\n}\r\nexport const continueLoading = Symbol();\r\n\r\nexport interface usePromiseComputedOptions<T> {\r\n /** 函数内的依赖变更的时候就重新计算,指定了 deps 则不会依赖于 getter 内的 ref 了\r\n * tips: 可以将其设置为 `()=>[]` 从而不主动执行 getter(), 可以通过调用返回的 reLoad 来调用 getter()\r\n */\r\n deps?: WatchSource<any>;\r\n /** data 的默认值 */\r\n defaultData?: T;\r\n /** 如果这个参数没有输入的话,应该自行调用 PromiseObj.setValue */\r\n getter?: () => Promise<T> | typeof continueLoading;\r\n /** 处理数据是否要和之前的数据进行合并 */\r\n dataMergeFun?: (oldData: T, newData: T) => T;\r\n}\r\n\r\nexport function usePromiseComputed<T, Err = Error>({\r\n deps,\r\n getter,\r\n dataMergeFun = (_oldData, newData) => newData,\r\n defaultData,\r\n}: usePromiseComputedOptions<T>) {\r\n const r = new PromiseObj<T, Err>();\r\n if (defaultData !== undefined) {\r\n r.data = defaultData;\r\n }\r\n return customRef<PromiseObj<T, Err>>((track, trigger) => {\r\n if (!deps && getter) {\r\n watchEffect(() => update(getter()));\r\n } else if (deps && getter) {\r\n if (deps instanceof Function) {\r\n const depsSource = deps();\r\n if (Array.isArray(depsSource) && depsSource.length === 0) {\r\n // 特性,传递空数组则先不执行 getter ,由用户自己决定时机执行 reload\r\n } else {\r\n watch(deps, () => update(getter()), { immediate: true });\r\n }\r\n } else {\r\n watch(deps, () => update(getter()), { immediate: true });\r\n }\r\n }\r\n function update(p: Promise<T> | typeof continueLoading) {\r\n r.pending = true;\r\n r.fulfilled = false;\r\n r.rejected = false;\r\n /** 返回值为继续加载则,getter函数中有特殊的判断逻辑,依据当前的 deps 还无法得出值,需要继续 loading */\r\n if (p === continueLoading) {\r\n nextTick(trigger);\r\n return;\r\n }\r\n r.setP(p);\r\n // 立即触发会导致死循环,所以包裹一层\r\n nextTick(trigger);\r\n p.then((res) => {\r\n // 避免 「求值fun」 第一次执行产生的 promise 比 第二次产生的后结束 导致 数据错误的采用了第一次的\r\n if (r.equalP(p)) {\r\n r.pending = false;\r\n r.fulfilled = true;\r\n r.data = dataMergeFun(r.data, res);\r\n }\r\n })\r\n .catch((e) => {\r\n if (r.equalP(p)) {\r\n r.pending = false;\r\n r.rejected = true;\r\n r.error = e;\r\n }\r\n })\r\n .finally(() => {\r\n if (r.equalP(p)) {\r\n trigger();\r\n }\r\n });\r\n }\r\n r.reLoad = () => {\r\n if (getter) update(getter());\r\n // 否则是用户通过 setValue 设定的值,是无法reLoad的\r\n };\r\n r.setValue = (data) => {\r\n r.pending = false;\r\n r.fulfilled = true;\r\n r.data = dataMergeFun(r.data, data);\r\n trigger();\r\n };\r\n return {\r\n get() {\r\n track();\r\n return r;\r\n },\r\n set(_newValue) {\r\n console.warn(\"不可设置值\");\r\n },\r\n };\r\n });\r\n}\r\n\r\nexport namespace usePromiseComputed {\r\n /** 辅助方法,返回一个deps为 `()=>{}` 的 PromiseObj */\r\n export function nullDeps<T>(getter: usePromiseComputedOptions<T>[\"getter\"]) {\r\n return usePromiseComputed({\r\n deps: () => [],\r\n getter,\r\n });\r\n }\r\n export function fn<T>(fn: () => Promise<T> | typeof continueLoading) {\r\n const p = usePromiseComputed({\r\n getter() {\r\n return fn();\r\n },\r\n });\r\n return p;\r\n }\r\n}\r\n\r\n/** 防抖的 ref */\r\nexport function useDebouncedRef<T>(value: T, delay = 200) {\r\n let timeout = 0;\r\n return customRef<T>((track, trigger) => {\r\n return {\r\n get() {\r\n track();\r\n return value;\r\n },\r\n set(newValue) {\r\n clearTimeout(timeout);\r\n timeout = setTimeout(() => {\r\n value = newValue;\r\n trigger();\r\n }, delay) as unknown as number;\r\n },\r\n };\r\n });\r\n}\r\n","import { Ref } from 'vue'\r\nimport {\r\n PromiseObj,\r\n usePromiseComputed,\r\n} from '../components/data_promise/index.ts'\r\nimport { NodeDocument, S_Node, file, notebook } from './siyuan_type.ts'\r\nimport { currentConfig } from '~/core/config.ts'\r\n\r\n/** https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md */\r\nexport interface api {\r\n /**\r\n * 列出笔记本\r\n */\r\n notebook_lsNotebooks(): {\r\n notebooks: notebook[]\r\n }\r\n block_getBlockInfo(p: { id: string }): {\r\n box: '20210816161940-zo21go1'\r\n path: '/20201104153359-sk9a3yg.sy'\r\n rootChildID: '20201104153359-sk9a3yg'\r\n rootID: '20201104153359-sk9a3yg'\r\n rootIcon: ''\r\n rootTitle: 'markdown'\r\n }\r\n filetree_listDocsByPath(p: { notebook: notebook['id']; path: '/' }): {\r\n box: '20210816161940-zo21go1'\r\n files: file[]\r\n path: '/'\r\n }\r\n filetree_getHPathByID(p: { id: file['id'] }): '/foo/bar'\r\n filetree_getDoc(p: {\r\n id: file['id']\r\n isBacklink: false\r\n mode: 0\r\n size: 48\r\n }): NodeDocument\r\n export_exportHTML(p: {\r\n id: file['id']\r\n pdf: false\r\n /** 为空时思源不会写文件 https://github.com/siyuan-note/siyuan/blob/master/kernel/model/export.go :ExportHTML */\r\n savePath: ''\r\n }): {\r\n content: '<html>'\r\n id: '20200825162036-4dx365o'\r\n name: '排版元素'\r\n }\r\n /** 执行 SQL 查询 https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#执行-sql-查询 */\r\n query_sql(p: {\r\n /** SELECT * FROM blocks WHERE content LIKE'%content%' LIMIT 7 */ stmt: string\r\n }): any[]\r\n /** 获取文件 https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#获取文件\r\n */\r\n file_getFile(p: { path: string }): S_Node | ArrayBuffer\r\n get_assets(p: { path: string }): ArrayBuffer\r\n /** 根据人类可读路径获取 IDs https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#根据人类可读路径获取-ids */\r\n filetree_getIDsByHPath(p: {\r\n /** /foo/bar */\r\n path: string\r\n /** 20210808180117-czj9bvb */\r\n notebook: string\r\n }): string[]\r\n}\r\ntype apiPromisify = {\r\n readonly [K in keyof api]: (\r\n ...arg: Parameters<api[K]>\r\n ) => Promise<unPromise<ReturnType<api[K]>>>\r\n}\r\n\r\n/** 解开 promise 类型包装 */\r\ndeclare type unPromise<T> = T extends Promise<infer R> ? R : T\r\nlet rpcCount = 0\r\nasync function rpc(method: string, arg: any) {\r\n const apiPrefix = currentConfig.value.apiPrefix\r\n const Authorization = currentConfig.value.authorized\r\n rpcCount++\r\n\r\n if (method === 'get_assets') {\r\n return fetch(`${apiPrefix}/${arg[0].path}`, {\r\n headers: {\r\n Authorization: `Token ${Authorization}`,\r\n },\r\n body: null,\r\n method: 'GET',\r\n mode: 'cors',\r\n }).then((r) => r.arrayBuffer())\r\n }\r\n const res = await fetch(`${apiPrefix}/api/${method.replace(/_/g, '/')}`, {\r\n headers: {\r\n Authorization: `Token ${Authorization}`,\r\n },\r\n body: JSON.stringify(arg[0]),\r\n method: 'POST',\r\n }).catch((err: Error) => {\r\n err.message = `访问思源接口时出错了,请检查思源服务是否启动以及配置接口地址是否正确。`\r\n throw err\r\n })\r\n if (method === 'file_getFile') {\r\n const path = arg[0].path as string\r\n if (path.endsWith('.sy')) {\r\n return await res.json()\r\n } else {\r\n const buffer = await res.arrayBuffer()\r\n if (buffer.byteLength < 200) {\r\n const decoder = new TextDecoder()\r\n const text = decoder.decode(buffer)\r\n if (JSON.parse(text).code === 404) {\r\n throw new Error(`文件不存在: ${path}`)\r\n }\r\n }\r\n return buffer\r\n }\r\n }\r\n const json = await res.json()\r\n\r\n if (json.code !== 0) {\r\n throw new Error(json.msg)\r\n }\r\n return json.data\r\n}\r\n\r\n/** 包装了一次的 RC 方便跳转到函数定义 */\r\nexport const API = new Proxy(\r\n {},\r\n {\r\n get(_, method: string) {\r\n return (...arg: any) => rpc(method, arg)\r\n },\r\n },\r\n) as apiPromisify\r\n\r\ntype vApi = {\r\n readonly [K in keyof api]: (\r\n ...arg: Parameters<api[K]>\r\n ) => Ref<PromiseObj<unPromise<ReturnType<api[K]>>, Error>>\r\n}\r\n/** 使用 usePromiseComputed 包装的方法,便于使用 */\r\nexport const vApi = new Proxy(\r\n {},\r\n {\r\n get(_, method: string) {\r\n return (...arg: any) => usePromiseComputed.fn(() => rpc(method, arg))\r\n },\r\n },\r\n) as vApi\r\n","import { escaping, unescaping } from '~/util/escaping.ts'\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, S_Node, NodeType } from './siyuan_type.ts'\r\nimport { storeDep } from '~/core/dependency.ts'\r\n\r\nexport type RenderHTML = typeof renderHTML\r\nexport type Render = typeof render\r\n\r\nexport async function renderHTML(\r\n sy: S_Node | undefined,\r\n /**\r\n * renderHTML 内部会创建一个 renderInstance 的浅克隆\r\n * 用来维护 renderHTML.nodeStack 的正常运转\r\n */\r\n renderInstance: Render = getRender(),\r\n): Promise<string> {\r\n if (sy === undefined) return ''\r\n const renderObj: Render = {\r\n ...renderInstance,\r\n nodeStack: [\r\n /** 避免让所有的 renderInstance.nodeStack 是同一个对象 ,所以这里复制一个新的 */ ...renderInstance.nodeStack,\r\n ],\r\n }\r\n if (\r\n renderInstance.nodeStack.find(\r\n (node) => node.ID && sy.ID && node.ID === sy.ID,\r\n )\r\n ) {\r\n return warnDiv(\r\n '循环引用',\r\n [...renderInstance.nodeStack, sy].map((el) => el.ID),\r\n )\r\n }\r\n if (renderObj[sy.Type] === undefined) {\r\n return warnDiv(\r\n `没有找到对应的渲染方法 ${sy.Type} ${renderObj.nodeStack[0].Properties?.title}`,\r\n )\r\n } else {\r\n /** 入栈 */\r\n renderObj.nodeStack.push(sy)\r\n /** 维护引用关系 */\r\n if (sy.ID && renderInstance.nodeStack[0]?.ID) {\r\n const targetDoc = await storeDep.getDocByChildID(sy.ID)\r\n const currentDoc = renderInstance.nodeStack[0]\r\n if (\r\n targetDoc?.ID !== undefined &&\r\n targetDoc.ID !== currentDoc.ID &&\r\n currentDoc.ID\r\n ) {\r\n /** 代表这个节点不在当前文档中,却在编译currentDoc时出现了,所以 currentDoc依赖(正向引用)targetDoc */\r\n // 记录引用 TODO 不应该在 render中之直接记录,该上报\r\n renderObj.refs.add(targetDoc.ID)\r\n }\r\n }\r\n const r = await renderObj[sy.Type]!(sy)\r\n /** 出栈 */\r\n renderObj.nodeStack.pop()\r\n return r\r\n }\r\n}\r\nfunction warnDiv(msg: string, ...args: any[]) {\r\n warn(msg, ...args)\r\n return `<div class=\"ft__smaller ft__secondary b3-form__space--small\">${msg}</div>`\r\n}\r\nfunction isRenderCode(sy: S_Node) {\r\n const mark = atob(\r\n sy.CodeBlockInfo ??\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockFenceInfoMarker')\r\n ?.CodeBlockInfo ??\r\n '',\r\n )\r\n return [\r\n [\r\n 'mindmap',\r\n 'mermaid',\r\n 'echarts',\r\n 'abc',\r\n 'graphviz',\r\n 'flowchart',\r\n 'plantuml',\r\n ].includes(mark),\r\n mark,\r\n ] as const\r\n}\r\nconst html = String.raw\r\nasync function childRender(sy: S_Node, renderInstance: typeof render) {\r\n let h = ''\r\n for await (const el of sy?.Children ?? []) {\r\n h += await renderHTML(el, renderInstance)\r\n }\r\n return h\r\n}\r\nfunction strAttr(\r\n sy: S_Node,\r\n config: {\r\n subtype_class?: string | [string, string]\r\n data_type?: string\r\n } = {},\r\n) {\r\n if (config?.subtype_class === undefined) {\r\n config.subtype_class = (() => {\r\n const typ_subtype =\r\n sy.ListData?.Typ === 1\r\n ? /** 有序列表 */ 'o'\r\n : sy.ListData?.Typ === 3\r\n ? /** 任务列表 */ 't'\r\n : /** 无序列表 */ 'u'\r\n\r\n if (sy.Type === 'NodeDocument') return 'h1'\r\n else if (sy.Type === 'NodeHeading') return `h${sy.HeadingLevel}`\r\n else if (sy.Type === 'NodeList') return [typ_subtype, 'list']\r\n else if (sy.Type === 'NodeListItem') return [typ_subtype, 'li']\r\n else if (sy.Type === 'NodeParagraph') return ['', 'p']\r\n else if (sy.Type === 'NodeImage') return ['', 'img']\r\n else if (sy.Type === 'NodeBlockquote') return ['', 'bq']\r\n else if (sy.Type === 'NodeSuperBlock') return ['', 'sb']\r\n else if (sy.Type === 'NodeCodeBlock') {\r\n const [yes, mark] = isRenderCode(sy)\r\n if (yes) {\r\n /** 脑图等需要渲染的块 */\r\n return [mark, 'render-node']\r\n } else {\r\n return ['', 'code-block']\r\n }\r\n } else if (sy.Type === 'NodeTable') return ['', 'table']\r\n else if (sy.Type === 'NodeThematicBreak') return ['', 'hr']\r\n else if (sy.Type === 'NodeMathBlock') return ['math', 'render-node']\r\n else if (sy.Type === 'NodeIFrame') return ['', 'iframe']\r\n else if (sy.Type === 'NodeVideo') return ['', 'iframe']\r\n else return ''\r\n })()\r\n }\r\n const attrObj = {} as { [k: string]: string }\r\n function addAttr(key: string, value: string) {\r\n attrObj[key] = value\r\n }\r\n if (sy.ID) {\r\n addAttr('id', sy.ID)\r\n addAttr('data-node-id', sy.ID)\r\n }\r\n\r\n if (sy?.TextMarkType === 'tag') {\r\n addAttr(`data-type`, sy.TextMarkType ?? '')\r\n } else {\r\n addAttr(`data-type`, config?.data_type ?? sy.Type)\r\n }\r\n if (sy.Properties?.updated) addAttr('updated', sy.Properties.updated)\r\n if (config?.subtype_class) {\r\n if (typeof config.subtype_class === 'string') {\r\n addAttr('data-subtype', config.subtype_class)\r\n addAttr('class', config.subtype_class)\r\n } else {\r\n if (config.subtype_class[0] !== '')\r\n addAttr('data-subtype', config.subtype_class[0])\r\n if (config.subtype_class[1] !== '')\r\n addAttr('class', config.subtype_class[1])\r\n }\r\n }\r\n if (sy.Properties) {\r\n Object.entries(sy.Properties).forEach(([k, v]) => addAttr(k, v))\r\n }\r\n if (sy.ListData?.Marker) addAttr('data-marker', atob(sy.ListData.Marker))\r\n if (\r\n /** 任务列表 */ sy.ListData?.Typ === 3 &&\r\n /** 该项被选中 */ sy.Children?.find(\r\n (el) => el.Type === 'NodeTaskListItemMarker',\r\n )?.TaskListItemChecked\r\n ) {\r\n attrObj['class'] = (attrObj['class'] ?? '') + ' protyle-task--done '\r\n }\r\n /** 不折叠任何项目 */ delete attrObj['fold']\r\n /** 避免任意元素上悬停都显示文档标题 */\r\n if (sy.Type === 'NodeDocument') delete attrObj['title']\r\n return Object.entries(attrObj)\r\n .map(([k, v]) => `${k}=\"${v}\"`)\r\n .join(' ')\r\n}\r\n/** 返回空字符串,一般用于不用解析的节点 */\r\nconst _emptyString = async (_sy: S_Node) => ''\r\nconst _dataString = async (sy: S_Node) => sy.Data ?? ''\r\n\r\n/** 对一些数据常量进行处理 */\r\nexport const getRender = () => {\r\n return {\r\n ...render,\r\n nodeStack: [],\r\n refs: new Set(),\r\n } as Render\r\n}\r\nconst render: {\r\n [key in keyof typeof NodeType]?: (sy: S_Node) => Promise<string>\r\n} & {\r\n /**\r\n * 用于保存调用栈,即从根节点到当前节点。\r\n * 例如在渲染 文档A中引用了文档B中的节点 时调用栈如下\r\n * ```\r\n * nodeStack ~= [A_NodeDocument,A_NodeList,...,A_block-ref,B_Node]\r\n * ```\r\n * 对render中的函数意味着 `this.nodeStack[0]===需要生成的文档`\r\n * 这样就方便解决 block-ref 等链接问题\r\n * */\r\n nodeStack: S_Node[]\r\n /** 当前实例所引用的其他文档id,在渲染中计算 */\r\n refs: Set<string>\r\n /** 返回当前文档到顶层文档的路径前缀,例如: ./../.. */\r\n getTopPathPrefix: (sy_doc?: S_Node) => Promise<string>\r\n} = {\r\n nodeStack: [] as S_Node[],\r\n refs: new Set(),\r\n async getTopPathPrefix() {\r\n const sy = this.nodeStack[0]\r\n let prefix = '.'\r\n if (sy.Type === 'NodeDocument' && sy.ID) {\r\n /** 基于当前文档路径将 href ../ 到顶层 */\r\n const path = await storeDep.getDocPathBySY(sy)\r\n if (path) {\r\n /** path data/box_id/doc_id/doc_id/doc_id.sy `data/box_id/` 这一节是多出来的,所以要减3 */\r\n const level = path.split('/').length - 3\r\n for (let i = 0; i < level; i++) {\r\n prefix += '/..'\r\n }\r\n }\r\n return prefix\r\n } else {\r\n console.log('未定义顶层元素非 NodeDocument 时的处理方式', sy)\r\n return ''\r\n }\r\n },\r\n async NodeDocument(sy) {\r\n let html = ''\r\n if (/** 只有顶层的文档块才渲染题图 */ this.nodeStack.length === 1) {\r\n html += `<div style=\"min-height: 150px;\" ${strAttr(sy)}>`\r\n if (sy.Properties?.['title-img']) {\r\n html += `<div class=\"protyle-background__img\" style=\"margin-bottom: 30px;position: relative;height: 16vh;${sy.Properties?.[\r\n 'title-img'\r\n ].replace(\r\n /assets/,\r\n // 修改为相对路径\r\n (await this.getTopPathPrefix()) + '/assets',\r\n )}\"/>${\r\n sy.Properties?.['icon']\r\n ? `<div style=\"position: absolute;bottom:-10px;left:15px;height: 80px;width: 80px;transition: var(--b3-transition);cursor: pointer;font-size: 68px;line-height: 80px;text-align: center;font-family: var(--b3-font-family-emoji);margin-right: 16px;\"> &#x${sy.Properties?.['icon']} </div>`\r\n : ''\r\n }</div>`\r\n }\r\n html += '</div>'\r\n /** h1 文档标题 */\r\n html += `<h1 ${strAttr(sy)} data-type=\"NodeHeading\" class=\"h1\">${\r\n sy.Properties?.title\r\n }</h1>`\r\n }\r\n html += await childRender(sy, this)\r\n return html\r\n },\r\n async NodeHeading(sy) {\r\n const tagName = `h${sy.HeadingLevel}`\r\n let html = `<${tagName} ${strAttr(sy)}>${await childRender(\r\n sy,\r\n this,\r\n )}</${tagName}>`\r\n\r\n // 在被嵌入查询块的情况下需要查询渲染其后面的非标题块\r\n const parentNode =\r\n this.nodeStack[\r\n this.nodeStack.length -\r\n 2 /** 最后一个元素是 sy本身(NodeHeading)还得要往前一个,所以是2 */\r\n ]\r\n\r\n if (parentNode?.Type === 'NodeBlockQueryEmbedScript') {\r\n let afterFlag = false\r\n for (const node of sy.Parent.Children ?? []) {\r\n if (node === sy) {\r\n afterFlag = true\r\n } else if (node !== sy && node.Type === 'NodeHeading') {\r\n afterFlag = false\r\n } else if (afterFlag) {\r\n html += '\\n' + (await renderHTML(node, this))\r\n }\r\n }\r\n }\r\n return html\r\n },\r\n NodeText: _dataString,\r\n async NodeList(sy) {\r\n return html`<div ${strAttr(sy)}>${await childRender(sy, this)}</div>`\r\n },\r\n async NodeListItem(sy) {\r\n return html`<div ${await strAttr(sy)}>\r\n <div class=\"protyle-action\">\r\n ${\r\n sy.ListData?.Typ === 1\r\n ? /** 有序列表 */ atob(sy.ListData?.Marker ?? '')\r\n : sy.ListData?.Typ === 3\r\n ? /** 任务列表 */ `<svg><use xlink:href=\"#${\r\n sy.Children?.find((el) => el.Type === 'NodeTaskListItemMarker')\r\n ?.TaskListItemChecked\r\n ? 'iconCheck'\r\n : 'iconUncheck'\r\n }\"></use></svg>`\r\n : /** 无序列表 */ `<svg><use xlink:href=\"#iconDot\"></use></svg>`\r\n }\r\n </div>\r\n ${await childRender(sy, this)}\r\n </div>`\r\n },\r\n NodeTaskListItemMarker: _emptyString,\r\n\r\n async NodeParagraph(sy) {\r\n /** .protyle-wysiwyg [data-node-id] [spellcheck] 定义了换行样式 */\r\n return `<div ${strAttr(sy)}><div spellcheck=\"false\">${await childRender(\r\n sy,\r\n this,\r\n )}</div></div>`\r\n },\r\n async NodeTextMark(sy) {\r\n const that = this\r\n let r: string = ''\r\n /** 从后向前渲染每一层mark ,TextMarkType有可能是 `a sub` |`sub a` | `a` |`code`等 */\r\n for (const type of (\r\n sy.TextMarkType?.split(' ') ?? []\r\n ).reverse() as S_Node['TextMarkType'][]) {\r\n if (r === '') {\r\n r = await TextMarkRender(sy, type, sy.TextMarkTextContent ?? '')\r\n } else {\r\n r = await TextMarkRender(sy, type, r)\r\n }\r\n }\r\n return r\r\n async function TextMarkRender(\r\n sy: S_Node,\r\n type: S_Node['TextMarkType'],\r\n content: string,\r\n ): Promise<string> {\r\n if (type === 'inline-math') {\r\n return `<span data-type=\"inline-math\" data-subtype=\"math\" data-content=\"${sy.TextMarkInlineMathContent}\" class=\"render-node\"></span>`\r\n } else if (type === 'inline-memo' /** 备注 */) {\r\n return `${content}<sup>(${sy.TextMarkInlineMemoContent})</sup>`\r\n } else if (type === 'block-ref' /** 引用块 */) {\r\n let href = ''\r\n if (sy.TextMarkBlockRefID) {\r\n const doc = await storeDep.getDocByChildID(sy.TextMarkBlockRefID)\r\n if (doc?.ID) {\r\n href = `${await that.getTopPathPrefix()}${await storeDep.getHPathByID_Node(\r\n doc /** 要先定位到文档,再通过下面的hash(#)定位到具体元素 */,\r\n )}.html#${sy.TextMarkBlockRefID}`\r\n that.refs.add(doc.ID)\r\n } else {\r\n warn(`未查找到${sy.ID}所指向的文档节点 ${sy.TextMarkBlockRefID}`)\r\n }\r\n } else {\r\n warn(`${sy.ID} 块引用没有设定 ref id`)\r\n }\r\n\r\n return `<span data-type=\"${sy.TextMarkType}\" \\\r\ndata-subtype=\"${/** \"s\" */ sy.TextMarkBlockRefSubtype}\" \\\r\ndata-id=\"${\r\n /** 被引用块的id */ sy.TextMarkBlockRefID\r\n }\"><a href=\"${href}\">${content}</a></span>`\r\n } else if (type === 'a') {\r\n let href = sy.TextMarkAHref\r\n if (href?.startsWith('assets/')) {\r\n /** TODO 应该有一个统一处理资源的方案 */\r\n href = `${await that.getTopPathPrefix()}/${href}`\r\n }\r\n return `<a href=\"${href}\">${content}</a>`\r\n } else if (\r\n `strong em u s mark sup sub kbd tag code strong code text`.includes(\r\n type ?? '',\r\n )\r\n ) {\r\n return `<span ${strAttr(sy, { data_type: type })}>${content}</span>`\r\n } else {\r\n return warnDiv(\r\n `没有找到对应的渲染器 ${sy.TextMarkType} ${that.nodeStack[0].Properties?.title}`,\r\n )\r\n }\r\n }\r\n },\r\n async NodeImage(sy) {\r\n let link = ''\r\n const LinkDest = sy.Children?.filter((c) => c.Type === 'NodeLinkDest')\r\n if (LinkDest?.length === 1) {\r\n link = await renderHTML(LinkDest[0], this)\r\n } else if (LinkDest?.length && LinkDest.length > 1) {\r\n warn('NodeImage 存在多个 LinkDest', sy)\r\n }\r\n\r\n let title = ''\r\n const LinkTitle = sy.Children?.filter((c) => c.Type === 'NodeLinkTitle')\r\n if (LinkTitle?.length === 1) {\r\n title = await renderHTML(LinkTitle[0], this)\r\n } else if (LinkTitle?.length && LinkTitle.length > 1) {\r\n warn('NodeImage 存在多个 LinkTitle', sy)\r\n }\r\n return `<span ${await strAttr(sy)} style=\"${\r\n sy.Properties?.['parent-style'] ?? ''\r\n }\">\r\n<img\r\n src=\"${link}\"\r\n data-src=\"${link}\"\r\n title=\"${title}\"\r\n style=\"${sy.Properties?.style ?? ''}\"\r\n loading=\"lazy\"\r\n/>\r\n<span class=\"protyle-action__title\">${title}</span></span>`\r\n },\r\n async NodeLinkDest(sy) {\r\n /** 绝对路径 */\r\n if (/^(?:[a-z]+:)?\\/\\/|^(?:\\/)/.test(sy.Data ?? '')) {\r\n return sy.Data ?? ''\r\n }\r\n /** 为相对路径添加正确的前缀 */\r\n return `${await this.getTopPathPrefix()}/${sy.Data}`\r\n },\r\n NodeLinkTitle: _dataString,\r\n NodeKramdownSpanIAL: _emptyString,\r\n async NodeSuperBlock(sy) {\r\n return `<div ${strAttr(sy)} data-sb-layout=\"${childDateByType(\r\n sy,\r\n 'NodeSuperBlockLayoutMarker',\r\n )}\">${await childRender(sy, this)}</div>`\r\n },\r\n NodeSuperBlockOpenMarker: _emptyString,\r\n NodeSuperBlockCloseMarker: _emptyString,\r\n NodeSuperBlockLayoutMarker: _emptyString,\r\n async NodeBlockQueryEmbed(sy) {\r\n return `<div ${strAttr(sy)} data-type=\"NodeBlockquote\" class=\"bq\">\\\r\n${await childRender(sy, this)}\\\r\n</div>`\r\n },\r\n NodeOpenBrace: _emptyString,\r\n NodeCloseBrace: _emptyString,\r\n async NodeBlockQueryEmbedScript(sy) {\r\n const sql = sy.Data\r\n if (!sql) {\r\n console.log('no sql', sy)\r\n return html`<pre>${sql}</pre>`\r\n }\r\n let htmlStr = ''\r\n const blocks: DB_block[] = await API.query_sql({\r\n stmt: /** sql 被思源转义了,类似 :SELECT * FROM blocks WHERE id = '20201227174241-nxny1tq'\r\n 所以这里将它转义回来\r\n TODO 当用户确实使用了包含转义的字符串时,这个实现是错误的 */ unescaping(\r\n sql,\r\n ).replace(\r\n /** 我不理解lute为什么这样实现 https://github.com/88250/lute/blob/HEAD/editor/const.go#L38\r\n * https://ld246.com/article/1696750832289\r\n */\r\n /_esc_newline_/g,\r\n '\\n',\r\n ),\r\n }).catch((err) => {\r\n throw new Error(\r\n `sql error: ${err.message}\\nrawSql:${sql}\\nunescapingSql:${unescaping(\r\n sql,\r\n )}`,\r\n )\r\n })\r\n for (const block of blocks) {\r\n const node = await storeDep.getNodeByID(block.id)\r\n if (node === undefined) {\r\n return warnDiv('未找到此块,可能为跨笔记引用', block.id, sql)\r\n }\r\n htmlStr += await renderHTML(node, this)\r\n }\r\n\r\n return htmlStr\r\n },\r\n async NodeBlockquote(sy) {\r\n return html`<div ${strAttr(sy)}>${await childRender(sy, this)}</div>`\r\n },\r\n NodeBlockquoteMarker: _emptyString,\r\n NodeCodeBlock: async (sy) => {\r\n const [yes, _] = isRenderCode(sy)\r\n if (yes) {\r\n return `<div ${strAttr(sy)} data-content=\"${escaping(\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockCode')?.Data ?? '',\r\n )}\">\r\n <div spin=\"1\"></div>\r\n <div class=\"protyle-attr\" contenteditable=\"false\"></div>\r\n </div>`\r\n }\r\n return `<div ${strAttr(sy)}>\r\n <div class=\"protyle-action\">\r\n <span class=\"protyle-action--first protyle-action__language\">${await renderHTML(\r\n sy.Children?.find(\r\n (el) => el.Type === 'NodeCodeBlockFenceInfoMarker',\r\n ),\r\n this,\r\n )}</span>\r\n <span class=\"fn__flex-1\"></span><span class=\"protyle-icon protyle-icon--only protyle-action__copy\"><svg><use xlink:href=\"#iconCopy\"></use></svg></span>\r\n </div>\r\n ${await renderHTML(\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockCode'),\r\n this,\r\n )}\r\n </div>`\r\n },\r\n NodeCodeBlockFenceInfoMarker: async (sy) => atob(sy.CodeBlockInfo ?? ''),\r\n NodeCodeBlockCode: async (sy) =>\r\n `<div class=\"hljs\" spellcheck=\"false\">${sy.Data}</div>`,\r\n NodeCodeBlockFenceOpenMarker: _emptyString,\r\n NodeCodeBlockFenceCloseMarker: _emptyString,\r\n async NodeTable(sy) {\r\n return `<div ${strAttr(sy)}>\r\n <div>\r\n <table spellcheck=\"false\">\r\n <colgroup>\r\n ${sy.TableAligns?.map(() => '<col />').join('')}\r\n </colgroup>\r\n ${await renderHTML(\r\n sy.Children?.find((el) => el.Type === 'NodeTableHead'),\r\n this,\r\n )}\r\n <tbody>\r\n ${(\r\n await Promise.all(\r\n sy.Children?.filter((el) => el.Type === 'NodeTableRow').map((el) =>\r\n renderHTML(el, this),\r\n ) ?? [],\r\n )\r\n ).join('\\n')}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>`\r\n },\r\n async NodeTableHead(sy) {\r\n return `<${sy.Data}>${await childRender(sy, this)}</${sy.Data}>`\r\n },\r\n async NodeTableRow(sy) {\r\n return `<tr>${await childRender(sy, this)}</tr>`\r\n },\r\n async NodeTableCell(sy) {\r\n return `<td>${await childRender(sy, this)}</td>`\r\n },\r\n NodeHTMLBlock: async (sy) => `<div ${strAttr(sy)}>${sy.Data}</div>`,\r\n NodeThematicBreak: async (sy) => `<div ${strAttr(sy)}><div></div></div>`,\r\n NodeMathBlock: async (sy) => `<div ${strAttr(\r\n sy,\r\n )} data-content=\"${childDateByType(sy, 'NodeMathBlockContent')}\">\r\n <div spin=\"1\"></div>\r\n </div>`,\r\n NodeMathBlockOpenMarker: _emptyString,\r\n NodeMathBlockCloseMarker: _emptyString,\r\n async NodeIFrame(sy) {\r\n return ` <div ${strAttr(sy)}>\r\n <div class=\"iframe-content\">\r\n ${\r\n /** 资源总是被复制到顶层目录,所以直接跳到顶层即可 */\r\n /** TODO 应该有一个统一处理资源的方案 */\r\n sy.Data?.replace(\r\n /src=\"assets\\//,\r\n `src=\"${await this.getTopPathPrefix()}/assets\\/`,\r\n )\r\n }\r\n </div>\r\n </div>`\r\n },\r\n async NodeVideo(sy) {\r\n return await this.NodeIFrame!(sy)\r\n },\r\n async NodeAudio(sy) {\r\n return await this.NodeIFrame!(sy)\r\n },\r\n /** 虚拟链接 */\r\n NodeHeadingC8hMarker: _emptyString,\r\n async NodeSoftBreak(_sy) {\r\n //TODO 此处实现应该有问题\r\n /** https://zh.wikipedia.org/wiki/零宽空格 */\r\n return '\\u200B'\r\n },\r\n async NodeBr(sy) {\r\n return `<${sy.Data}>`\r\n },\r\n async NodeWidget(sy) {\r\n return `<div ${strAttr(\r\n sy,\r\n )}><img src=\"${await this.getTopPathPrefix()}/assets/widget/${\r\n sy.ID\r\n }.jpg\"/></div>`\r\n },\r\n async NodeBackslash(sy) {\r\n if (sy.Data === undefined || sy.Data === 'span') {\r\n return `${await childRender(sy, this)}`\r\n } else {\r\n return warnDiv(\r\n `未定义的 NodeBackslash 处理 ${sy.Data}`,\r\n this.nodeStack[0].Properties?.title,\r\n )\r\n }\r\n },\r\n NodeBackslashContent: _dataString,\r\n}\r\n\r\n/** 获取sy节点的child中第一个type类型节点的data */\r\nfunction childDateByType(sy: S_Node, type: S_Node['Type']) {\r\n return sy.Children?.find((el) => el.Type === type)?.Data\r\n}\r\n\r\nfunction warn(...arg: any[]) {\r\n console.warn('\\n', ...arg)\r\n}\r\n","export interface notebook {\r\n id: \"20210808180117-czj9bvb\";\r\n name: \"思源笔记用户指南\";\r\n icon: \"1f4d4\";\r\n sort: 1;\r\n closed: false;\r\n}\r\nexport interface file {\r\n /** \"/20210816161946-cktc4gf.sy\" */\r\n path: string;\r\n name: \"关于.sy\";\r\n icon: \"\";\r\n name1: \"\";\r\n alias: \"\";\r\n memo: \"\";\r\n bookmark: \"\";\r\n /** \"20210816161946-cktc4gf\" */\r\n id: string;\r\n count: 0;\r\n size: 362;\r\n hSize: \"362 B\";\r\n mtime: 1629101986;\r\n ctime: 1629101986;\r\n hMtime: \"2 年以前\";\r\n hCtime: \"2021-08-16 16:19:46\";\r\n sort: 0;\r\n subFileCount: 9;\r\n newFlashcardCount: 0;\r\n dueFlashcardCount: 0;\r\n flashcardCount: 0;\r\n}\r\nexport interface NodeDocument {\r\n blockCount: 2;\r\n box: \"20210808180117-czj9bvb\";\r\n content: \"<html>\";\r\n eof: false;\r\n id: \"20230519105228-hm0y74i\";\r\n isBacklinkExpand: false;\r\n isSyncing: false;\r\n mode: 0;\r\n parent2ID: \"20230519105228-hm0y74i\";\r\n parentID: \"20230519105228-hm0y74i\";\r\n path: \"/20230519105228-hm0y74i.sy\";\r\n rootID: \"20230519105228-hm0y74i\";\r\n scroll: false;\r\n type: \"NodeDocument\";\r\n}\r\n\r\nexport function DB_block_path(p: DB_block) {\r\n return `data/${p.box}${p.path}`;\r\n}\r\nexport interface DB_block {\r\n alias: \"\";\r\n box: \"20210816161940-3mfvumm\";\r\n content: \"自述\";\r\n created: \"20201125202944\";\r\n fcontent: \"自述\";\r\n hash: \"922ee83\";\r\n hpath: \"/计算机基础课/自述\";\r\n ial: '{: id=\"20201125202944-01mdxqn\" title=\"自述\" type=\"doc\" updated=\"20201125202944\"}';\r\n id: \"20201125202944-01mdxqn\";\r\n length: 2;\r\n markdown: \"\";\r\n memo: \"\";\r\n name: \"\";\r\n parent_id: \"\";\r\n path: \"/20210816161944-io0cgn6/20201125202944-01mdxqn.sy\";\r\n root_id: \"20201125202944-01mdxqn\";\r\n sort: 0;\r\n subtype: \"\";\r\n tag: \"\";\r\n type: \"d\";\r\n updated: \"20201125202944\";\r\n}\r\nexport interface S_Node {\r\n ID?: string; // 节点的唯一标识\r\n Box?: string; // 容器\r\n Path?: string; // 路径\r\n Spec?: string; // 规范版本号\r\n Type: NodeType; // 节点类型\r\n Parent: S_Node; // 父节点 在 node.ts 中被重建了,所以这个引用关系是可用的\r\n Previous?: S_Node; // 前一个兄弟节点\r\n Next?: S_Node; // 后一个兄弟节点\r\n FirstChild?: S_Node; // 第一个子节点\r\n LastChild?: S_Node; // 最后一个子节点\r\n Children?: S_Node[]; // 所有子节点\r\n Tokens?: number[]; // 词法分析结果 Tokens,语法分析阶段会继续操作这些 Tokens\r\n TypeStr: string; // 类型字符串\r\n Data?: string; // Tokens 字符串\r\n Close?: boolean; // 标识是否关闭\r\n LastLineBlank?: boolean; // 标识最后一行是否是空行\r\n LastLineChecked?: boolean; // 标识最后一行是否检查过\r\n CodeMarkerLen?: number; // ` 个数,1 或 2\r\n IsFencedCodeBlock?: boolean;\r\n CodeBlockFenceChar?: number;\r\n CodeBlockFenceLen?: number;\r\n CodeBlockFenceOffset?: number;\r\n CodeBlockOpenFence?: number[];\r\n CodeBlockInfo?: string; // Z28= | atob = 'go'\r\n CodeBlockCloseFence?: number[];\r\n HtmlBlockType?: number;\r\n ListData?: ListData;\r\n TaskListItemChecked?: boolean;\r\n TableAligns?: number[];\r\n TableCellAlign?: number;\r\n TableCellContentWidth?: number;\r\n TableCellContentMaxWidth?: number;\r\n LinkType?: number;\r\n LinkRefLabel?: number[];\r\n HeadingLevel?: number;\r\n HeadingSetext?: boolean;\r\n HeadingNormalizedID?: string;\r\n MathBlockDollarOffset?: number;\r\n FootnotesRefLabel?: number[];\r\n FootnotesRefId?: string;\r\n FootnotesRefs?: Node[];\r\n HtmlEntityTokens?: number[];\r\n KramdownIAL?: string[][];\r\n Properties?: {\r\n icon: \"1f4f0\";\r\n id: \"20200825162036-4dx365o\";\r\n title: \"排版元素\";\r\n \"title-img\": \"background-color: hsl(2, 57%, 40%);background-image: repeating-linear-gradient(transparent, transparent 50px, rgba(0,0,0,.4) 50px, rgba(0,0,0,.4) 53px, transparent 53px, transparent 63px, rgba(0,0,0,.4) 63px, rgba(0,0,0,.4) 66px, transparent 66px, transparent 116px, rgba(0,0,0,.5) 116px, rgba(0,0,0,.5) 166px, rgba(255,255,255,.2) 166px, rgba(255,255,255,.2) 169px, rgba(0,0,0,.5) 169px, rgba(0,0,0,.5) 179px, rgba(255,255,255,.2) 179px, rgba(255,255,255,.2) 182px, rgba(0,0,0,.5) 182px, rgba(0,0,0,.5) 232px, transparent 232px),repeating-linear-gradient(270deg, transparent, transparent 50px, rgba(0,0,0,.4) 50px, rgba(0,0,0,.4) 53px, transparent 53px, transparent 63px, rgba(0,0,0,.4) 63px, rgba(0,0,0,.4) 66px, transparent 66px, transparent 116px, rgba(0,0,0,.5) 116px, rgba(0,0,0,.5) 166px, rgba(255,255,255,.2) 166px, rgba(255,255,255,.2) 169px, rgba(0,0,0,.5) 169px, rgba(0,0,0,.5) 179px, rgba(255,255,255,.2) 179px, rgba(255,255,255,.2) 182px, rgba(0,0,0,.5) 182px, rgba(0,0,0,.5) 232px, transparent 232px),repeating-linear-gradient(125deg, transparent, transparent 2px, rgba(0,0,0,.2) 2px, rgba(0,0,0,.2) 3px, transparent 3px, transparent 5px, rgba(0,0,0,.2) 5px);\";\r\n type: \"doc\";\r\n updated: \"20230820185054\";\r\n \"parent-style\"?: \"max-width: 137px;\";\r\n style?: \"display: block;\";\r\n };\r\n TextMarkType?: \"block-ref\" | \"a\" | \"tag\" | \"inline-math\" | \"inline-memo\";\r\n TextMarkAHref?: string;\r\n TextMarkATitle?: string;\r\n TextMarkInlineMathContent?: string;\r\n TextMarkInlineMemoContent?: string;\r\n TextMarkBlockRefID?: string;\r\n TextMarkBlockRefSubtype?: string;\r\n TextMarkFileAnnotationRefID?: string;\r\n TextMarkTextContent?: string;\r\n AttributeViewID?: string;\r\n AttributeViewType?: string;\r\n CustomBlockFenceOffset?: number;\r\n CustomBlockInfo?: string;\r\n}\r\ntype NodeType = ValueKeys<typeof NodeType>;\r\ntype ValueKeys<T> = keyof { [K in keyof T]: T[K] extends string ? K : never };\r\ninterface ListData {\r\n Typ?: number; // 0:无序列表,1:有序列表,3:任务列表\r\n Tight?: boolean; // 是否是紧凑模式\r\n BulletChar?: number; // 无序列表标识,* - 或者 +\r\n Start?: number; // 有序列表起始序号\r\n Delimiter?: number; // 有序列表分隔符,. 或者 )\r\n Padding?: number; // 列表内部缩进空格数(包含标识符长度,即规范中的 W+N)\r\n MarkerOffset?: number; // 标识符(* - + 或者 1 2 3)相对缩进空格数\r\n Checked?: boolean; // 任务列表项是否勾选\r\n Marker?: string; // 列表标识符\r\n Num?: number; // 有序列表项修正过的序号\r\n}\r\n\r\nexport const NodeType = {\r\n NodeDocument: 0, // 根\r\n NodeParagraph: 1, // 段落\r\n NodeHeading: 2, // 标题\r\n NodeHeadingC8hMarker: 3, // ATX 标题标记符 #\r\n NodeThematicBreak: 4, // 分隔线\r\n NodeBlockquote: 5, // 块引用\r\n NodeBlockquoteMarker: 6, // 块引用标记符 >\r\n NodeList: 7, // 列表\r\n NodeListItem: 8, // 列表项\r\n NodeHTMLBlock: 9, // HTML 块\r\n NodeInlineHTML: 10, // 内联 HTML\r\n NodeCodeBlock: 11, // 代码块\r\n NodeCodeBlockFenceOpenMarker: 12, // 开始围栏代码块标记符 ```\r\n NodeCodeBlockFenceCloseMarker: 13, // 结束围栏代码块标记符 ```\r\n NodeCodeBlockFenceInfoMarker: 14, // 围栏代码块信息标记符 info string\r\n NodeCodeBlockCode: 15, // 围栏代码块代码\r\n NodeText: 16, // 文本\r\n NodeEmphasis: 17, // 强调\r\n NodeEmA6kOpenMarker: 18, // 开始强调标记符 *\r\n NodeEmA6kCloseMarker: 19, // 结束强调标记符 *\r\n NodeEmU8eOpenMarker: 20, // 开始强调标记符 _\r\n NodeEmU8eCloseMarker: 21, // 结束强调标记符 _\r\n NodeStrong: 22, // 加粗\r\n NodeStrongA6kOpenMarker: 23, // 开始加粗标记符 **\r\n NodeStrongA6kCloseMarker: 24, // 结束加粗标记符 **\r\n NodeStrongU8eOpenMarker: 25, // 开始加粗标记符 __\r\n NodeStrongU8eCloseMarker: 26, // 结束加粗标记符 __\r\n NodeCodeSpan: 27, // 代码\r\n NodeCodeSpanOpenMarker: 28, // 开始代码标记符 `\r\n NodeCodeSpanContent: 29, // 代码内容\r\n NodeCodeSpanCloseMarker: 30, // 结束代码标记符 `\r\n NodeHardBreak: 31, // 硬换行\r\n NodeSoftBreak: 32, // 软换行\r\n NodeLink: 33, // 链接\r\n NodeImage: 34, // 图片\r\n NodeBang: 35, // !\r\n NodeOpenBracket: 36, // [\r\n NodeCloseBracket: 37, // ]\r\n NodeOpenParen: 38, // (\r\n NodeCloseParen: 39, // )\r\n NodeLinkText: 40, // 链接文本\r\n NodeLinkDest: 41, // 链接地址\r\n NodeLinkTitle: 42, // 链接标题\r\n NodeLinkSpace: 43, // 链接地址和链接标题之间的空格\r\n NodeHTMLEntity: 44, // HTML 实体\r\n NodeLinkRefDefBlock: 45, // 链接引用定义块\r\n NodeLinkRefDef: 46, // 链接引用定义 [label]:\r\n NodeLess: 47, // <\r\n NodeGreater: 48, // >\r\n\r\n // GFM\r\n\r\n NodeTaskListItemMarker: 100, // 任务列表项标记符\r\n NodeStrikethrough: 101, // 删除线\r\n NodeStrikethrough1OpenMarker: 102, // 开始删除线标记符 ~\r\n NodeStrikethrough1CloseMarker: 103, // 结束删除线标记符 ~\r\n NodeStrikethrough2OpenMarker: 104, // 开始删除线标记符 ~~\r\n NodeStrikethrough2CloseMarker: 105, // 结束删除线标记符 ~~\r\n NodeTable: 106, // 表\r\n NodeTableHead: 107, // 表头\r\n NodeTableRow: 108, // 表行\r\n NodeTableCell: 109, // 表格\r\n\r\n // Emoji\r\n\r\n NodeEmoji: 200, // Emoji\r\n NodeEmojiUnicode: 201, // Emoji Unicode\r\n NodeEmojiImg: 202, // Emoji 图片\r\n NodeEmojiAlias: 203, // Emoji ASCII\r\n\r\n // 数学公式\r\n\r\n NodeMathBlock: 300, // 数学公式块\r\n NodeMathBlockOpenMarker: 301, // 开始数学公式块标记符 $$\r\n NodeMathBlockContent: 302, // 数学公式块内容\r\n NodeMathBlockCloseMarker: 303, // 结束数学公式块标记符 $$\r\n NodeInlineMath: 304, // 内联数学公式\r\n NodeInlineMathOpenMarker: 305, // 开始内联数学公式标记符 $\r\n NodeInlineMathContent: 306, // 内联数学公式内容\r\n NodeInlineMathCloseMarker: 307, // 结束内联数学公式标记符 $\r\n\r\n // 转义\r\n\r\n NodeBackslash: 400, // 转义反斜杠标记符 \\\r\n NodeBackslashContent: 401, // 转义反斜杠后的内容\r\n\r\n // Vditor 支持\r\n\r\n NodeVditorCaret: 405, // 插入符,某些情况下需要使用该节点进行插入符位置调整\r\n\r\n // 脚注\r\n\r\n NodeFootnotesDefBlock: 410, // 脚注定义块\r\n NodeFootnotesDef: 411, // 脚注定义 [^label]:\r\n NodeFootnotesRef: 412, // 脚注引用 [^label]\r\n\r\n // 目录\r\n\r\n NodeToC: 415, // 目录 [toc]\r\n\r\n // 标题\r\n\r\n NodeHeadingID: 420, // 标题 ID # foo {id}\r\n\r\n // YAML Front Matter\r\n\r\n NodeYamlFrontMatter: 425, // https://,jekyllrb.com/docs/front-matter/\r\n NodeYamlFrontMatterOpenMarker: 426, // 开始 YAML Front Matter 标记符 ---\r\n NodeYamlFrontMatterContent: 427, // YAML Front Matter 内容\r\n NodeYamlFrontMatterCloseMarker: 428, // 结束 YAML Front Matter 标记符 ---\r\n\r\n // 内容块引用(Block Reference) https://,github.com/88250/lute/issues/82\r\n\r\n NodeBlockRef: 430, // 内容块引用节点\r\n NodeBlockRefID: 431, // 被引用的内容块(定义块)ID\r\n NodeBlockRefSpace: 432, // 被引用的内容块 ID 和内容块引用锚文本之间的空格\r\n NodeBlockRefText: 433, // 内容块引用锚文本\r\n NodeBlockRefDynamicText: 434, // 内容块引用动态锚文本\r\n\r\n // ==Mark== 标记语法 https://,github.com/88250/lute/issues/84\r\n\r\n NodeMark: 450, // 标记\r\n NodeMark1OpenMarker: 451, // 开始标记标记符 =\r\n NodeMark1CloseMarker: 452, // 结束标记标记符 =\r\n NodeMark2OpenMarker: 453, // 开始标记标记符 ==\r\n NodeMark2CloseMarker: 454, // 结束标记标记符 ==\r\n\r\n // kramdown 内联属性列表 https://,github.com/88250/lute/issues/89 and https://,github.com/88250/lute/issues/118\r\n\r\n NodeKramdownBlockIAL: 455, // 块级内联属性列表 {: name,=\"value\"}\r\n NodeKramdownSpanIAL: 456, // 行级内联属性列表 *foo*{: name,=\"value\"}bar\r\n\r\n // #Tag# 标签语法 https://,github.com/88250/lute/issues/92\r\n\r\n NodeTag: 460, // 标签\r\n NodeTagOpenMarker: 461, // 开始标签标记符 #\r\n NodeTagCloseMarker: 462, // 结束标签标记符 #\r\n\r\n // 内容块查询嵌入(Block Query Embed)语法 https://,github.com/88250/lute/issues/96\r\n\r\n NodeBlockQueryEmbed: 465, // 内容块查询嵌入\r\n NodeOpenBrace: 466, // {\r\n NodeCloseBrace: 467, // }\r\n NodeBlockQueryEmbedScript: 468, // 内容块查询嵌入脚本\r\n\r\n // 超级块语法 https://,github.com/88250/lute/issues/111\r\n\r\n NodeSuperBlock: 475, // 超级块节点\r\n NodeSuperBlockOpenMarker: 476, // 开始超级块标记符 {{{\r\n NodeSuperBlockLayoutMarker: 477, // 超级块布局 row/col\r\n NodeSuperBlockCloseMarker: 478, // 结束超级块标记符 }}}\r\n\r\n // 上标下标语法 https://,github.com/88250/lute/issues/113\r\n\r\n NodeSup: 485, // 上标\r\n NodeSupOpenMarker: 486, // 开始上标标记符 ^\r\n NodeSupCloseMarker: 487, // 结束上标标记符 ^\r\n NodeSub: 490, // 下标\r\n NodeSubOpenMarker: 491, // 开始下标标记符 ~\r\n NodeSubCloseMarker: 492, // 结束下标标记符 ~\r\n\r\n // Git 冲突标记 https://,github.com/88250/lute/issues/131\r\n\r\n NodeGitConflict: 495, // Git 冲突标记\r\n NodeGitConflictOpenMarker: 496, // 开始 Git 冲突标记标记符 <<<<<<<\r\n NodeGitConflictContent: 497, // Git 冲突标记内容\r\n NodeGitConflictCloseMarker: 498, // 结束 Git 冲突标记标记符 >>>>>>>\r\n\r\n // <iframe> 标签\r\n\r\n NodeIFrame: 500, // <iframe> 标签\r\n\r\n // <audio> 标签\r\n\r\n NodeAudio: 505, // <audio> 标签\r\n\r\n // <video> 标签\r\n\r\n NodeVideo: 510, // <video> 标签\r\n\r\n // <kbd> 标签\r\n\r\n NodeKbd: 515, // 键盘\r\n NodeKbdOpenMarker: 516, // 开始 kbd 标记符 <kbd>\r\n NodeKbdCloseMarker: 517, // 结束 kbd 标记符 </kbd>\r\n\r\n // <u> 标签\r\n\r\n NodeUnderline: 520, // 下划线\r\n NodeUnderlineOpenMarker: 521, // 开始下划线标记符 <u>\r\n NodeUnderlineCloseMarker: 522, // 结束下划线标记符 </u>\r\n\r\n // <br> 标签\r\n\r\n NodeBr: 525, // <br> 换行\r\n\r\n // <span data-type=\"mark\">foo</span> 通用的行级文本标记,不能嵌套\r\n\r\n NodeTextMark: 530, // 文本标记,该节点因为不存在嵌套,所以不使用 Open/Close 标记符\r\n\r\n // Protyle 挂件,<iframe data-type=\"NodeWidget\">\r\n\r\n NodeWidget: 535, // <iframe data-type=\"NodeWidget\" data-subtype=\"widget\"></iframe>\r\n\r\n // 文件注解引用 https://,github.com/88250/lute/issues/155\r\n\r\n NodeFileAnnotationRef: 540, // 文件注解引用节点\r\n NodeFileAnnotationRefID: 541, // 被引用的文件注解 ID(file/annotation)\r\n NodeFileAnnotationRefSpace: 542, // 被引用的文件注解 ID 和文件注解引用锚文本之间的空格\r\n NodeFileAnnotationRefText: 543, // 文件注解引用锚文本(不能为空,如果为空的话会自动使用 ID 渲染)\r\n\r\n // 属性视图 https://,github.com/siyuan-note/siyuan/issues/7535 <div data-type=\"NodeAttributeView\" data-av-type=\"table\" data-av-id=\"xxx\"></div>\r\n\r\n NodeAttributeView: 550, // 属性视图\r\n\r\n // 自定义块 https://,github.com/siyuan-note/siyuan/issues/8418 ;;;info\r\n\r\n NodeCustomBlock: 560, // 自定义块\r\n\r\n NodeTypeMaxVal: 1024, // 节点类型最大值\r\n};\r\n","/** ════════════════════════🏳🌈 cache 🏳🌈════════════════════════\r\n * 对于思源内核 api 的调用存到内存,通过快取技术避免重复请求和没有必要的请求,加速程序运行速度,但这可能会导致数据不是最新的\r\n ** ════════════════════════🚧 cache 🚧════════════════════════ */\r\n\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, DB_block_path, S_Node } from './siyuan_type.ts'\r\n\r\nlet cache = true\r\n/** 控制是否启用快取功能 */\r\nexport function setCache(b: boolean) {\r\n cache = b\r\n}\r\n\r\n/** sql->查询结果 */\r\nconst sqlCacheMap = new Map<string, any>()\r\n/** hpath->S_Node文档节点 */\r\nconst hpathCacheMap = new Map<string, S_Node>()\r\n/** id->S_Node */\r\nconst idCacheMap = new Map</** id */ string, S_Node>()\r\n/** id->DB_block */\r\nconst blockCacheMap = new Map</** id */ string, DB_block>()\r\n\r\nexport async function getIDsByHPath(p: {\r\n path: string\r\n notebook: string\r\n}): Promise<string[]> {\r\n if (cache && hpathCacheMap.has(p.path)) {\r\n const id = hpathCacheMap.get(p.path)?.ID\r\n // TODO 也许会有重复hpath这里暂不考虑\r\n return id ? [id] : []\r\n }\r\n const ids = await API.filetree_getIDsByHPath(p)\r\n return ids\r\n}\r\n\r\n/** 设置快取 sqlCacheMap */\r\nexport async function query_sql(stmt: string): Promise<any> {\r\n if (cache && sqlCacheMap.has(stmt)) {\r\n return sqlCacheMap.get(stmt)\r\n }\r\n const res = await API.query_sql({\r\n stmt,\r\n })\r\n if (cache) {\r\n sqlCacheMap.set(stmt, res)\r\n }\r\n return res\r\n}\r\n\r\n/** 设置快取 hpathCacheMap idCacheMap */\r\nexport async function get_doc_by_hpath(hpath: string): Promise<S_Node> {\r\n if (cache) {\r\n const c = hpathCacheMap.get(hpath)\r\n if (c) return c\r\n }\r\n const docBlock = (\r\n (await query_sql(\r\n `SELECT * FROM blocks WHERE hpath = '${hpath}'`,\r\n )) as DB_block[]\r\n )[0]\r\n if (docBlock === undefined) throw new Error(`not doc by:${hpath}`)\r\n const res = await get_doc_by_SyPath(DB_block_path(docBlock))\r\n if (cache) {\r\n hpathCacheMap.set(hpath, res)\r\n }\r\n return res\r\n}\r\n/** 设置快取 idCacheMap */\r\nexport async function get_doc_by_SyPath(path: string): Promise<S_Node> {\r\n const res = parentRef(\r\n (await API.file_getFile({\r\n path,\r\n })) as S_Node,\r\n )\r\n if (cache) {\r\n idCache(res)\r\n }\r\n return res\r\n}\r\n\r\nexport async function get_block_by_id(id: string) {\r\n if (cache) {\r\n const block = blockCacheMap.get(id)\r\n if (block) return block\r\n }\r\n const blocks = (await query_sql(`\r\n SELECT * from blocks\r\n WHERE id = '${id}'\r\n `)) as DB_block[]\r\n if (blocks.length === 0) {\r\n return\r\n }\r\n if (cache) blockCacheMap.set(id, blocks[0])\r\n return blocks[0]\r\n}\r\nexport async function get_node_by_id(id?: string) {\r\n if (id === undefined) return\r\n if (cache) {\r\n const node = idCacheMap.get(id)\r\n if (node) return node\r\n }\r\n const doc = await get_doc_by_child_id(id)\r\n if (doc === undefined) return\r\n return findNode(doc)\r\n\r\n function findNode(node: S_Node): S_Node | undefined {\r\n if (node.ID === id) return node\r\n if (node.Children) {\r\n return node.Children.find((child) => findNode(child))\r\n }\r\n }\r\n}\r\n/** set blockCacheMap*/\r\n// TODO 需要更换成能够完全遍历一个笔记本的写法\r\nexport async function allDocBlock_by_bookId(id: string) {\r\n const res = (await query_sql(`\r\n SELECT * from blocks\r\n WHERE box = '${id}'\r\n AND type = 'd'\r\n limit 150000 OFFSET 0\r\n `)) as DB_block[]\r\n if (cache) {\r\n res.forEach((block) => blockCacheMap.set(block.id, block))\r\n }\r\n return res\r\n}\r\n\r\nexport async function get_doc_by_child_id(\r\n id: string,\r\n): Promise<S_Node | undefined> {\r\n if (cache) {\r\n const child = idCacheMap.get(id)\r\n if (child) {\r\n let node = child\r\n while (true) {\r\n if (node.Type === 'NodeDocument') {\r\n return node\r\n } else if (node === undefined) {\r\n break\r\n }\r\n node = node.Parent\r\n }\r\n }\r\n }\r\n const block = await get_block_by_id(id)\r\n if (block === undefined) return\r\n return await get_doc_by_hpath(block.hpath)\r\n}\r\n\r\nfunction idCache(node: S_Node) {\r\n if (node.ID) {\r\n idCacheMap.set(node.ID, node)\r\n }\r\n if (node.Children) {\r\n node.Children.forEach(idCache)\r\n }\r\n}\r\n\r\n/** 为 children 节点附加 Parent 引用 */\r\nexport function parentRef(sy: S_Node) {\r\n for (const child of sy?.Children ?? []) {\r\n child.Parent = sy\r\n parentRef(child)\r\n }\r\n return sy\r\n}\r\n","import { get_node_by_id } from './cache.ts'\nimport type { Config } from './config.ts'\nimport { storeDep } from './dependency.ts'\nimport type { Render } from './render.ts'\nimport type { DB_block } from './siyuan_type.ts'\n\n/** 生成当前实例所有引用文档的RSS XML */\nexport async function generateRSSXML(\n path: string,\n renderInstance: Render,\n config: Config,\n): Promise<string> {\n const refNode = (\n await Promise.all([...renderInstance.refs.values()].map(get_node_by_id))\n ).filter((el) => el)\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n <channel>\n <title>${config.sitemap.title}</title>\n <link>${config.sitemap.siteLink}</link>\n <description>${config.sitemap.description}</description>\n <atom:link href=\"${\n config.sitemap.sitePrefix\n }${path}\" rel=\"self\" type=\"application/rss+xml\"/>\n <lastBuildDate>${new Date().toISOString()}</lastBuildDate>\n ${(\n await Promise.all(\n refNode.map(\n async (node) => `<item>\n <title>${node?.Properties?.title}</title>\n <link>${config.sitemap.sitePrefix}${\n node?.ID ? (await storeDep.getHPathByID_Node(node?.ID)) + '.html' : ''\n }</link>\n <description>${'' /** TODO 或许可以加入ai 进行摘要 */}</description>\n <pubDate>${\n node?.Properties?.updated\n ? new Date(\n node.Properties.updated.replace(\n /(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})/,\n '$1/$2/$3 $4:$5:$6',\n ),\n ).toISOString()\n : ''\n }</pubDate>\n </item>`,\n ),\n )\n ).join('\\n')}\n </channel>\n </rss>`\n}\n\n/** 生成 sitemap.xml 文件内容 */\nexport function sitemap_xml(\n docArr: DB_block[],\n config: {\n sitePrefix: string\n },\n) {\n const urlList: string = docArr\n .map((doc) => {\n let lastmod = ''\n const time = doc.ial.match(/updated=\\\"(\\d+)\\\"/)?.[1] ?? doc.created\n if (time) {\n lastmod = `\\n<lastmod>${time.slice(0, 4)}-${time.slice(\n 4,\n 6,\n )}-${time.slice(6, 8)}</lastmod>`\n }\n return `<url>\n <loc>${config.sitePrefix}${doc.hpath}.html</loc>${lastmod}\n </url>\\n`\n })\n .join('')\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n ${urlList}\n </urlset>`\n}\n","import { Config, currentConfig, tempConfig } from '~/core/config.ts'\r\nimport { htmlTemplate } from './htmlTemplate.ts'\r\nimport { getRender, renderHTML } from './render.ts'\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, DB_block_path, S_Node } from './siyuan_type.ts'\r\nimport { deepAssign } from '~/util/deep_assign.ts'\r\nimport {\r\n allDocBlock_by_bookId,\r\n get_doc_by_SyPath,\r\n get_node_by_id,\r\n} from './cache.ts'\r\nimport packageJson from '~/../package.json' with { type: 'json' };\r\nimport { generateRSSXML, sitemap_xml } from './genRssXml.ts'\r\nimport { downloadZIP } from './genZip.ts'\r\n\r\nexport interface DocTree {\r\n [/** \"/计算机基础课/自述\" */ docPath: string]: {\r\n sy: S_Node\r\n docBlock: DB_block\r\n }\r\n}\r\nexport interface FileTree {\r\n [path: string]: string | ArrayBuffer\r\n}\r\nexport type Build = typeof build\r\n/** 根据配置文件进行编译\r\n * TODO 将浏览器写文件的部分抽离出去,也改成使用 onFileTree\r\n */\r\nexport async function build(\r\n config: Config,\r\n effect:{\r\n log: (msg:string)=>void,\r\n percentage:(_n: number)=>void,\r\n },\r\n otherConfig?: {\r\n // 监听文件准备完毕 TODO:应该修改实现,而非目前直接全量加载到内存\r\n onFileTree?: (tree: FileTree) => void\r\n renderHtmlFn?: typeof renderHTML\r\n },\r\n) {\r\n const _renderHTML = otherConfig?.renderHtmlFn ?? renderHTML\r\n const book = config.notebook\r\n const docTree: DocTree = {}\r\n const skipBuilds = useSkipBuilds()\r\n\r\n let oldPercentage = 0\r\n let total = 0\r\n /** 较为精准的估计进度 */\r\n function processPercentage(\r\n /** 0~1 的小数 表示这个数占整体百分之多少 */ percentage: number,\r\n ) {\r\n total += oldPercentage\r\n return (/** 0~1 的小数 */ process: number) => {\r\n oldPercentage = process * percentage\r\n effect.percentage((total + oldPercentage) * 100)\r\n }\r\n }\r\n effect.log( `=== 开始编译 ${book.name} ===`)\r\n let process = processPercentage(0.4)\r\n /** 查询所有文档级block\r\n * TODO 增量编译时不应该全部获取\r\n */\r\n const Doc_blocks: DB_block[] = await allDocBlock_by_bookId(book.id)\r\n /** docBlock 的引用没有更新:true */\r\n function refsNotUpdated(docBlock: DB_block): boolean {\r\n const refs = config.__skipBuilds__[docBlock.id]?.refs ?? []\r\n for (const ref_id of refs) {\r\n const new_doc_hash = Doc_blocks.find(\r\n (docBlock) => docBlock.id === ref_id,\r\n )?.hash\r\n const old_doc_hash = config.__skipBuilds__[ref_id]?.hash\r\n if (new_doc_hash === undefined || old_doc_hash === undefined) {\r\n /** 不应该进入此分支的,如果进来了就重新编译吧 */\r\n return false\r\n } else if (new_doc_hash === old_doc_hash) {\r\n continue\r\n } else {\r\n return false\r\n }\r\n }\r\n /** 引用的都没有更新 */\r\n return true\r\n }\r\n effect.log (`=== 查询文档级block完成 ===`)\r\n let i = 0\r\n await Promise.all(\r\n Doc_blocks.map(async (docBlock) => {\r\n const sy = await get_doc_by_SyPath(DB_block_path(docBlock))\r\n docTree[docBlock.hpath] = { sy, docBlock }\r\n i++\r\n process(i / Doc_blocks.length)\r\n }),\r\n )\r\n const fileTree: FileTree = {}\r\n\r\n process = processPercentage(0.4)\r\n\r\n const enableIncrementalCompilation_doc = (() => {\r\n if (packageJson.version !== config.OceanPress.version) {\r\n effect.log(\r\n `配置文件版本号[${config.OceanPress.version}]与OceanPress版本[${packageJson.version}]不一致,将进行文档全量编译`,\r\n )\r\n return false\r\n }\r\n return config.enableIncrementalCompilation_doc\r\n })()\r\n effect.log (`=== 开始渲染文档 ===`)\r\n await Promise.all(\r\n Object.entries(docTree).map(async ([path, { sy, docBlock }]) => {\r\n if (\r\n config.enableIncrementalCompilation &&\r\n enableIncrementalCompilation_doc &&\r\n /** 文档本身没有发生变化 */\r\n config.__skipBuilds__[docBlock.id]?.hash === docBlock.hash &&\r\n /** docBlock所引用的文档也没有更新 */\r\n refsNotUpdated(docBlock)\r\n )\r\n return /** skip */\r\n\r\n try {\r\n const rootLevel =\r\n path.split('/').length -\r\n 2 /** 最开头有一个 / 还有一个 data 目录所以减二 */\r\n const renderInstance = getRender()\r\n\r\n fileTree[path + '.html'] = await htmlTemplate(\r\n {\r\n title: sy.Properties?.title || '',\r\n htmlContent: await _renderHTML(sy, renderInstance),\r\n level: rootLevel,\r\n },\r\n {\r\n ...tempConfig.cdn,\r\n embedCode: config.embedCode,\r\n },\r\n )\r\n\r\n /** rss.xml 生成 */\r\n if (config.sitemap.rss && path.endsWith('.rss.xml')) {\r\n const rssPath = path\r\n fileTree[rssPath] =await generateRSSXML(rssPath, renderInstance, config)\r\n effect.log(`渲染 rss.xml:${rssPath} 完毕`)\r\n }\r\n if (\r\n config.enableIncrementalCompilation &&\r\n config.enableIncrementalCompilation_doc\r\n ) {\r\n /** 更新为当前hash */\r\n skipBuilds.add(docBlock.id, {\r\n hash: docBlock.hash,\r\n })\r\n }\r\n /** 无论是否配置增量更新都要更新正向引用,不然开启增量更新后没有引用数据可用 */\r\n skipBuilds.add(docBlock.id, {\r\n refs: /** 保存引用 */ [...renderInstance.refs.values()],\r\n })\r\n } catch (error) {\r\n effect.log(`${path} 渲染失败:${error}`)\r\n console.log(error)\r\n }\r\n process(i / Doc_blocks.length)\r\n effect.log(`渲染完毕:${path}`)\r\n }),\r\n )\r\n effect.log( `=== 渲染文档完成 ===`)\r\n effect.log( `=== 开始生成 sitemap.xml ===`)\r\n if (config.sitemap.enable) {\r\n fileTree['sitemap.xml'] = sitemap_xml(Doc_blocks, config.sitemap)\r\n }\r\n if (config.excludeAssetsCopy === false) {\r\n effect.log( `=== 开始复制资源文件 ===`)\r\n const assets: {\r\n box: string\r\n docpath: string\r\n path: string\r\n hash: string\r\n id: string\r\n }[] = await API.query_sql({\r\n stmt: `SELECT * from assets\r\n WHERE box = '${book.id}'\r\n limit 150000 OFFSET 0`,\r\n })\r\n await Promise.all(\r\n assets.map(async (item) => {\r\n if (\r\n config.enableIncrementalCompilation &&\r\n /** 资源没有变化,直接跳过 */\r\n config.__skipBuilds__[item.id]?.hash === item.hash\r\n ) {\r\n return /** skip */\r\n } else {\r\n fileTree[item.path] = await API.get_assets({\r\n path: item.path,\r\n })\r\n if (config.enableIncrementalCompilation) {\r\n skipBuilds.add(item.id, { hash: item.hash })\r\n }\r\n }\r\n }),\r\n )\r\n effect.log( `=== 开始复制挂件资源文件 ===`)\r\n const widgetList: DB_block[] = await API.query_sql({\r\n stmt: `\r\n SELECT *\r\n from blocks\r\n WHERE box = '${book.id}'\r\n AND type = 'widget'\r\n limit 150000 OFFSET 0\r\n `,\r\n })\r\n const widgetNode = (\r\n await Promise.all(\r\n widgetList.map(async (el) => await get_node_by_id(el.id)),\r\n )\r\n )\r\n .filter(\r\n (widget) =>\r\n (widget?.Properties as any)?.['custom-oceanpress-widget-update'],\r\n )\r\n .map(async (widget) => {\r\n if (!widget || !widget?.ID) return\r\n const update = (widget?.Properties as any)?.[\r\n 'custom-oceanpress-widget-update'\r\n ] as string\r\n if (\r\n config.enableIncrementalCompilation &&\r\n config.__skipBuilds__[widget.ID]?.updated === update\r\n ) {\r\n return /** 资源没有变化,直接跳过 */\r\n } else {\r\n const id = widget.ID\r\n // 快照保存的位置 `/data/storage/oceanpress/widget_img/${id}.jpg`\r\n fileTree[`assets/widget/${id}.jpg`] = (await API.file_getFile({\r\n path: `data/storage/oceanpress/widget_img/${id}.jpg`,\r\n })) as ArrayBuffer\r\n if (config.enableIncrementalCompilation) {\r\n skipBuilds.add(id, { updated: update })\r\n }\r\n }\r\n })\r\n await Promise.all(widgetNode)\r\n }\r\n\r\n // === 输出编译成果 ===\r\n if (otherConfig?.onFileTree) {\r\n otherConfig.onFileTree(fileTree)\r\n }\r\n if (config.compressedZip) {\r\n effect.log( `=== 开始生成压缩包 ===`)\r\n await downloadZIP(fileTree, {\r\n // TODO 这里应该移出来成为全局的写选项\r\n withoutZip: tempConfig.withoutPublicZip,\r\n publicZip: tempConfig.cdn.publicZip,\r\n })\r\n }\r\n config.OceanPress.version = packageJson.version\r\n /** 更新跳过编译的资源 */\r\n skipBuilds.write()\r\n effect.percentage(100)\r\n effect.log( '编译完毕')\r\n\r\n return {fileTree}\r\n}\r\n\r\n\r\nfunction useSkipBuilds() {\r\n const obj: { [k: string]: { hash?: string } } = {}\r\n return {\r\n add(\r\n id: string,\r\n value: { hash?: string; refs?: string[]; updated?: string },\r\n ) {\r\n if (obj[id] === undefined) {\r\n obj[id] = {}\r\n }\r\n deepAssign(obj[id], value)\r\n },\r\n /** 将缓存的写入到配置文件 */\r\n write() {\r\n deepAssign(currentConfig.value.__skipBuilds__, obj)\r\n },\r\n }\r\n}\r\n","import { createRPC } from 'oceanpress-rpc'\r\nimport type { API } from 'oceanpress-server'\r\nimport { stringify } from 'superjson'\r\nimport { type Config } from '~/core/config.ts'\r\nimport { genZIP } from '~/core/genZip.ts'\r\nimport type { OceanPressPlugin } from '~/core/ocean_press.ts'\r\n\r\n/** 上传数据到 s3 适配云端 */\r\nexport function deployOceanPressServer_plugin(config: Config) {\r\n const plugin: OceanPressPlugin = {\r\n async build_onFileTree([tree], next) {\r\n next(tree)\r\n\r\n const client = await createRPC<API>('apiConsumer', {\r\n async remoteCall(method, data) {\r\n let body: ReadableStream | string | Blob\r\n // 如果第一参数是 ReadableStream 的时候,直接使用 ReadableStream 作为 body,不用考虑其他参数,因为这种情况只支持一个参数\r\n let content_type\r\n if (data[0] instanceof ReadableStream) {\r\n // body = data[0] //会遇到一些兼容性问题, http 1.1 不支持使用流作为 body,需要转换为 blob 或者 arraybuffer\r\n\r\n body = await new Response(data[0]).blob()\r\n content_type = 'application/octet-stream'\r\n } else {\r\n body = stringify(data)\r\n console.log('[body]', body)\r\n content_type = 'application/json'\r\n }\r\n return fetch(`${config.oceanPressServer.apiBase}/api/${method}`, {\r\n method: 'POST',\r\n body,\r\n headers: {\r\n 'x-api-key': config.oceanPressServer.apiKey,\r\n 'Content-Type': content_type,\r\n },\r\n // @ts-expect-error 在 node 运行的时候需要声明双工模式才能正确发送 ReadableStream,TODO 需要验证浏览器端可以这样运行吗\r\n duplex: 'half', // 关键:显式声明半双工模式\r\n })\r\n .then((res) => res.json())\r\n .then((r) => {\r\n if (r.error) {\r\n console.log('[r]', r)\r\n throw new Error()\r\n }\r\n return r.result\r\n })\r\n },\r\n })\r\n const zip = await genZIP(tree, { withoutZip: true })\r\n const sizeInMB = zip.size / (1024 * 1024)\r\n console.log('[zip.size in MB]', sizeInMB.toFixed(2))\r\n // 将 Blob 转换为 ReadableStream\r\n const readableStream = zip.stream()\r\n const { chunkCount, fileId } = await client.API.upload(readableStream)\r\n\r\n console.log('[res]', { chunkCount, fileId })\r\n const res = await client.API.deploy({ zipFileId: fileId })\r\n console.log('[deploy res]', res)\r\n },\r\n }\r\n return plugin\r\n}\r\n","import { MeilisearchPlugin } from '~/plugins/meilisearch_plugin/meilisearch_upload.ts'\r\nimport { Config } from './config.ts'\r\nimport { PluginCenter } from './plugin.ts'\r\nimport { s3Upload_plugin } from '~/plugins/publish/s3.ts'\r\nimport { FileTree, build } from './build.ts'\r\nimport { renderHTML } from './render.ts'\r\nimport { deployOceanPressServer_plugin } from '~/plugins/publish/OceanPressServer.ts'\r\n\r\nexport type OceanPressPlugin = PluginCenter<OceanPress['funMap']>['pluginType']\r\n\r\n/** OceanPress 核心类,用于管理插件和配置,执行构建过程。 */\r\nexport class OceanPress {\r\n async build(effect: {\r\n log: (msg: string) => void\r\n percentage: (_n: number) => void\r\n }) {\r\n const build_res = this.pluginCenter.fun.build(this.config, effect, {\r\n renderHtmlFn: this.pluginCenter.fun.build_renderHTML,\r\n onFileTree: this.pluginCenter.fun.build_onFileTree,\r\n })\r\n return build_res\r\n }\r\n funMap = {\r\n /** 开始整体编译 */\r\n build,\r\n /** 用于渲染文档的函数 */\r\n build_renderHTML: renderHTML,\r\n /** 编译完成后文件树的处理回调函数 */\r\n build_onFileTree: (_tree: FileTree) => {},\r\n }\r\n pluginCenter: PluginCenter<OceanPress['funMap']> = new PluginCenter(\r\n this.funMap,\r\n )\r\n constructor(public config: Config) {\r\n // TODO 内置插件,以后应该改成由用户配置\r\n if (config.meilisearch.enable) {\r\n this.pluginCenter.registerPlugin(\r\n new MeilisearchPlugin(config.meilisearch),\r\n )\r\n }\r\n if (config.s3.enable) {\r\n this.pluginCenter.registerPlugin(s3Upload_plugin)\r\n }\r\n if (config.oceanPressServer.enable) {\r\n this.pluginCenter.registerPlugin(\r\n deployOceanPressServer_plugin(this.config),\r\n )\r\n }\r\n }\r\n}\r\n","import { storeDep } from '~/core/dependency.ts'\r\nimport { DB_block_path, type S_Node } from './siyuan_type.ts'\r\nimport { get_block_by_id, get_doc_by_child_id } from './cache.ts'\r\n\r\nstoreDep.getDocByChildID = async (id: string) => {\r\n return await get_doc_by_child_id(id)\r\n}\r\n\r\nstoreDep.getDocPathBySY = async (sy?: S_Node) => {\r\n if (sy?.ID) {\r\n const block = await get_block_by_id(sy.ID)\r\n if (block) {\r\n return DB_block_path(block)\r\n }\r\n }\r\n}\r\n\r\n/** TODO 应该可以从cache中获取,而不需要查询 */\r\nstoreDep.getHPathByID_Node = async (\r\n id_node: string | S_Node,\r\n): Promise<string> => {\r\n const id = typeof id_node === 'string' ? id_node : id_node.ID\r\n if (id === undefined) throw new Error('id is undefined')\r\n const docNode = await get_doc_by_child_id(id)\r\n if (docNode === undefined) throw new Error('docNode is undefined')\r\n const docBlock = await get_block_by_id(id)\r\n if (docBlock === undefined) throw new Error('docBlock is undefined')\r\n return docBlock.hpath\r\n}\r\n\r\nstoreDep.getNodeByID = async (id?: string): Promise<S_Node | undefined> => {\r\n if (id === undefined) return\r\n const doc = await storeDep.getDocByChildID(id)\r\n if (doc === undefined) return\r\n return getNode(doc)\r\n function getNode(node: S_Node): S_Node | undefined {\r\n if (node.ID === id) return node\r\n if (node.Children === undefined) return\r\n for (const child of node.Children) {\r\n const n = getNode(child)\r\n if (n) return n\r\n }\r\n }\r\n}\r\n","import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'node:fs'\r\nimport { storeDep } from '~/core/dependency.ts'\r\n\r\nstoreDep.getItem = getItem\r\nstoreDep.setItem = setItem\r\n\r\nexport function setItem(key: string, value: string) {\r\n if (!existsSync('./store/')) {\r\n // 目录不存在,递归创建目录\r\n mkdirSync('./store/', { recursive: true })\r\n }\r\n return writeFileSync(`./store/${key}`, value, {\r\n encoding: 'utf-8',\r\n })\r\n}\r\n\r\nexport function getItem(key: string): string | undefined {\r\n try {\r\n return readFileSync(`./store/${key}`, 'utf-8')\r\n } catch (_) {\r\n return undefined\r\n }\r\n}\r\n","import '~/core/render.api.dep'\nimport '~/util/store.node.dep'\nimport { Command } from 'commander'\n\nexport const program = new Command()\n\nprogram\n .name('OceanPress')\n .description('这是一款从思源笔记本生成一个静态站点的工具')\n","import { Command } from 'commander'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { resolve } from 'path'\nimport { join } from 'path/posix'\nimport { program } from './common.ts'\nimport { currentConfig, loadConfigFile } from '~/core/config.ts'\nimport { OceanPress } from '~/core/ocean_press.ts'\n\nprogram\n .command('build')\n .description('输出静态站点源码')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-o, --output <string>', '指定输出目录位置')\n .action(async (opt: { config: string; output: string }) => {\n if (!opt.config || !opt.output) {\n console.log(`请设置配置文件位置和输出目录位置`)\n throw new Error('请设置配置文件位置和输出目录位置')\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n const filePath = resolve(opt.output)\n const ocean_press = new OceanPress(currentConfig.value)\n\n // node 端写磁盘插件\n ocean_press.pluginCenter.registerPlugin({\n async build_onFileTree([tree]) {\n for (const [path, data] of Object.entries(tree)) {\n const fullPath = join(filePath, './', path)\n const pathArray = fullPath.split('/').slice(0, -1)\n const dirPath = pathArray.join('/')\n mkdir(dirPath, { recursive: true })\n try {\n if (typeof data === 'string') {\n await writeFile(fullPath, data, 'utf-8')\n } else {\n await writeFile(fullPath, new DataView(data))\n }\n } catch (error) {\n console.log(`${fullPath} 无法写入`)\n }\n }\n },\n })\n\n await ocean_press.build({\n log: (msg) => {\n if (msg.startsWith('渲染:')) {\n process.stdout.write(`\\r\\x1b[K${msg}`)\n } else {\n process.stdout.write(`\\n${msg}`)\n }\n },\n percentage: (n) => {\n process.stdout.write(`\\r\\x1b[K进度:${n}%`)\n },\n })\n })\n","import { readFile } from 'fs/promises'\nimport { setCache } from '~/core/cache.ts'\nimport { loadConfigFile } from '~/core/config.ts'\nimport { server } from '~/server.ts'\nimport { program } from './common.ts'\nprogram\n .command('server')\n .description('启动动态代理')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-h, --host <string>', 'web服务绑定到的地址', '127.0.0.1')\n .option('-p, --port <number>', 'web服务绑定到的端口', '80')\n .option(\n '--cache <boolean>',\n '配置为 true 时开启缓存,默认为 false 不开启缓存',\n 'false',\n )\n .action(\n async (opt: {\n config: string\n host: string\n port: string\n cache: 'false'\n }) => {\n if (!opt.config) {\n console.log(`请设置配置文件位置`)\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n setCache(opt.cache !== 'false')\n server({\n hostname: opt.host,\n port: Number(opt.port),\n })\n },\n )\n","import { serve } from '@hono/node-server'\r\nimport { createHonoApp } from './core/hono_server.ts'\r\nimport { serveStatic } from '@hono/node-server/serve-static'\r\nimport { Hono } from 'hono'\r\nimport { join, resolve } from 'path/posix'\r\nconsole.log(join(import.meta.url.slice(5), '../../public/'))\r\n\r\nexport function server(config = { port: 80, hostname: '0.0.0.0' }) {\r\n const app = new Hono()\r\n\r\n // 方便开发调试样式\r\n app.use(\r\n '/notebook/*',\r\n serveStatic({\r\n root: './public/',\r\n onNotFound(path, c) {\r\n console.log('[onNotFound notebook path]', path)\r\n },\r\n }),\r\n )\r\n createHonoApp(app)\r\n return new Promise((resolve, _reject) => {\r\n serve(\r\n {\r\n fetch: app.fetch,\r\n port: config.port,\r\n hostname: config.hostname,\r\n },\r\n (info) => {\r\n resolve({ info, app })\r\n console.log(`Listening on http://${info.address}:${info.port}`)\r\n },\r\n )\r\n })\r\n}\r\n","import { Context, Hono } from 'hono'\r\nimport { currentConfig, tempConfig } from './config.ts'\r\nimport { get_doc_by_hpath } from './cache.ts'\r\nimport { htmlTemplate } from './htmlTemplate.ts'\r\nimport { renderHTML } from './render.ts'\r\nimport { stream } from 'hono/streaming'\r\nimport type { StatusCode } from 'hono/utils/http-status'\r\n\r\nexport function createHonoApp(app: Hono = new Hono()) {\r\n app.get('/', (c) => c.redirect('/index.html'))\r\n app.get('/assets/*', assetsHandle)\r\n app.get('*', async (c) => {\r\n const path = decodeURIComponent(c.req.path)\r\n\r\n const r = await renderHtmlByUriPath(path).catch(async (err: Error) => {\r\n if (err.message.includes('not doc')) {\r\n return await assetsHandle(c)\r\n }\r\n throw err\r\n })\r\n\r\n if (r instanceof Error) {\r\n throw r\r\n } else if (typeof r === 'string') {\r\n return c.html(r)\r\n } else {\r\n return r\r\n }\r\n })\r\n return app\r\n}\r\nasync function assetsHandle(c: Context) {\r\n // TODO 处于安全考虑应该防范 file 跳出 assets\r\n const file = c.req.path\r\n const widgetPrefix = '/assets/widget/'\r\n const isWidget = file.startsWith(widgetPrefix)\r\n const apiPath = `${currentConfig.value.apiPrefix}${\r\n isWidget ? '/api/file/getFile' : file\r\n }`\r\n const r = await fetch(apiPath, {\r\n headers: {\r\n Authorization: `Token ${currentConfig.value.authorized}`,\r\n },\r\n method: isWidget ? 'POST' : 'GET',\r\n body: isWidget\r\n ? JSON.stringify({\r\n path: `/data/storage/oceanpress/widget_img/${file.substring(\r\n widgetPrefix.length,\r\n )}`,\r\n })\r\n : undefined,\r\n })\r\n const body = r.body\r\n if (!body) {\r\n return c.text('响应体为 null', 500, { 'Content-Type': 'text/plain' })\r\n }\r\n c.status(r.status as StatusCode)\r\n return stream(c, async (writeStream) => {\r\n const reader = body.getReader()\r\n while (true) {\r\n const r = await reader.read()\r\n if (r.done) {\r\n writeStream.close()\r\n break\r\n } else {\r\n writeStream.write(r.value)\r\n }\r\n }\r\n })\r\n}\r\nasync function renderHtmlByUriPath(path: string): Promise<string | Error> {\r\n const hpath = decodeURIComponent(path)\r\n .replace(/\\#(.*)?$/, '')\r\n .replace(/\\.html$/, '')\r\n\r\n const doc = await get_doc_by_hpath(hpath)\r\n\r\n return await htmlTemplate(\r\n {\r\n title: doc.Properties?.title || '',\r\n htmlContent: await renderHTML(doc),\r\n level: path.split('/').length - 1 /** 最开头有一个 / */,\r\n },\r\n {\r\n ...tempConfig.cdn,\r\n embedCode: currentConfig.value.embedCode,\r\n },\r\n )\r\n}\r\n","\r\n\r\nimport './cli/deploy.ts'\r\nimport './cli/build.ts'\r\nimport './cli/server.ts'\r\nimport { program } from './cli/common.ts'\r\n\r\nprogram.parse(process.argv)\r\n"],"mappings":"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","names":["createRPC","stringify","html","html","c","version","watch","watch","usePromiseComputed","fn","html","sy","process","docBlock","res","createRPC","stringify","readFile","readFile","readFile","r","Hono","join","resolve","readFile"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/deploy.ts","../../rpc/src/createRPC.ts","../src/core/dependency.ts","../src/util/deep_assign.ts","../src/core/config.ts","../package.json","../src/core/genZip.ts","../src/plugins/meilisearch_plugin/meilisearch_upload.ts","../src/core/plugin.ts","../src/plugins/publish/s3.ts","../src/core/htmlTemplate.ts","../src/util/escaping.ts","../src/components/data_promise/index.ts","../src/core/siyuan_api.ts","../src/core/render.ts","../src/core/siyuan_type.ts","../src/core/cache.ts","../src/core/genRssXml.ts","../src/core/build.ts","../src/plugins/publish/OceanPressServer.ts","../src/core/ocean_press.ts","../src/core/render.api.dep.ts","../src/util/store.node.dep.ts","../src/cli/common.ts","../src/cli/build.ts","../src/cli/server.ts","../src/server.ts","../src/core/hono_server.ts","../src/cli.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { createRPC } from 'oceanpress-rpc'\nimport type { API } from 'oceanpress-server'\nimport { stringify } from 'superjson'\nimport { currentConfig, loadConfigFile } from '~/core/config.ts'\nimport { genZIP } from '~/core/genZip.ts'\nimport { OceanPress } from '~/core/ocean_press.ts'\nimport { program } from './common.ts'\n\nprogram\n .command('deploy')\n .description('部署站点')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-h, --apiBase <string>', 'OceanPress server 地址')\n .option('-k, --apiKey <string>', 'OceanPress server Api 密钥')\n .action(async (opt: { config: string; apiBase: string; apiKey: string }) => {\n if (!opt.apiBase || !opt.apiKey) {\n return console.error(`请配置 apiBase 和 apiKey`)\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n const client = await createRPC<API>('apiConsumer', {\n remoteCall(method, data) {\n let body: ReadableStream | string\n // 如果第一参数是 ReadableStream 的时候,直接使用 ReadableStream 作为 body,不用考虑其他参数,因为这种情况只支持一个参数\n let content_type\n if (data[0] instanceof ReadableStream) {\n body = data[0]\n content_type = 'application/octet-stream'\n } else {\n body = stringify(data)\n console.log('[body]', body)\n content_type = 'application/json'\n }\n return fetch(`${opt.apiBase}/api/${method}`, {\n method: 'POST',\n body,\n headers: {\n 'x-api-key': opt.apiKey,\n 'Content-Type': content_type,\n },\n // @ts-expect-error 在 node 运行的时候需要声明双工模式才能正确发送 ReadableStream,TODO 需要验证浏览器端可以这样运行吗\n duplex: 'half', // 关键:显式声明半双工模式\n })\n .then((res) => res.json())\n .then((r) => {\n if (r.error) {\n console.log('[r]', r)\n throw new Error()\n }\n return r.result\n })\n },\n })\n const ocean_press = new OceanPress(currentConfig.value)\n\n ocean_press.pluginCenter.registerPlugin({\n async build_onFileTree([tree], next) {\n const zip = await genZIP(tree, { withoutZip: true })\n const sizeInMB = zip.size / (1024 * 1024)\n console.log('[zip.size in MB]', sizeInMB.toFixed(2))\n // 将 Blob 转换为 ReadableStream\n const readableStream = zip.stream()\n const { chunkCount, fileId } = await client.API.upload(readableStream)\n\n console.log('[res]', { chunkCount, fileId })\n const res = await client.API.deploy({ zipFileId: fileId })\n console.log('[deploy res]', res)\n },\n })\n\n await ocean_press.build({\n log: (msg) => {\n if (msg.startsWith('渲染:')) {\n process.stdout.write(`\\r\\x1b[K${msg}`)\n } else {\n process.stdout.write(`\\n${msg}`)\n }\n },\n percentage: (n) => {\n process.stdout.write(`\\r\\x1b[K进度:${n}%`)\n },\n })\n })\n","/** ═════════🏳🌈 超轻量级的远程调用,完备的类型提示! 🏳🌈═════════ */\n\ninterface commonOptions {\n middleware?: ((method: string, data: any[], next: () => Promise<any>) => Promise<any>)[]; // 统一的中间件\n}\n\nexport async function createRPC<API_TYPE>(\n ...[type, options]:\n | [\n 'apiProvider',\n commonOptions & {\n genApiModule: () => Promise<API_TYPE>;\n },\n ]\n | [\n 'apiConsumer',\n commonOptions & {\n /** 配置此选项替换默认的远程调用函数,默认逻辑采用 fetch 实现。 */\n remoteCall: (method: string, data: any[]) => Promise<any>; // 远程调用函数\n },\n ]\n) {\n const apiModule = type === 'apiProvider' ? await options.genApiModule() : undefined;\n\n const remoteCall = type === 'apiConsumer' ? options.remoteCall : undefined;\n\n async function RC<K extends string>(method: K, data: any[]): Promise<any> {\n // 洋葱路由的核心逻辑\n async function executeMiddleware(index: number): Promise<any> {\n if (options.middleware && index < options.middleware.length) {\n return options.middleware[index](method, data, () => executeMiddleware(index + 1));\n } else {\n return executeCall();\n }\n }\n\n async function executeCall(): Promise<any> {\n try {\n if (type === 'apiProvider') {\n const methodParts = method.split('.');\n let currentObj: any = apiModule;\n for (const part of methodParts) {\n if (currentObj && typeof currentObj === 'object' && part in currentObj) {\n currentObj = currentObj[part];\n } else {\n throw new Error(`Method ${method} not found`);\n }\n }\n if (typeof currentObj === 'function') {\n return await currentObj(...data);\n } else {\n throw new Error(`${method} is not a function`);\n }\n } else {\n return await remoteCall!(method, data);\n }\n } catch (error) {\n console.error('API call failed:', error);\n throw error;\n }\n }\n\n return await executeMiddleware(0);\n }\n\n /** Remote call , 会就近的选择是远程调用还是使用本地函数 */\n\n /** 创建嵌套的Proxy处理器 */\n function createNestedProxy(path: string[] = []): ProxyHandler<object> {\n return {\n get(target, prop: string) {\n if (prop === 'then') {\n // Handle the case when the proxy is accidentally treated as a Promise\n return undefined;\n }\n const newPath = [...path, prop];\n return new Proxy(function (...args: any[]) {\n const method = newPath.join('.');\n return RC(method, args);\n }, createNestedProxy(newPath));\n },\n apply(target, thisArg, args) {\n const method = path.join('.');\n return RC(method, args);\n },\n };\n }\n /** 包装了一次的 RC 方便跳转到函数定义 */\n const API = new Proxy(function () {}, createNestedProxy()) as unknown as NestedAsyncAPI<API_TYPE>;\n return { API, RC };\n}\n\ntype AsyncifyReturnType<T> = T extends (...args: any[]) => infer R\n ? R extends Promise<any>\n ? T\n : (...args: Parameters<T>) => Promise<Awaited<R>>\n : T;\n\ntype DeepAsyncify<T> = T extends (...args: any[]) => any\n ? AsyncifyReturnType<T>\n : T extends object\n ? { [K in keyof T]: DeepAsyncify<T[K]> }\n : T;\n/** 因为如果是客户端调用,那么返回值必须要是 promise 风格的,所以使用这个类型来将所有返回值的类型包裹一层promise */\ntype NestedAsyncAPI<T> = {\n [K in keyof T]: DeepAsyncify<T[K]>;\n};\n","import type { S_Node } from './siyuan_type.ts'\r\n\r\n/** 默认填充函数,不应当被调用 */\r\nconst nullDep: any = () => {\r\n throw new Error('不可调用未填充的依赖')\r\n}\r\n\r\n/** ════════════════════════🏳🌈 全局依赖 🏳🌈════════════════════════\r\n * 供不同入口注入不同依赖实现\r\n ** ════════════════════════🚧 全局依赖 🚧════════════════════════ */\r\nexport const storeDep = {\r\n // 读写配置文件所依赖的副作用\r\n setItem: nullDep as (key: string, value: string) => void,\r\n getItem: nullDep as (key: string) => string | undefined,\r\n\r\n // render功能依赖的副作用\r\n getNodeByID: nullDep as (id?: string) => Promise<S_Node | undefined>,\r\n getDocPathBySY: nullDep as (sy?: S_Node) => Promise<string | undefined>,\r\n getDocByChildID: nullDep as (id: string) => Promise<S_Node | undefined>,\r\n getHPathByID_Node: nullDep as (id_node: string | S_Node) => Promise<string>,\r\n}\r\n","export function deepAssign<T>(target: any, source: any, config = { add: true, update: true }): T {\r\n for (let key in source) {\r\n if (source.hasOwnProperty(key)) {\r\n if (source[key] instanceof Object && !Array.isArray(source[key])) {\r\n // 如果属性是对象且不是数组,则递归执行深度合并\r\n if (!target.hasOwnProperty(key)) {\r\n // 目标对象不存在该属性则创建空对象\r\n target[key] = {};\r\n }\r\n deepAssign(target[key], source[key], config);\r\n } else {\r\n // 如果属性不是对象或者是数组,则直接赋值\r\n if (!target.hasOwnProperty(key) && config.add) {\r\n // 目标属性不存在属于新增\r\n target[key] = source[key];\r\n } else if (config.update) {\r\n // 更新\r\n target[key] = source[key];\r\n }\r\n }\r\n }\r\n }\r\n return target;\r\n }\r\n","import { storeDep } from '~/core/dependency.ts'\r\nimport { deepAssign } from '~/util/deep_assign.ts'\r\nimport { computed, reactive, watch } from 'vue'\r\nimport { notebook } from './siyuan_type.ts'\r\nimport packageJson from '~/../package.json' with { type: 'json' };\r\nconst version = packageJson.version\r\n\r\n/** 不要在运行时修改这个对象,他只应该在代码中配置 */\r\nconst defaultConfig = {\r\n name: 'default',\r\n /** 需要编译的笔记本 */\r\n notebook: {} as notebook,\r\n /** 思源的鉴权key */\r\n authorized: '',\r\n /** 思源的api服务地址 */\r\n apiPrefix: 'http://127.0.0.1:6806',\r\n /** 打包成 zip */\r\n compressedZip: true,\r\n /** 不将 publicZip 打包到 zip 包中 */\r\n // withoutPublicZip: true,\r\n /** 不复制 assets/ ,勾选此选项则需要自行处理资源文件 */\r\n excludeAssetsCopy: false,\r\n /** 输出站点地图相关 */\r\n sitemap: {\r\n /** 控制是否输出 sitemap.xml,不影响 rss 选项 */\r\n enable: true,\r\n /** 默认为 \".\" 生成路径例如 \"./record/思源笔记.html\"\r\n * 但 sitemap 并不建议采用相对路径所以应该替换成例如 \"https://shenzilong.cn\"\r\n * 则会生成 \"https://shenzilong.cn/record/思源笔记.html\" 这样的绝对路径\r\n * 参见 https://www.sitemaps.org/protocol.html#escaping\r\n */\r\n sitePrefix: '.',\r\n /** 站点地址 */\r\n siteLink: '',\r\n /** 站点描述 */\r\n description: '',\r\n /** 站点标题 */\r\n title: '',\r\n /** 开启 rss 生成,对于文件名为 .rss.xml 结尾的文档生效 */\r\n rss: true,\r\n },\r\n /** 开启增量编译,当开启增量编译时,\r\n * 在编译过程中会依据 __skipBuilds__ 的内容来跳过一些没有变化不需要重新输出的内容\r\n */\r\n enableIncrementalCompilation: false,\r\n /**\r\n * 要全量编译文档时将此选项设置为false,当OceanPress版本和上次编译时不同时会忽略此属性全量编译文档\r\n */\r\n enableIncrementalCompilation_doc: true,\r\n /** 跳过编译的资源 */\r\n __skipBuilds__: {} as {\r\n [id: string]:\r\n | {\r\n hash?: string\r\n /** 此文档正向引用的其他文档的id */ refs?: string[]\r\n /** 挂件快照的更新时间 */ updated?: string\r\n }\r\n | undefined\r\n },\r\n\r\n // cdn: {\r\n // /** 思源 js、css等文件的前缀 */\r\n // siyuanPrefix:\r\n // 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/notebook/',\r\n // /** 思源 js、css等文件zip包地址 */\r\n // publicZip:\r\n // 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/public.zip',\r\n // },\r\n /** s3 上传配置\r\n * https://help.aliyun.com/zh/oss/developer-reference/use-amazon-s3-sdks-to-access-oss#section-2ri-suq-pb3\r\n */\r\n s3: {\r\n enable: false,\r\n bucket: '',\r\n region: '',\r\n pathPrefix: '',\r\n endpoint: '',\r\n accessKeyId: '',\r\n secretAccessKey: '',\r\n },\r\n /** 部署到 oceanPressServer 的配置 */\r\n oceanPressServer:{\r\n enable: false,\r\n apiBase:'',\r\n apiKey:'',\r\n },\r\n meilisearch: {\r\n enable: false,\r\n host: '',\r\n apiKey: '',\r\n indexName: '',\r\n },\r\n /** html模板嵌入代码块,会将此处配置中的代码嵌入到生成的html所对应的位置 */\r\n embedCode: {\r\n head: '',\r\n beforeBody: '',\r\n afterBody: `<footer>\r\n<p style=\"text-align:center;margin:15px 0;\">\r\n 技术支持:\r\n <a target=\"_blank\" href=\"https://github.com/2234839/oceanPress_js\">OceanPress</a> |\r\n 开发者:\r\n <a target=\"_blank\" href=\"https://shenzilong.cn\">崮生(子虚)</a>\r\n</p>\r\n</footer>`,\r\n },\r\n OceanPress: {\r\n /** 此配置文件编译时的版本 */\r\n version: version,\r\n },\r\n}\r\nexport type Config = typeof defaultConfig\r\nexport const configs = reactive({\r\n /** 当前所使用的配置项的 key */\r\n __current__: 'default' as const,\r\n /** 为true是表示是代码中设置的默认值,不会保存到本地,避免覆盖之前保存的数据,在加载本地配置后会自动修改为false */\r\n __init__: true,\r\n default: deepAssign<typeof defaultConfig>({}, defaultConfig),\r\n})\r\n\r\nexport function addConfig(name: string, value?: typeof defaultConfig) {\r\n configs[name as 'default'] = deepAssign<typeof defaultConfig>(\r\n {},\r\n value ?? defaultConfig,\r\n )\r\n}\r\n/** 加载配置文件 */\r\nexport const loadConfigFile = (c?: typeof configs) => {\r\n if (c) {\r\n deepAssign(configs, c)\r\n } else {\r\n const localConfig = storeDep.getItem('configs')\r\n if (localConfig) {\r\n /** 从本地存储加载配置 */\r\n deepAssign(configs, JSON.parse(localConfig))\r\n }\r\n }\r\n\r\n Object.entries(configs)\r\n .filter(([key]) => key.startsWith('__') === false)\r\n .forEach(([_key, obj]) => {\r\n /** 将新增配置项更新到旧配置上 */\r\n deepAssign(obj, defaultConfig, { update: false, add: true })\r\n })\r\n}\r\nexport const currentConfig = computed(() => configs[configs.__current__])\r\n\r\n/** 应该要给用户配置的,但目前没有什么好方法,所以暂时不给配置 */\r\nexport const tempConfig = {\r\n cdn: {\r\n /** 思源 js、css等文件的前缀 */\r\n siyuanPrefix:\r\n 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@latest/apps/frontend/public/notebook/',\r\n /** 思源 js、css等文件zip包地址 */\r\n publicZip:\r\n 'https://fastly.jsdelivr.net/gh/siyuan-note/oceanpress@v0.0.7/apps/frontend/public/public.zip',\r\n },\r\n withoutPublicZip:true,\r\n}\r\n\r\nexport const saveConfig = () => {\r\n if (configs.__init__ === false)\r\n storeDep.setItem('configs', JSON.stringify(configs, null, 2))\r\n}\r\n\r\nlet timer: ReturnType<typeof setTimeout> | null = null\r\n/** 防抖的保存配置 */\r\nexport const debounceSaveConfig = () => {\r\n if (timer) {\r\n clearTimeout(timer)\r\n }\r\n timer = setTimeout(() => {\r\n saveConfig()\r\n timer = null\r\n }, 700)\r\n}\r\nwatch(configs, debounceSaveConfig, { deep: true })\r\n\r\nconfigs.__init__ = false\r\n\r\n/** 浏览器环境下,直接尝试加载配置 */\r\nif (globalThis.document) {\r\n loadConfigFile()\r\n}\r\n","{\n \"name\": \"oceanpress\",\n \"version\": \"1.0.4\",\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"cli\": \"tsx ./src/cli.ts\",\n \"cli_watch\": \"tsx watch ./src/cli.ts\",\n \"build\": \"vite build && npm run build_lib\",\n \"build_lib\": \"vite build --config vite.sw.config.ts\",\n \"build_app\": \"vite build --mode library\",\n \"build_cli\": \"tsup\",\n \"build_plugin_ui\": \"vite build --config vite.plugin.config.ts\",\n \"dev_plugin_ui\": \"vite build --watch --config vite.plugin.config.ts\",\n \"generate_dependency_graph\": \"depcruise src --include-only '^src' --output-type dot > ./assets/dep.dot\",\n \"preview\": \"vite preview\"\n },\n \"bin\": {\n \"oceanpress\": \"./dist-cli/cli.js\"\n },\n \"files\": [\n \"dist/assets\",\n \"dist/dev\",\n \"dist/index.html\",\n \"dist/ocean_press-log.png\",\n \"dist-app/assets\",\n \"dist-app/dev\",\n \"dist-app/app.*\",\n \"dist-cli\",\n \"*.md\"\n ],\n \"dependencies\": {\n \"@aws-sdk/client-s3\": \"^3.758.0\",\n \"@hono/node-server\": \"^1.13.8\",\n \"cheerio\": \"1.0.0\",\n \"commander\": \"^13.1.0\",\n \"fzstd\": \"^0.1.1\",\n \"hono\": \"^4.7.4\",\n \"jszip\": \"^3.10.1\",\n \"meilisearch\": \"^0.49.0\",\n \"naive-ui\": \"^2.41.0\",\n \"octokit\": \"^4.1.2\",\n \"superjson\": \"^2.2.2\",\n \"tsx\": \"^4.19.3\",\n \"vditor\": \"^3.10.9\",\n \"vue\": \"^3.5.13\",\n \"vue-router\": \"^4.5.0\",\n \"zstd-codec\": \"^0.1.5\"\n },\n \"devDependencies\": {\n \"oceanpress-rpc\": \"workspace:*\",\n \"oceanpress-server\": \"workspace:*\",\n \"@vitejs/plugin-vue\": \"^5.2.1\",\n \"@vitejs/plugin-vue-jsx\": \"^4.1.1\",\n \"dependency-cruiser\": \"^16.10.0\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.2\",\n \"vite\": \"^6.2.2\",\n \"vite-plugin-vue-devtools\": \"^7.7.2\",\n \"vue-tsc\": \"^2.2.8\"\n }\n}","import JSZip from 'jszip'\n\n/** 下载zip */\nexport async function downloadZIP(\n docTree: { [htmlPath: string]: string | ArrayBuffer },\n config?: { publicZip?: string; withoutZip?: boolean },\n) {\n const content = await genZIP(docTree, config)\n if (globalThis.document) {\n // 将ZIP文件保存为下载\n const link = document.createElement('a')\n link.href = URL.createObjectURL(content)\n link.download = `notebook.zip`\n link.click()\n } else {\n //TODO node 环境下需要写文件\n }\n}\n\nexport async function genZIP(\n docTree: { [htmlPath: string]: string | ArrayBuffer },\n config?: {\n /** 默认的public.zip压缩包内容路径,默认为/public.zip */\n publicZip?: string\n /** 是否不包含默认的public.zip压缩包内容,设置为 true 则会不下载 public.zip 内容合并使用 */\n withoutZip?: boolean\n },\n) {\n const zip = new JSZip()\n if (config?.withoutZip !== true) {\n const presetZip = await (\n await fetch(config?.publicZip ?? '/public.zip')\n ).arrayBuffer()\n await zip.loadAsync(presetZip)\n }\n for (const [path, html] of Object.entries(docTree)) {\n const newPath = path.startsWith('/') ? path.slice(1) : path\n zip.file(newPath, html)\n }\n return await zip.generateAsync({ type: 'blob' })\n}\n","import { Meilisearch, Index } from 'meilisearch'\r\nimport { OceanPressPlugin } from '~/core/ocean_press.ts'\r\nimport { load } from 'cheerio'\r\ntype doc = {\r\n id: string\r\n title?: string\r\n content: string\r\n url: string\r\n lvl0?: string\r\n lvl1?: string\r\n lvl2?: string\r\n lvl3?: string\r\n lvl4?: string\r\n lvl5?: string\r\n lvl6?: string\r\n}\r\nexport class MeilisearchPlugin implements OceanPressPlugin {\r\n _melisearch: Meilisearch | undefined\r\n _index: Index | undefined\r\n _indexName: string\r\n host: string\r\n apiKey: string\r\n constructor(option: { host: string; apiKey: string; indexName: string }) {\r\n this.host = option.host\r\n this.apiKey = option.apiKey\r\n this._indexName = option.indexName\r\n }\r\n async _getMeliSearch() {\r\n if (this._melisearch === undefined) {\r\n this._melisearch = new Meilisearch({\r\n host: this.host,\r\n apiKey: this.apiKey,\r\n })\r\n }\r\n return this._melisearch!\r\n }\r\n async _getIndex() {\r\n if (this._index === undefined) {\r\n const meilisearch = await this._getMeliSearch()\r\n this._index = meilisearch.index(this._indexName)\r\n }\r\n return this._index!\r\n }\r\n docs: { [id: string]: doc } = {}\r\n async addDocument(doc: doc) {\r\n this.docs[doc.id] = doc\r\n }\r\n async updateDocument() {\r\n console.log(`开始上传数据到 ${this.host}`)\r\n const index = await this._getIndex()\r\n const res = await index.addDocuments(Object.values(this.docs))\r\n console.log(`上传结果`, res)\r\n }\r\n build_onFileTree: OceanPressPlugin['build_onFileTree'] = (c, next) => {\r\n const [tree] = c\r\n console.log('开始生成 meilisearch 所需数据结构')\r\n\r\n const htmlTree = Object.keys(tree)\r\n .filter((path) => path.endsWith('.html'))\r\n .map((path) => [path, tree[path]] as const)\r\n for (const [path, html] of htmlTree) {\r\n const $ = load(html.toString())\r\n const entries = $('.h1,.h2,.h3,.h4,.h5,.h6,.p').toArray()\r\n const level: Record<string, string> = { lvl0: $('title').text() }\r\n for (const el of entries) {\r\n /** h1~h6、p */\r\n const c = el.attribs.class\r\n if (c !== 'p') {\r\n Object.keys(level).forEach((lv) => {\r\n if (lv.substring(3, 4) > c.substring(1, 2)) {\r\n /** 跳出层级 */\r\n delete level[lv]\r\n }\r\n })\r\n /** 进入层级 */\r\n level[`lvl${c.substring(1, 2)}`] = $(el).text()\r\n }\r\n this.addDocument({\r\n id: el.attribs.id,\r\n content: $(el).text(),\r\n url: `${path}#${el.attribs.id}`,\r\n ...level,\r\n })\r\n }\r\n\r\n if (path.endsWith('index.html')) break\r\n }\r\n this.updateDocument()\r\n return next(tree)\r\n }\r\n}\r\n","/** 基于洋葱 HOOk 机制的插件管理器\r\n * 我感觉这个手搓的插件机制还可以,类型完备,可拓展性强,\r\n */\r\nexport class PluginCenter<T extends Record<string, (...args: any[]) => any>> {\r\n plugins: PluginCenter<T>['pluginType'][] = []\r\n registerPlugin(plugin: PluginCenter<T>['pluginType']) {\r\n this.plugins.push(plugin)\r\n }\r\n removePlugin(plugin: PluginCenter<T>['pluginType']) {\r\n this.plugins = this.plugins.filter((p) => p !== plugin)\r\n }\r\n /** 洋葱hook调用机制的实现 */\r\n callFn<R extends keyof PluginCenter<T>['pluginType']>(\r\n name: R,\r\n fn: GetMiddlewareFunc<Required<PluginCenter<T>['pluginType']>[R]>,\r\n ) {\r\n return ((...arg: any) => {\r\n // 此处可优化,不必每次都重新生成 middlewareRunner\r\n const m = new middlewareRunner(fn)\r\n // 注入 plugins 中的对应中间件\r\n for (const plugin of this.plugins) {\r\n const middleware = plugin[name]\r\n if (middleware) {\r\n m.use(middleware)\r\n }\r\n }\r\n return m.runMiddlewareHandel(...arg)\r\n }) as GetMiddlewareFunc<Required<PluginCenter<T>['pluginType']>[R]>\r\n }\r\n /** 辅助类型,不可调用! */\r\n pluginType: {\r\n [key in keyof PluginCenter<T>['_funMap']]?: FuncMiddlewares<\r\n PluginCenter<T>['_funMap'][key]\r\n >\r\n } = 0 as any\r\n /** 对需要调用的函数进行代理,完成插件hook介入。 */\r\n fun: PluginCenter<T>['_funMap']\r\n constructor(\r\n /** 原始函数映射表,这里的函数全部可以被插件处理 */\r\n public _funMap: T,\r\n ) {\r\n const that = this\r\n // 可以改成生成对象 {} 的方式,比 proxy 开销要小\r\n this.fun = new Proxy({} as T, {\r\n get(_target, propertyKey, receiver) {\r\n const method = Reflect.get(that._funMap, propertyKey, receiver)\r\n if (typeof method === 'function') {\r\n return (...args: any) => {\r\n return that.callFn(\r\n propertyKey as keyof T,\r\n //@ts-ignore 懒得推类型了。属于内部实现,就直接忽略掉吧\r\n method,\r\n )(...args)\r\n }\r\n }\r\n return method\r\n },\r\n })\r\n }\r\n}\r\n\r\ntype GetMiddlewareFunc<T> = T extends FuncMiddlewares<infer R> ? R : never\r\n\r\n// 小中间件实现,接收一个函数 handel 作为最终执行的函数,当执行 runMiddlewareHandel 时等价于执行 Handel\r\n// 通过 use 注册中间件,类似于洋葱路由,先注册的先执行\r\ntype FuncMiddlewares<Handel extends (...args: any[]) => any> = (\r\n ctx: Parameters<Handel>,\r\n next: Handel,\r\n) => ReturnType<Handel>\r\nclass middlewareRunner<Handel extends (...args: any[]) => any> {\r\n middlewares: FuncMiddlewares<Handel>[] = []\r\n constructor(public handel: Handel) {}\r\n use(middleware: FuncMiddlewares<Handel>) {\r\n this.middlewares.push(middleware)\r\n }\r\n runMiddlewareHandel(...ctx: Parameters<typeof this.handel>) {\r\n let index = 0\r\n const next = ((...ctx2: Parameters<Handel>) => {\r\n const middleware = this.middlewares[index]\r\n index++\r\n if (middleware === undefined) {\r\n return this.handel.call(this, ...ctx2)\r\n }\r\n return middleware(ctx2, next)\r\n }) as Handel\r\n return next.call(this, ...ctx)\r\n }\r\n}\r\n","import type { OceanPressPlugin } from '~/core/ocean_press.ts'\r\nimport type { uploadFiles } from './interface.ts'\r\nimport { S3 } from '@aws-sdk/client-s3'\r\n\r\n/** 上传数据到 s3 适配云端 */\r\nexport const s3Upload_plugin: OceanPressPlugin = {\r\n build: async function ([config, effect, other], next) {\r\n const res = await next(config, effect, {\r\n ...other,\r\n\r\n onFileTree: async (tree) => {\r\n if (other?.onFileTree) {\r\n // 维持原有其他监听程序\r\n await other.onFileTree(tree)\r\n }\r\n for await (const [fileName, ETag] of s3_uploads(tree, config)) {\r\n effect.log(`上传: ${fileName} ${ETag}`)\r\n }\r\n },\r\n })\r\n effect.log(`s3 上传完毕`)\r\n return res\r\n },\r\n}\r\nconst s3_uploads: uploadFiles = async function* (tree, config) {\r\n // https://help.aliyun.com/zh/oss/developer-reference/use-amazon-s3-sdks-to-access-oss#section-2ri-suq-pb3\r\n\r\n const s3 = new S3({\r\n region: config.s3.region,\r\n endpoint: config.s3.endpoint,\r\n credentials: {\r\n accessKeyId: config.s3.accessKeyId,\r\n secretAccessKey: config.s3.secretAccessKey,\r\n },\r\n })\r\n // 将文件逐个上传至 s3\r\n // TODO 可改成并发上传,以缩短时间\r\n const encoder = new TextEncoder()\r\n for (const [path, value] of Object.entries(tree)) {\r\n let buffer: Uint8Array\r\n if (typeof value === 'string') {\r\n buffer = encoder.encode(value)\r\n } else {\r\n buffer = new Uint8Array(value)\r\n }\r\n const r = await s3.putObject({\r\n Bucket: config.s3.bucket,\r\n Key: (config.s3.pathPrefix + path).replace(/\\/\\//g, '/'),\r\n Body: buffer,\r\n })\r\n yield [path, r.ETag] as const\r\n }\r\n}\r\n","export async function htmlTemplate(\r\n p: { htmlContent: string; title: string; level: number },\r\n config?: {\r\n siyuanPrefix: string\r\n embedCode?: { head?: string; beforeBody?: string; afterBody?: string }\r\n },\r\n) {\r\n /** 根据level有几级返回多少个 '../' ,用于解决 file协议打开html文档无法正常加载资源 */\r\n let prePath = ''\r\n if (config?.siyuanPrefix) {\r\n prePath = config.siyuanPrefix\r\n } else {\r\n for (let i = 0; i < p.level; i++) {\r\n prePath += '../'\r\n }\r\n }\r\n const version = '2.10.5'\r\n /** 思源中导出 html 代码: https://github1s.com/siyuan-note/siyuan/blob/HEAD/app/src/protyle/export/index.ts#L652 */\r\n //data-theme-mode=\"dark\" data-light-theme=\"daylight\" data-dark-theme=\"midnight\"\r\n return `<!DOCTYPE html>\r\n<html lang=\"zh_CN\" data-theme-mode=\"light\" data-light-theme=\"daylight\" data-dark-theme=\"midnight\">\r\n<head>\r\n ${config?.embedCode?.head ?? ''}\r\n <meta charset=\"utf-8\" />\r\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\r\n <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\r\n <meta name=\"mobile-web-app-capable\" content=\"yes\" />\r\n <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\" />\r\n <link rel=\"stylesheet\" type=\"text/css\" id=\"baseStyle\" href=\"${prePath}stage/build/export/base.css?${version}\"/>\r\n <script>\r\n function isNightTime() {\r\n const currentHour = new Date().getHours();\r\n return currentHour >= 18 || currentHour < 6;\r\n }\r\n document.write('<link rel=\"stylesheet\" type=\"text/css\" id=\"themeDefaultStyle\" href=\"${prePath}appearance/themes/'+(isNightTime()?'midnight':'daylight')+'/theme.css?${version}\"/>');\r\n </script>\r\n <link rel=\"stylesheet\" type=\"text/css\" href=\"${prePath}appearance/oceanpress.css\"/>\r\n <title>${p.title}</title>\r\n</head>\r\n<body>\r\n ${config?.embedCode?.beforeBody ?? ''}\r\n <div class=\"protyle-wysiwyg protyle-wysiwyg--attr\" id=\"preview\">\r\n ${p.htmlContent}\r\n </div>\r\n <script src=\"${prePath}appearance/icons/material/icon.js?${version}\"></script>\r\n <script src=\"${prePath}stage/build/export/protyle-method.js?${version}\"></script>\r\n <script src=\"${prePath}stage/protyle/js/lute/lute.min.js?${version}\"></script>\r\n <script>\r\n window.siyuan = {\r\n config: {\r\n appearance: {\r\n mode: isNightTime()?1:0,//主题 明亮=0 暗黑=1\r\n codeBlockThemeDark: \"base16/dracula\",\r\n codeBlockThemeLight: \"github\",\r\n },\r\n editor: {\r\n codeLineWrap: true,\r\n codeLigatures: false,\r\n plantUMLServePath: \"https://www.plantuml.com/plantuml/svg/~1\",\r\n codeSyntaxHighlightLineNum: true,\r\n katexMacros: JSON.stringify({}),\r\n },\r\n },\r\n languages: { copy: \"复制\" },\r\n };\r\n const cdn = \"${prePath}stage/protyle\";\r\n const previewElement = document.getElementById(\"preview\");\r\n\r\n Protyle.highlightRender(previewElement, cdn);\r\n Protyle.mathRender(previewElement, cdn, false);\r\n Protyle.mermaidRender(previewElement, cdn);\r\n Protyle.flowchartRender(previewElement, cdn);\r\n Protyle.graphvizRender(previewElement, cdn);\r\n Protyle.chartRender(previewElement, cdn);\r\n Protyle.mindmapRender(previewElement, cdn);\r\n Protyle.abcRender(previewElement, cdn);\r\n Protyle.htmlRender(previewElement);\r\n Protyle.plantumlRender(previewElement, cdn);\r\n document.querySelectorAll(\".protyle-action__copy\").forEach((item) => {\r\n item.addEventListener(\"click\", (event) => {\r\n navigator.clipboard.writeText(\r\n item.parentElement.nextElementSibling.textContent.trimEnd(),\r\n );\r\n event.preventDefault();\r\n event.stopPropagation();\r\n });\r\n });\r\n </script>\r\n ${config?.embedCode?.afterBody ?? ''}\r\n</body>\r\n</html>`\r\n}\r\n","/** html 实体转义 https://www.sitemaps.org/protocol.html#escaping */\r\nexport function escaping(s: string) {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/\"/g, \""\")\r\n .replace(/'/g, \"&apos\");\r\n}\r\nexport function unescaping(s: string) {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/&#(\\d+);/g, (_sub,code) => {\r\n return String.fromCharCode(Number(code));\r\n });\r\n}\r\n","/** ════════════════════════🏳🌈 实用功能 🏳🌈════════════════════════\r\n * 利用 composition-api 实现的一些实用功能\r\n ** ════════════════════════🚧 实用功能 🚧════════════════════════ */\r\nimport { customRef, nextTick, watch, watchEffect, WatchSource } from \"vue\";\r\n\r\nexport class PromiseObj<T, Err = Error> {\r\n pending = false;\r\n fulfilled = false;\r\n rejected = false;\r\n data = {} as T;\r\n error = {} as Err;\r\n _p = Promise.resolve() as Promise<unknown>;\r\n setP(p: Promise<unknown>) {\r\n this._p = p;\r\n }\r\n equalP(p: Promise<unknown>) {\r\n return this._p === p;\r\n }\r\n reLoad() {}\r\n setValue(_data: T) {}\r\n}\r\nexport const continueLoading = Symbol();\r\n\r\nexport interface usePromiseComputedOptions<T> {\r\n /** 函数内的依赖变更的时候就重新计算,指定了 deps 则不会依赖于 getter 内的 ref 了\r\n * tips: 可以将其设置为 `()=>[]` 从而不主动执行 getter(), 可以通过调用返回的 reLoad 来调用 getter()\r\n */\r\n deps?: WatchSource<any>;\r\n /** data 的默认值 */\r\n defaultData?: T;\r\n /** 如果这个参数没有输入的话,应该自行调用 PromiseObj.setValue */\r\n getter?: () => Promise<T> | typeof continueLoading;\r\n /** 处理数据是否要和之前的数据进行合并 */\r\n dataMergeFun?: (oldData: T, newData: T) => T;\r\n}\r\n\r\nexport function usePromiseComputed<T, Err = Error>({\r\n deps,\r\n getter,\r\n dataMergeFun = (_oldData, newData) => newData,\r\n defaultData,\r\n}: usePromiseComputedOptions<T>) {\r\n const r = new PromiseObj<T, Err>();\r\n if (defaultData !== undefined) {\r\n r.data = defaultData;\r\n }\r\n return customRef<PromiseObj<T, Err>>((track, trigger) => {\r\n if (!deps && getter) {\r\n watchEffect(() => update(getter()));\r\n } else if (deps && getter) {\r\n if (deps instanceof Function) {\r\n const depsSource = deps();\r\n if (Array.isArray(depsSource) && depsSource.length === 0) {\r\n // 特性,传递空数组则先不执行 getter ,由用户自己决定时机执行 reload\r\n } else {\r\n watch(deps, () => update(getter()), { immediate: true });\r\n }\r\n } else {\r\n watch(deps, () => update(getter()), { immediate: true });\r\n }\r\n }\r\n function update(p: Promise<T> | typeof continueLoading) {\r\n r.pending = true;\r\n r.fulfilled = false;\r\n r.rejected = false;\r\n /** 返回值为继续加载则,getter函数中有特殊的判断逻辑,依据当前的 deps 还无法得出值,需要继续 loading */\r\n if (p === continueLoading) {\r\n nextTick(trigger);\r\n return;\r\n }\r\n r.setP(p);\r\n // 立即触发会导致死循环,所以包裹一层\r\n nextTick(trigger);\r\n p.then((res) => {\r\n // 避免 「求值fun」 第一次执行产生的 promise 比 第二次产生的后结束 导致 数据错误的采用了第一次的\r\n if (r.equalP(p)) {\r\n r.pending = false;\r\n r.fulfilled = true;\r\n r.data = dataMergeFun(r.data, res);\r\n }\r\n })\r\n .catch((e) => {\r\n if (r.equalP(p)) {\r\n r.pending = false;\r\n r.rejected = true;\r\n r.error = e;\r\n }\r\n })\r\n .finally(() => {\r\n if (r.equalP(p)) {\r\n trigger();\r\n }\r\n });\r\n }\r\n r.reLoad = () => {\r\n if (getter) update(getter());\r\n // 否则是用户通过 setValue 设定的值,是无法reLoad的\r\n };\r\n r.setValue = (data) => {\r\n r.pending = false;\r\n r.fulfilled = true;\r\n r.data = dataMergeFun(r.data, data);\r\n trigger();\r\n };\r\n return {\r\n get() {\r\n track();\r\n return r;\r\n },\r\n set(_newValue) {\r\n console.warn(\"不可设置值\");\r\n },\r\n };\r\n });\r\n}\r\n\r\nexport namespace usePromiseComputed {\r\n /** 辅助方法,返回一个deps为 `()=>{}` 的 PromiseObj */\r\n export function nullDeps<T>(getter: usePromiseComputedOptions<T>[\"getter\"]) {\r\n return usePromiseComputed({\r\n deps: () => [],\r\n getter,\r\n });\r\n }\r\n export function fn<T>(fn: () => Promise<T> | typeof continueLoading) {\r\n const p = usePromiseComputed({\r\n getter() {\r\n return fn();\r\n },\r\n });\r\n return p;\r\n }\r\n}\r\n\r\n/** 防抖的 ref */\r\nexport function useDebouncedRef<T>(value: T, delay = 200) {\r\n let timeout = 0;\r\n return customRef<T>((track, trigger) => {\r\n return {\r\n get() {\r\n track();\r\n return value;\r\n },\r\n set(newValue) {\r\n clearTimeout(timeout);\r\n timeout = setTimeout(() => {\r\n value = newValue;\r\n trigger();\r\n }, delay) as unknown as number;\r\n },\r\n };\r\n });\r\n}\r\n","import { Ref } from 'vue'\r\nimport {\r\n PromiseObj,\r\n usePromiseComputed,\r\n} from '../components/data_promise/index.ts'\r\nimport { NodeDocument, S_Node, file, notebook } from './siyuan_type.ts'\r\nimport { currentConfig } from '~/core/config.ts'\r\n\r\n/** https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md */\r\nexport interface api {\r\n /**\r\n * 列出笔记本\r\n */\r\n notebook_lsNotebooks(): {\r\n notebooks: notebook[]\r\n }\r\n block_getBlockInfo(p: { id: string }): {\r\n box: '20210816161940-zo21go1'\r\n path: '/20201104153359-sk9a3yg.sy'\r\n rootChildID: '20201104153359-sk9a3yg'\r\n rootID: '20201104153359-sk9a3yg'\r\n rootIcon: ''\r\n rootTitle: 'markdown'\r\n }\r\n filetree_listDocsByPath(p: { notebook: notebook['id']; path: '/' }): {\r\n box: '20210816161940-zo21go1'\r\n files: file[]\r\n path: '/'\r\n }\r\n filetree_getHPathByID(p: { id: file['id'] }): '/foo/bar'\r\n filetree_getDoc(p: {\r\n id: file['id']\r\n isBacklink: false\r\n mode: 0\r\n size: 48\r\n }): NodeDocument\r\n export_exportHTML(p: {\r\n id: file['id']\r\n pdf: false\r\n /** 为空时思源不会写文件 https://github.com/siyuan-note/siyuan/blob/master/kernel/model/export.go :ExportHTML */\r\n savePath: ''\r\n }): {\r\n content: '<html>'\r\n id: '20200825162036-4dx365o'\r\n name: '排版元素'\r\n }\r\n /** 执行 SQL 查询 https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#执行-sql-查询 */\r\n query_sql(p: {\r\n /** SELECT * FROM blocks WHERE content LIKE'%content%' LIMIT 7 */ stmt: string\r\n }): any[]\r\n /** 获取文件 https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#获取文件\r\n */\r\n file_getFile(p: { path: string }): S_Node | ArrayBuffer\r\n get_assets(p: { path: string }): ArrayBuffer\r\n /** 根据人类可读路径获取 IDs https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#根据人类可读路径获取-ids */\r\n filetree_getIDsByHPath(p: {\r\n /** /foo/bar */\r\n path: string\r\n /** 20210808180117-czj9bvb */\r\n notebook: string\r\n }): string[]\r\n}\r\ntype apiPromisify = {\r\n readonly [K in keyof api]: (\r\n ...arg: Parameters<api[K]>\r\n ) => Promise<unPromise<ReturnType<api[K]>>>\r\n}\r\n\r\n/** 解开 promise 类型包装 */\r\ndeclare type unPromise<T> = T extends Promise<infer R> ? R : T\r\nlet rpcCount = 0\r\nasync function rpc(method: string, arg: any) {\r\n const apiPrefix = currentConfig.value.apiPrefix\r\n const Authorization = currentConfig.value.authorized\r\n rpcCount++\r\n\r\n if (method === 'get_assets') {\r\n return fetch(`${apiPrefix}/${arg[0].path}`, {\r\n headers: {\r\n Authorization: `Token ${Authorization}`,\r\n },\r\n body: null,\r\n method: 'GET',\r\n mode: 'cors',\r\n }).then((r) => r.arrayBuffer())\r\n }\r\n const res = await fetch(`${apiPrefix}/api/${method.replace(/_/g, '/')}`, {\r\n headers: {\r\n Authorization: `Token ${Authorization}`,\r\n },\r\n body: JSON.stringify(arg[0]),\r\n method: 'POST',\r\n }).catch((err: Error) => {\r\n err.message = `访问思源接口时出错了,请检查思源服务是否启动以及配置接口地址是否正确。`\r\n throw err\r\n })\r\n if (method === 'file_getFile') {\r\n const path = arg[0].path as string\r\n if (path.endsWith('.sy')) {\r\n return await res.json()\r\n } else {\r\n const buffer = await res.arrayBuffer()\r\n if (buffer.byteLength < 200) {\r\n const decoder = new TextDecoder()\r\n const text = decoder.decode(buffer)\r\n if (JSON.parse(text).code === 404) {\r\n throw new Error(`文件不存在: ${path}`)\r\n }\r\n }\r\n return buffer\r\n }\r\n }\r\n const json = await res.json()\r\n\r\n if (json.code !== 0) {\r\n throw new Error(json.msg)\r\n }\r\n return json.data\r\n}\r\n\r\n/** 包装了一次的 RC 方便跳转到函数定义 */\r\nexport const API = new Proxy(\r\n {},\r\n {\r\n get(_, method: string) {\r\n return (...arg: any) => rpc(method, arg)\r\n },\r\n },\r\n) as apiPromisify\r\n\r\ntype vApi = {\r\n readonly [K in keyof api]: (\r\n ...arg: Parameters<api[K]>\r\n ) => Ref<PromiseObj<unPromise<ReturnType<api[K]>>, Error>>\r\n}\r\n/** 使用 usePromiseComputed 包装的方法,便于使用 */\r\nexport const vApi = new Proxy(\r\n {},\r\n {\r\n get(_, method: string) {\r\n return (...arg: any) => usePromiseComputed.fn(() => rpc(method, arg))\r\n },\r\n },\r\n) as vApi\r\n","import { escaping, unescaping } from '~/util/escaping.ts'\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, S_Node, NodeType } from './siyuan_type.ts'\r\nimport { storeDep } from '~/core/dependency.ts'\r\n\r\nexport type RenderHTML = typeof renderHTML\r\nexport type Render = typeof render\r\n\r\nexport async function renderHTML(\r\n sy: S_Node | undefined,\r\n /**\r\n * renderHTML 内部会创建一个 renderInstance 的浅克隆\r\n * 用来维护 renderHTML.nodeStack 的正常运转\r\n */\r\n renderInstance: Render = getRender(),\r\n): Promise<string> {\r\n if (sy === undefined) return ''\r\n const renderObj: Render = {\r\n ...renderInstance,\r\n nodeStack: [\r\n /** 避免让所有的 renderInstance.nodeStack 是同一个对象 ,所以这里复制一个新的 */ ...renderInstance.nodeStack,\r\n ],\r\n }\r\n if (\r\n renderInstance.nodeStack.find(\r\n (node) => node.ID && sy.ID && node.ID === sy.ID,\r\n )\r\n ) {\r\n return warnDiv(\r\n '循环引用',\r\n [...renderInstance.nodeStack, sy].map((el) => el.ID),\r\n )\r\n }\r\n if (renderObj[sy.Type] === undefined) {\r\n return warnDiv(\r\n `没有找到对应的渲染方法 ${sy.Type} ${renderObj.nodeStack[0].Properties?.title}`,\r\n )\r\n } else {\r\n /** 入栈 */\r\n renderObj.nodeStack.push(sy)\r\n /** 维护引用关系 */\r\n if (sy.ID && renderInstance.nodeStack[0]?.ID) {\r\n const targetDoc = await storeDep.getDocByChildID(sy.ID)\r\n const currentDoc = renderInstance.nodeStack[0]\r\n if (\r\n targetDoc?.ID !== undefined &&\r\n targetDoc.ID !== currentDoc.ID &&\r\n currentDoc.ID\r\n ) {\r\n /** 代表这个节点不在当前文档中,却在编译currentDoc时出现了,所以 currentDoc依赖(正向引用)targetDoc */\r\n // 记录引用 TODO 不应该在 render中之直接记录,该上报\r\n renderObj.refs.add(targetDoc.ID)\r\n }\r\n }\r\n const r = await renderObj[sy.Type]!(sy)\r\n /** 出栈 */\r\n renderObj.nodeStack.pop()\r\n return r\r\n }\r\n}\r\nfunction warnDiv(msg: string, ...args: any[]) {\r\n warn(msg, ...args)\r\n return `<div class=\"ft__smaller ft__secondary b3-form__space--small\">${msg}</div>`\r\n}\r\nfunction isRenderCode(sy: S_Node) {\r\n const mark = atob(\r\n sy.CodeBlockInfo ??\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockFenceInfoMarker')\r\n ?.CodeBlockInfo ??\r\n '',\r\n )\r\n return [\r\n [\r\n 'mindmap',\r\n 'mermaid',\r\n 'echarts',\r\n 'abc',\r\n 'graphviz',\r\n 'flowchart',\r\n 'plantuml',\r\n ].includes(mark),\r\n mark,\r\n ] as const\r\n}\r\nconst html = String.raw\r\nasync function childRender(sy: S_Node, renderInstance: typeof render) {\r\n let h = ''\r\n for await (const el of sy?.Children ?? []) {\r\n h += await renderHTML(el, renderInstance)\r\n }\r\n return h\r\n}\r\nfunction strAttr(\r\n sy: S_Node,\r\n config: {\r\n subtype_class?: string | [string, string]\r\n data_type?: string\r\n } = {},\r\n) {\r\n if (config?.subtype_class === undefined) {\r\n config.subtype_class = (() => {\r\n const typ_subtype =\r\n sy.ListData?.Typ === 1\r\n ? /** 有序列表 */ 'o'\r\n : sy.ListData?.Typ === 3\r\n ? /** 任务列表 */ 't'\r\n : /** 无序列表 */ 'u'\r\n\r\n if (sy.Type === 'NodeDocument') return 'h1'\r\n else if (sy.Type === 'NodeHeading') return `h${sy.HeadingLevel}`\r\n else if (sy.Type === 'NodeList') return [typ_subtype, 'list']\r\n else if (sy.Type === 'NodeListItem') return [typ_subtype, 'li']\r\n else if (sy.Type === 'NodeParagraph') return ['', 'p']\r\n else if (sy.Type === 'NodeImage') return ['', 'img']\r\n else if (sy.Type === 'NodeBlockquote') return ['', 'bq']\r\n else if (sy.Type === 'NodeSuperBlock') return ['', 'sb']\r\n else if (sy.Type === 'NodeCodeBlock') {\r\n const [yes, mark] = isRenderCode(sy)\r\n if (yes) {\r\n /** 脑图等需要渲染的块 */\r\n return [mark, 'render-node']\r\n } else {\r\n return ['', 'code-block']\r\n }\r\n } else if (sy.Type === 'NodeTable') return ['', 'table']\r\n else if (sy.Type === 'NodeThematicBreak') return ['', 'hr']\r\n else if (sy.Type === 'NodeMathBlock') return ['math', 'render-node']\r\n else if (sy.Type === 'NodeIFrame') return ['', 'iframe']\r\n else if (sy.Type === 'NodeVideo') return ['', 'iframe']\r\n else return ''\r\n })()\r\n }\r\n const attrObj = {} as { [k: string]: string }\r\n function addAttr(key: string, value: string) {\r\n attrObj[key] = value\r\n }\r\n if (sy.ID) {\r\n addAttr('id', sy.ID)\r\n addAttr('data-node-id', sy.ID)\r\n }\r\n\r\n if (sy?.TextMarkType === 'tag') {\r\n addAttr(`data-type`, sy.TextMarkType ?? '')\r\n } else {\r\n addAttr(`data-type`, config?.data_type ?? sy.Type)\r\n }\r\n if (sy.Properties?.updated) addAttr('updated', sy.Properties.updated)\r\n if (config?.subtype_class) {\r\n if (typeof config.subtype_class === 'string') {\r\n addAttr('data-subtype', config.subtype_class)\r\n addAttr('class', config.subtype_class)\r\n } else {\r\n if (config.subtype_class[0] !== '')\r\n addAttr('data-subtype', config.subtype_class[0])\r\n if (config.subtype_class[1] !== '')\r\n addAttr('class', config.subtype_class[1])\r\n }\r\n }\r\n if (sy.Properties) {\r\n Object.entries(sy.Properties).forEach(([k, v]) => addAttr(k, v))\r\n }\r\n if (sy.ListData?.Marker) addAttr('data-marker', atob(sy.ListData.Marker))\r\n if (\r\n /** 任务列表 */ sy.ListData?.Typ === 3 &&\r\n /** 该项被选中 */ sy.Children?.find(\r\n (el) => el.Type === 'NodeTaskListItemMarker',\r\n )?.TaskListItemChecked\r\n ) {\r\n attrObj['class'] = (attrObj['class'] ?? '') + ' protyle-task--done '\r\n }\r\n /** 不折叠任何项目 */ delete attrObj['fold']\r\n /** 避免任意元素上悬停都显示文档标题 */\r\n if (sy.Type === 'NodeDocument') delete attrObj['title']\r\n return Object.entries(attrObj)\r\n .map(([k, v]) => `${k}=\"${v}\"`)\r\n .join(' ')\r\n}\r\n/** 返回空字符串,一般用于不用解析的节点 */\r\nconst _emptyString = async (_sy: S_Node) => ''\r\nconst _dataString = async (sy: S_Node) => sy.Data ?? ''\r\n\r\n/** 对一些数据常量进行处理 */\r\nexport const getRender = () => {\r\n return {\r\n ...render,\r\n nodeStack: [],\r\n refs: new Set(),\r\n } as Render\r\n}\r\nconst render: {\r\n [key in keyof typeof NodeType]?: (sy: S_Node) => Promise<string>\r\n} & {\r\n /**\r\n * 用于保存调用栈,即从根节点到当前节点。\r\n * 例如在渲染 文档A中引用了文档B中的节点 时调用栈如下\r\n * ```\r\n * nodeStack ~= [A_NodeDocument,A_NodeList,...,A_block-ref,B_Node]\r\n * ```\r\n * 对render中的函数意味着 `this.nodeStack[0]===需要生成的文档`\r\n * 这样就方便解决 block-ref 等链接问题\r\n * */\r\n nodeStack: S_Node[]\r\n /** 当前实例所引用的其他文档id,在渲染中计算 */\r\n refs: Set<string>\r\n /** 返回当前文档到顶层文档的路径前缀,例如: ./../.. */\r\n getTopPathPrefix: (sy_doc?: S_Node) => Promise<string>\r\n} = {\r\n nodeStack: [] as S_Node[],\r\n refs: new Set(),\r\n async getTopPathPrefix() {\r\n const sy = this.nodeStack[0]\r\n let prefix = '.'\r\n if (sy.Type === 'NodeDocument' && sy.ID) {\r\n /** 基于当前文档路径将 href ../ 到顶层 */\r\n const path = await storeDep.getDocPathBySY(sy)\r\n if (path) {\r\n /** path data/box_id/doc_id/doc_id/doc_id.sy `data/box_id/` 这一节是多出来的,所以要减3 */\r\n const level = path.split('/').length - 3\r\n for (let i = 0; i < level; i++) {\r\n prefix += '/..'\r\n }\r\n }\r\n return prefix\r\n } else {\r\n console.log('未定义顶层元素非 NodeDocument 时的处理方式', sy)\r\n return ''\r\n }\r\n },\r\n async NodeDocument(sy) {\r\n let html = ''\r\n if (/** 只有顶层的文档块才渲染题图 */ this.nodeStack.length === 1) {\r\n html += `<div style=\"min-height: 150px;\" ${strAttr(sy)}>`\r\n if (sy.Properties?.['title-img']) {\r\n html += `<div class=\"protyle-background__img\" style=\"margin-bottom: 30px;position: relative;height: 16vh;${sy.Properties?.[\r\n 'title-img'\r\n ].replace(\r\n /assets/,\r\n // 修改为相对路径\r\n (await this.getTopPathPrefix()) + '/assets',\r\n )}\"/>${\r\n sy.Properties?.['icon']\r\n ? `<div style=\"position: absolute;bottom:-10px;left:15px;height: 80px;width: 80px;transition: var(--b3-transition);cursor: pointer;font-size: 68px;line-height: 80px;text-align: center;font-family: var(--b3-font-family-emoji);margin-right: 16px;\"> &#x${sy.Properties?.['icon']} </div>`\r\n : ''\r\n }</div>`\r\n }\r\n html += '</div>'\r\n /** h1 文档标题 */\r\n html += `<h1 ${strAttr(sy)} data-type=\"NodeHeading\" class=\"h1\">${\r\n sy.Properties?.title\r\n }</h1>`\r\n }\r\n html += await childRender(sy, this)\r\n return html\r\n },\r\n async NodeHeading(sy) {\r\n const tagName = `h${sy.HeadingLevel}`\r\n let html = `<${tagName} ${strAttr(sy)}>${await childRender(\r\n sy,\r\n this,\r\n )}</${tagName}>`\r\n\r\n // 在被嵌入查询块的情况下需要查询渲染其后面的非标题块\r\n const parentNode =\r\n this.nodeStack[\r\n this.nodeStack.length -\r\n 2 /** 最后一个元素是 sy本身(NodeHeading)还得要往前一个,所以是2 */\r\n ]\r\n\r\n if (parentNode?.Type === 'NodeBlockQueryEmbedScript') {\r\n let afterFlag = false\r\n for (const node of sy.Parent.Children ?? []) {\r\n if (node === sy) {\r\n afterFlag = true\r\n } else if (node !== sy && node.Type === 'NodeHeading') {\r\n afterFlag = false\r\n } else if (afterFlag) {\r\n html += '\\n' + (await renderHTML(node, this))\r\n }\r\n }\r\n }\r\n return html\r\n },\r\n NodeText: _dataString,\r\n async NodeList(sy) {\r\n return html`<div ${strAttr(sy)}>${await childRender(sy, this)}</div>`\r\n },\r\n async NodeListItem(sy) {\r\n return html`<div ${await strAttr(sy)}>\r\n <div class=\"protyle-action\">\r\n ${\r\n sy.ListData?.Typ === 1\r\n ? /** 有序列表 */ atob(sy.ListData?.Marker ?? '')\r\n : sy.ListData?.Typ === 3\r\n ? /** 任务列表 */ `<svg><use xlink:href=\"#${\r\n sy.Children?.find((el) => el.Type === 'NodeTaskListItemMarker')\r\n ?.TaskListItemChecked\r\n ? 'iconCheck'\r\n : 'iconUncheck'\r\n }\"></use></svg>`\r\n : /** 无序列表 */ `<svg><use xlink:href=\"#iconDot\"></use></svg>`\r\n }\r\n </div>\r\n ${await childRender(sy, this)}\r\n </div>`\r\n },\r\n NodeTaskListItemMarker: _emptyString,\r\n\r\n async NodeParagraph(sy) {\r\n /** .protyle-wysiwyg [data-node-id] [spellcheck] 定义了换行样式 */\r\n return `<div ${strAttr(sy)}><div spellcheck=\"false\">${await childRender(\r\n sy,\r\n this,\r\n )}</div></div>`\r\n },\r\n async NodeTextMark(sy) {\r\n const that = this\r\n let r: string = ''\r\n /** 从后向前渲染每一层mark ,TextMarkType有可能是 `a sub` |`sub a` | `a` |`code`等 */\r\n for (const type of (\r\n sy.TextMarkType?.split(' ') ?? []\r\n ).reverse() as S_Node['TextMarkType'][]) {\r\n if (r === '') {\r\n r = await TextMarkRender(sy, type, sy.TextMarkTextContent ?? '')\r\n } else {\r\n r = await TextMarkRender(sy, type, r)\r\n }\r\n }\r\n return r\r\n async function TextMarkRender(\r\n sy: S_Node,\r\n type: S_Node['TextMarkType'],\r\n content: string,\r\n ): Promise<string> {\r\n if (type === 'inline-math') {\r\n return `<span data-type=\"inline-math\" data-subtype=\"math\" data-content=\"${sy.TextMarkInlineMathContent}\" class=\"render-node\"></span>`\r\n } else if (type === 'inline-memo' /** 备注 */) {\r\n return `${content}<sup>(${sy.TextMarkInlineMemoContent})</sup>`\r\n } else if (type === 'block-ref' /** 引用块 */) {\r\n let href = ''\r\n if (sy.TextMarkBlockRefID) {\r\n const doc = await storeDep.getDocByChildID(sy.TextMarkBlockRefID)\r\n if (doc?.ID) {\r\n href = `${await that.getTopPathPrefix()}${await storeDep.getHPathByID_Node(\r\n doc /** 要先定位到文档,再通过下面的hash(#)定位到具体元素 */,\r\n )}.html#${sy.TextMarkBlockRefID}`\r\n that.refs.add(doc.ID)\r\n } else {\r\n warn(`未查找到${sy.ID}所指向的文档节点 ${sy.TextMarkBlockRefID}`)\r\n }\r\n } else {\r\n warn(`${sy.ID} 块引用没有设定 ref id`)\r\n }\r\n\r\n return `<span data-type=\"${sy.TextMarkType}\" \\\r\ndata-subtype=\"${/** \"s\" */ sy.TextMarkBlockRefSubtype}\" \\\r\ndata-id=\"${\r\n /** 被引用块的id */ sy.TextMarkBlockRefID\r\n }\"><a href=\"${href}\">${content}</a></span>`\r\n } else if (type === 'a') {\r\n let href = sy.TextMarkAHref\r\n if (href?.startsWith('assets/')) {\r\n /** TODO 应该有一个统一处理资源的方案 */\r\n href = `${await that.getTopPathPrefix()}/${href}`\r\n }\r\n return `<a href=\"${href}\">${content}</a>`\r\n } else if (\r\n `strong em u s mark sup sub kbd tag code strong code text`.includes(\r\n type ?? '',\r\n )\r\n ) {\r\n return `<span ${strAttr(sy, { data_type: type })}>${content}</span>`\r\n } else {\r\n return warnDiv(\r\n `没有找到对应的渲染器 ${sy.TextMarkType} ${that.nodeStack[0].Properties?.title}`,\r\n )\r\n }\r\n }\r\n },\r\n async NodeImage(sy) {\r\n let link = ''\r\n const LinkDest = sy.Children?.filter((c) => c.Type === 'NodeLinkDest')\r\n if (LinkDest?.length === 1) {\r\n link = await renderHTML(LinkDest[0], this)\r\n } else if (LinkDest?.length && LinkDest.length > 1) {\r\n warn('NodeImage 存在多个 LinkDest', sy)\r\n }\r\n\r\n let title = ''\r\n const LinkTitle = sy.Children?.filter((c) => c.Type === 'NodeLinkTitle')\r\n if (LinkTitle?.length === 1) {\r\n title = await renderHTML(LinkTitle[0], this)\r\n } else if (LinkTitle?.length && LinkTitle.length > 1) {\r\n warn('NodeImage 存在多个 LinkTitle', sy)\r\n }\r\n return `<span ${await strAttr(sy)} style=\"${\r\n sy.Properties?.['parent-style'] ?? ''\r\n }\">\r\n<img\r\n src=\"${link}\"\r\n data-src=\"${link}\"\r\n title=\"${title}\"\r\n style=\"${sy.Properties?.style ?? ''}\"\r\n loading=\"lazy\"\r\n/>\r\n<span class=\"protyle-action__title\">${title}</span></span>`\r\n },\r\n async NodeLinkDest(sy) {\r\n /** 绝对路径 */\r\n if (/^(?:[a-z]+:)?\\/\\/|^(?:\\/)/.test(sy.Data ?? '')) {\r\n return sy.Data ?? ''\r\n }\r\n /** 为相对路径添加正确的前缀 */\r\n return `${await this.getTopPathPrefix()}/${sy.Data}`\r\n },\r\n NodeLinkTitle: _dataString,\r\n NodeKramdownSpanIAL: _emptyString,\r\n async NodeSuperBlock(sy) {\r\n return `<div ${strAttr(sy)} data-sb-layout=\"${childDateByType(\r\n sy,\r\n 'NodeSuperBlockLayoutMarker',\r\n )}\">${await childRender(sy, this)}</div>`\r\n },\r\n NodeSuperBlockOpenMarker: _emptyString,\r\n NodeSuperBlockCloseMarker: _emptyString,\r\n NodeSuperBlockLayoutMarker: _emptyString,\r\n async NodeBlockQueryEmbed(sy) {\r\n return `<div ${strAttr(sy)} data-type=\"NodeBlockquote\" class=\"bq\">\\\r\n${await childRender(sy, this)}\\\r\n</div>`\r\n },\r\n NodeOpenBrace: _emptyString,\r\n NodeCloseBrace: _emptyString,\r\n async NodeBlockQueryEmbedScript(sy) {\r\n const sql = sy.Data\r\n if (!sql) {\r\n console.log('no sql', sy)\r\n return html`<pre>${sql}</pre>`\r\n }\r\n let htmlStr = ''\r\n const blocks: DB_block[] = await API.query_sql({\r\n stmt: /** sql 被思源转义了,类似 :SELECT * FROM blocks WHERE id = '20201227174241-nxny1tq'\r\n 所以这里将它转义回来\r\n TODO 当用户确实使用了包含转义的字符串时,这个实现是错误的 */ unescaping(\r\n sql,\r\n ).replace(\r\n /** 我不理解lute为什么这样实现 https://github.com/88250/lute/blob/HEAD/editor/const.go#L38\r\n * https://ld246.com/article/1696750832289\r\n */\r\n /_esc_newline_/g,\r\n '\\n',\r\n ),\r\n }).catch((err) => {\r\n throw new Error(\r\n `sql error: ${err.message}\\nrawSql:${sql}\\nunescapingSql:${unescaping(\r\n sql,\r\n )}`,\r\n )\r\n })\r\n for (const block of blocks) {\r\n const node = await storeDep.getNodeByID(block.id)\r\n if (node === undefined) {\r\n return warnDiv('未找到此块,可能为跨笔记引用', block.id, sql)\r\n }\r\n htmlStr += await renderHTML(node, this)\r\n }\r\n\r\n return htmlStr\r\n },\r\n async NodeBlockquote(sy) {\r\n return html`<div ${strAttr(sy)}>${await childRender(sy, this)}</div>`\r\n },\r\n NodeBlockquoteMarker: _emptyString,\r\n NodeCodeBlock: async (sy) => {\r\n const [yes, _] = isRenderCode(sy)\r\n if (yes) {\r\n return `<div ${strAttr(sy)} data-content=\"${escaping(\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockCode')?.Data ?? '',\r\n )}\">\r\n <div spin=\"1\"></div>\r\n <div class=\"protyle-attr\" contenteditable=\"false\"></div>\r\n </div>`\r\n }\r\n return `<div ${strAttr(sy)}>\r\n <div class=\"protyle-action\">\r\n <span class=\"protyle-action--first protyle-action__language\">${await renderHTML(\r\n sy.Children?.find(\r\n (el) => el.Type === 'NodeCodeBlockFenceInfoMarker',\r\n ),\r\n this,\r\n )}</span>\r\n <span class=\"fn__flex-1\"></span><span class=\"protyle-icon protyle-icon--only protyle-action__copy\"><svg><use xlink:href=\"#iconCopy\"></use></svg></span>\r\n </div>\r\n ${await renderHTML(\r\n sy.Children?.find((el) => el.Type === 'NodeCodeBlockCode'),\r\n this,\r\n )}\r\n </div>`\r\n },\r\n NodeCodeBlockFenceInfoMarker: async (sy) => atob(sy.CodeBlockInfo ?? ''),\r\n NodeCodeBlockCode: async (sy) =>\r\n `<div class=\"hljs\" spellcheck=\"false\">${sy.Data}</div>`,\r\n NodeCodeBlockFenceOpenMarker: _emptyString,\r\n NodeCodeBlockFenceCloseMarker: _emptyString,\r\n async NodeTable(sy) {\r\n return `<div ${strAttr(sy)}>\r\n <div>\r\n <table spellcheck=\"false\">\r\n <colgroup>\r\n ${sy.TableAligns?.map(() => '<col />').join('')}\r\n </colgroup>\r\n ${await renderHTML(\r\n sy.Children?.find((el) => el.Type === 'NodeTableHead'),\r\n this,\r\n )}\r\n <tbody>\r\n ${(\r\n await Promise.all(\r\n sy.Children?.filter((el) => el.Type === 'NodeTableRow').map((el) =>\r\n renderHTML(el, this),\r\n ) ?? [],\r\n )\r\n ).join('\\n')}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>`\r\n },\r\n async NodeTableHead(sy) {\r\n return `<${sy.Data}>${await childRender(sy, this)}</${sy.Data}>`\r\n },\r\n async NodeTableRow(sy) {\r\n return `<tr>${await childRender(sy, this)}</tr>`\r\n },\r\n async NodeTableCell(sy) {\r\n return `<td>${await childRender(sy, this)}</td>`\r\n },\r\n NodeHTMLBlock: async (sy) => `<div ${strAttr(sy)}>${sy.Data}</div>`,\r\n NodeThematicBreak: async (sy) => `<div ${strAttr(sy)}><div></div></div>`,\r\n NodeMathBlock: async (sy) => `<div ${strAttr(\r\n sy,\r\n )} data-content=\"${childDateByType(sy, 'NodeMathBlockContent')}\">\r\n <div spin=\"1\"></div>\r\n </div>`,\r\n NodeMathBlockOpenMarker: _emptyString,\r\n NodeMathBlockCloseMarker: _emptyString,\r\n async NodeIFrame(sy) {\r\n return ` <div ${strAttr(sy)}>\r\n <div class=\"iframe-content\">\r\n ${\r\n /** 资源总是被复制到顶层目录,所以直接跳到顶层即可 */\r\n /** TODO 应该有一个统一处理资源的方案 */\r\n sy.Data?.replace(\r\n /src=\"assets\\//,\r\n `src=\"${await this.getTopPathPrefix()}/assets\\/`,\r\n )\r\n }\r\n </div>\r\n </div>`\r\n },\r\n async NodeVideo(sy) {\r\n return await this.NodeIFrame!(sy)\r\n },\r\n async NodeAudio(sy) {\r\n return await this.NodeIFrame!(sy)\r\n },\r\n /** 虚拟链接 */\r\n NodeHeadingC8hMarker: _emptyString,\r\n async NodeSoftBreak(_sy) {\r\n //TODO 此处实现应该有问题\r\n /** https://zh.wikipedia.org/wiki/零宽空格 */\r\n return '\\u200B'\r\n },\r\n async NodeBr(sy) {\r\n return `<${sy.Data}>`\r\n },\r\n async NodeWidget(sy) {\r\n return `<div ${strAttr(\r\n sy,\r\n )}><img src=\"${await this.getTopPathPrefix()}/assets/widget/${\r\n sy.ID\r\n }.jpg\"/></div>`\r\n },\r\n async NodeBackslash(sy) {\r\n if (sy.Data === undefined || sy.Data === 'span') {\r\n return `${await childRender(sy, this)}`\r\n } else {\r\n return warnDiv(\r\n `未定义的 NodeBackslash 处理 ${sy.Data}`,\r\n this.nodeStack[0].Properties?.title,\r\n )\r\n }\r\n },\r\n NodeBackslashContent: _dataString,\r\n}\r\n\r\n/** 获取sy节点的child中第一个type类型节点的data */\r\nfunction childDateByType(sy: S_Node, type: S_Node['Type']) {\r\n return sy.Children?.find((el) => el.Type === type)?.Data\r\n}\r\n\r\nfunction warn(...arg: any[]) {\r\n console.warn('\\n', ...arg)\r\n}\r\n","export interface notebook {\r\n id: \"20210808180117-czj9bvb\";\r\n name: \"思源笔记用户指南\";\r\n icon: \"1f4d4\";\r\n sort: 1;\r\n closed: false;\r\n}\r\nexport interface file {\r\n /** \"/20210816161946-cktc4gf.sy\" */\r\n path: string;\r\n name: \"关于.sy\";\r\n icon: \"\";\r\n name1: \"\";\r\n alias: \"\";\r\n memo: \"\";\r\n bookmark: \"\";\r\n /** \"20210816161946-cktc4gf\" */\r\n id: string;\r\n count: 0;\r\n size: 362;\r\n hSize: \"362 B\";\r\n mtime: 1629101986;\r\n ctime: 1629101986;\r\n hMtime: \"2 年以前\";\r\n hCtime: \"2021-08-16 16:19:46\";\r\n sort: 0;\r\n subFileCount: 9;\r\n newFlashcardCount: 0;\r\n dueFlashcardCount: 0;\r\n flashcardCount: 0;\r\n}\r\nexport interface NodeDocument {\r\n blockCount: 2;\r\n box: \"20210808180117-czj9bvb\";\r\n content: \"<html>\";\r\n eof: false;\r\n id: \"20230519105228-hm0y74i\";\r\n isBacklinkExpand: false;\r\n isSyncing: false;\r\n mode: 0;\r\n parent2ID: \"20230519105228-hm0y74i\";\r\n parentID: \"20230519105228-hm0y74i\";\r\n path: \"/20230519105228-hm0y74i.sy\";\r\n rootID: \"20230519105228-hm0y74i\";\r\n scroll: false;\r\n type: \"NodeDocument\";\r\n}\r\n\r\nexport function DB_block_path(p: DB_block) {\r\n return `data/${p.box}${p.path}`;\r\n}\r\nexport interface DB_block {\r\n alias: \"\";\r\n box: \"20210816161940-3mfvumm\";\r\n content: \"自述\";\r\n created: \"20201125202944\";\r\n fcontent: \"自述\";\r\n hash: \"922ee83\";\r\n hpath: \"/计算机基础课/自述\";\r\n ial: '{: id=\"20201125202944-01mdxqn\" title=\"自述\" type=\"doc\" updated=\"20201125202944\"}';\r\n id: \"20201125202944-01mdxqn\";\r\n length: 2;\r\n markdown: \"\";\r\n memo: \"\";\r\n name: \"\";\r\n parent_id: \"\";\r\n path: \"/20210816161944-io0cgn6/20201125202944-01mdxqn.sy\";\r\n root_id: \"20201125202944-01mdxqn\";\r\n sort: 0;\r\n subtype: \"\";\r\n tag: \"\";\r\n type: \"d\";\r\n updated: \"20201125202944\";\r\n}\r\nexport interface S_Node {\r\n ID?: string; // 节点的唯一标识\r\n Box?: string; // 容器\r\n Path?: string; // 路径\r\n Spec?: string; // 规范版本号\r\n Type: NodeType; // 节点类型\r\n Parent: S_Node; // 父节点 在 node.ts 中被重建了,所以这个引用关系是可用的\r\n Previous?: S_Node; // 前一个兄弟节点\r\n Next?: S_Node; // 后一个兄弟节点\r\n FirstChild?: S_Node; // 第一个子节点\r\n LastChild?: S_Node; // 最后一个子节点\r\n Children?: S_Node[]; // 所有子节点\r\n Tokens?: number[]; // 词法分析结果 Tokens,语法分析阶段会继续操作这些 Tokens\r\n TypeStr: string; // 类型字符串\r\n Data?: string; // Tokens 字符串\r\n Close?: boolean; // 标识是否关闭\r\n LastLineBlank?: boolean; // 标识最后一行是否是空行\r\n LastLineChecked?: boolean; // 标识最后一行是否检查过\r\n CodeMarkerLen?: number; // ` 个数,1 或 2\r\n IsFencedCodeBlock?: boolean;\r\n CodeBlockFenceChar?: number;\r\n CodeBlockFenceLen?: number;\r\n CodeBlockFenceOffset?: number;\r\n CodeBlockOpenFence?: number[];\r\n CodeBlockInfo?: string; // Z28= | atob = 'go'\r\n CodeBlockCloseFence?: number[];\r\n HtmlBlockType?: number;\r\n ListData?: ListData;\r\n TaskListItemChecked?: boolean;\r\n TableAligns?: number[];\r\n TableCellAlign?: number;\r\n TableCellContentWidth?: number;\r\n TableCellContentMaxWidth?: number;\r\n LinkType?: number;\r\n LinkRefLabel?: number[];\r\n HeadingLevel?: number;\r\n HeadingSetext?: boolean;\r\n HeadingNormalizedID?: string;\r\n MathBlockDollarOffset?: number;\r\n FootnotesRefLabel?: number[];\r\n FootnotesRefId?: string;\r\n FootnotesRefs?: Node[];\r\n HtmlEntityTokens?: number[];\r\n KramdownIAL?: string[][];\r\n Properties?: {\r\n icon: \"1f4f0\";\r\n id: \"20200825162036-4dx365o\";\r\n title: \"排版元素\";\r\n \"title-img\": \"background-color: hsl(2, 57%, 40%);background-image: repeating-linear-gradient(transparent, transparent 50px, rgba(0,0,0,.4) 50px, rgba(0,0,0,.4) 53px, transparent 53px, transparent 63px, rgba(0,0,0,.4) 63px, rgba(0,0,0,.4) 66px, transparent 66px, transparent 116px, rgba(0,0,0,.5) 116px, rgba(0,0,0,.5) 166px, rgba(255,255,255,.2) 166px, rgba(255,255,255,.2) 169px, rgba(0,0,0,.5) 169px, rgba(0,0,0,.5) 179px, rgba(255,255,255,.2) 179px, rgba(255,255,255,.2) 182px, rgba(0,0,0,.5) 182px, rgba(0,0,0,.5) 232px, transparent 232px),repeating-linear-gradient(270deg, transparent, transparent 50px, rgba(0,0,0,.4) 50px, rgba(0,0,0,.4) 53px, transparent 53px, transparent 63px, rgba(0,0,0,.4) 63px, rgba(0,0,0,.4) 66px, transparent 66px, transparent 116px, rgba(0,0,0,.5) 116px, rgba(0,0,0,.5) 166px, rgba(255,255,255,.2) 166px, rgba(255,255,255,.2) 169px, rgba(0,0,0,.5) 169px, rgba(0,0,0,.5) 179px, rgba(255,255,255,.2) 179px, rgba(255,255,255,.2) 182px, rgba(0,0,0,.5) 182px, rgba(0,0,0,.5) 232px, transparent 232px),repeating-linear-gradient(125deg, transparent, transparent 2px, rgba(0,0,0,.2) 2px, rgba(0,0,0,.2) 3px, transparent 3px, transparent 5px, rgba(0,0,0,.2) 5px);\";\r\n type: \"doc\";\r\n updated: \"20230820185054\";\r\n \"parent-style\"?: \"max-width: 137px;\";\r\n style?: \"display: block;\";\r\n };\r\n TextMarkType?: \"block-ref\" | \"a\" | \"tag\" | \"inline-math\" | \"inline-memo\";\r\n TextMarkAHref?: string;\r\n TextMarkATitle?: string;\r\n TextMarkInlineMathContent?: string;\r\n TextMarkInlineMemoContent?: string;\r\n TextMarkBlockRefID?: string;\r\n TextMarkBlockRefSubtype?: string;\r\n TextMarkFileAnnotationRefID?: string;\r\n TextMarkTextContent?: string;\r\n AttributeViewID?: string;\r\n AttributeViewType?: string;\r\n CustomBlockFenceOffset?: number;\r\n CustomBlockInfo?: string;\r\n}\r\ntype NodeType = ValueKeys<typeof NodeType>;\r\ntype ValueKeys<T> = keyof { [K in keyof T]: T[K] extends string ? K : never };\r\ninterface ListData {\r\n Typ?: number; // 0:无序列表,1:有序列表,3:任务列表\r\n Tight?: boolean; // 是否是紧凑模式\r\n BulletChar?: number; // 无序列表标识,* - 或者 +\r\n Start?: number; // 有序列表起始序号\r\n Delimiter?: number; // 有序列表分隔符,. 或者 )\r\n Padding?: number; // 列表内部缩进空格数(包含标识符长度,即规范中的 W+N)\r\n MarkerOffset?: number; // 标识符(* - + 或者 1 2 3)相对缩进空格数\r\n Checked?: boolean; // 任务列表项是否勾选\r\n Marker?: string; // 列表标识符\r\n Num?: number; // 有序列表项修正过的序号\r\n}\r\n\r\nexport const NodeType = {\r\n NodeDocument: 0, // 根\r\n NodeParagraph: 1, // 段落\r\n NodeHeading: 2, // 标题\r\n NodeHeadingC8hMarker: 3, // ATX 标题标记符 #\r\n NodeThematicBreak: 4, // 分隔线\r\n NodeBlockquote: 5, // 块引用\r\n NodeBlockquoteMarker: 6, // 块引用标记符 >\r\n NodeList: 7, // 列表\r\n NodeListItem: 8, // 列表项\r\n NodeHTMLBlock: 9, // HTML 块\r\n NodeInlineHTML: 10, // 内联 HTML\r\n NodeCodeBlock: 11, // 代码块\r\n NodeCodeBlockFenceOpenMarker: 12, // 开始围栏代码块标记符 ```\r\n NodeCodeBlockFenceCloseMarker: 13, // 结束围栏代码块标记符 ```\r\n NodeCodeBlockFenceInfoMarker: 14, // 围栏代码块信息标记符 info string\r\n NodeCodeBlockCode: 15, // 围栏代码块代码\r\n NodeText: 16, // 文本\r\n NodeEmphasis: 17, // 强调\r\n NodeEmA6kOpenMarker: 18, // 开始强调标记符 *\r\n NodeEmA6kCloseMarker: 19, // 结束强调标记符 *\r\n NodeEmU8eOpenMarker: 20, // 开始强调标记符 _\r\n NodeEmU8eCloseMarker: 21, // 结束强调标记符 _\r\n NodeStrong: 22, // 加粗\r\n NodeStrongA6kOpenMarker: 23, // 开始加粗标记符 **\r\n NodeStrongA6kCloseMarker: 24, // 结束加粗标记符 **\r\n NodeStrongU8eOpenMarker: 25, // 开始加粗标记符 __\r\n NodeStrongU8eCloseMarker: 26, // 结束加粗标记符 __\r\n NodeCodeSpan: 27, // 代码\r\n NodeCodeSpanOpenMarker: 28, // 开始代码标记符 `\r\n NodeCodeSpanContent: 29, // 代码内容\r\n NodeCodeSpanCloseMarker: 30, // 结束代码标记符 `\r\n NodeHardBreak: 31, // 硬换行\r\n NodeSoftBreak: 32, // 软换行\r\n NodeLink: 33, // 链接\r\n NodeImage: 34, // 图片\r\n NodeBang: 35, // !\r\n NodeOpenBracket: 36, // [\r\n NodeCloseBracket: 37, // ]\r\n NodeOpenParen: 38, // (\r\n NodeCloseParen: 39, // )\r\n NodeLinkText: 40, // 链接文本\r\n NodeLinkDest: 41, // 链接地址\r\n NodeLinkTitle: 42, // 链接标题\r\n NodeLinkSpace: 43, // 链接地址和链接标题之间的空格\r\n NodeHTMLEntity: 44, // HTML 实体\r\n NodeLinkRefDefBlock: 45, // 链接引用定义块\r\n NodeLinkRefDef: 46, // 链接引用定义 [label]:\r\n NodeLess: 47, // <\r\n NodeGreater: 48, // >\r\n\r\n // GFM\r\n\r\n NodeTaskListItemMarker: 100, // 任务列表项标记符\r\n NodeStrikethrough: 101, // 删除线\r\n NodeStrikethrough1OpenMarker: 102, // 开始删除线标记符 ~\r\n NodeStrikethrough1CloseMarker: 103, // 结束删除线标记符 ~\r\n NodeStrikethrough2OpenMarker: 104, // 开始删除线标记符 ~~\r\n NodeStrikethrough2CloseMarker: 105, // 结束删除线标记符 ~~\r\n NodeTable: 106, // 表\r\n NodeTableHead: 107, // 表头\r\n NodeTableRow: 108, // 表行\r\n NodeTableCell: 109, // 表格\r\n\r\n // Emoji\r\n\r\n NodeEmoji: 200, // Emoji\r\n NodeEmojiUnicode: 201, // Emoji Unicode\r\n NodeEmojiImg: 202, // Emoji 图片\r\n NodeEmojiAlias: 203, // Emoji ASCII\r\n\r\n // 数学公式\r\n\r\n NodeMathBlock: 300, // 数学公式块\r\n NodeMathBlockOpenMarker: 301, // 开始数学公式块标记符 $$\r\n NodeMathBlockContent: 302, // 数学公式块内容\r\n NodeMathBlockCloseMarker: 303, // 结束数学公式块标记符 $$\r\n NodeInlineMath: 304, // 内联数学公式\r\n NodeInlineMathOpenMarker: 305, // 开始内联数学公式标记符 $\r\n NodeInlineMathContent: 306, // 内联数学公式内容\r\n NodeInlineMathCloseMarker: 307, // 结束内联数学公式标记符 $\r\n\r\n // 转义\r\n\r\n NodeBackslash: 400, // 转义反斜杠标记符 \\\r\n NodeBackslashContent: 401, // 转义反斜杠后的内容\r\n\r\n // Vditor 支持\r\n\r\n NodeVditorCaret: 405, // 插入符,某些情况下需要使用该节点进行插入符位置调整\r\n\r\n // 脚注\r\n\r\n NodeFootnotesDefBlock: 410, // 脚注定义块\r\n NodeFootnotesDef: 411, // 脚注定义 [^label]:\r\n NodeFootnotesRef: 412, // 脚注引用 [^label]\r\n\r\n // 目录\r\n\r\n NodeToC: 415, // 目录 [toc]\r\n\r\n // 标题\r\n\r\n NodeHeadingID: 420, // 标题 ID # foo {id}\r\n\r\n // YAML Front Matter\r\n\r\n NodeYamlFrontMatter: 425, // https://,jekyllrb.com/docs/front-matter/\r\n NodeYamlFrontMatterOpenMarker: 426, // 开始 YAML Front Matter 标记符 ---\r\n NodeYamlFrontMatterContent: 427, // YAML Front Matter 内容\r\n NodeYamlFrontMatterCloseMarker: 428, // 结束 YAML Front Matter 标记符 ---\r\n\r\n // 内容块引用(Block Reference) https://,github.com/88250/lute/issues/82\r\n\r\n NodeBlockRef: 430, // 内容块引用节点\r\n NodeBlockRefID: 431, // 被引用的内容块(定义块)ID\r\n NodeBlockRefSpace: 432, // 被引用的内容块 ID 和内容块引用锚文本之间的空格\r\n NodeBlockRefText: 433, // 内容块引用锚文本\r\n NodeBlockRefDynamicText: 434, // 内容块引用动态锚文本\r\n\r\n // ==Mark== 标记语法 https://,github.com/88250/lute/issues/84\r\n\r\n NodeMark: 450, // 标记\r\n NodeMark1OpenMarker: 451, // 开始标记标记符 =\r\n NodeMark1CloseMarker: 452, // 结束标记标记符 =\r\n NodeMark2OpenMarker: 453, // 开始标记标记符 ==\r\n NodeMark2CloseMarker: 454, // 结束标记标记符 ==\r\n\r\n // kramdown 内联属性列表 https://,github.com/88250/lute/issues/89 and https://,github.com/88250/lute/issues/118\r\n\r\n NodeKramdownBlockIAL: 455, // 块级内联属性列表 {: name,=\"value\"}\r\n NodeKramdownSpanIAL: 456, // 行级内联属性列表 *foo*{: name,=\"value\"}bar\r\n\r\n // #Tag# 标签语法 https://,github.com/88250/lute/issues/92\r\n\r\n NodeTag: 460, // 标签\r\n NodeTagOpenMarker: 461, // 开始标签标记符 #\r\n NodeTagCloseMarker: 462, // 结束标签标记符 #\r\n\r\n // 内容块查询嵌入(Block Query Embed)语法 https://,github.com/88250/lute/issues/96\r\n\r\n NodeBlockQueryEmbed: 465, // 内容块查询嵌入\r\n NodeOpenBrace: 466, // {\r\n NodeCloseBrace: 467, // }\r\n NodeBlockQueryEmbedScript: 468, // 内容块查询嵌入脚本\r\n\r\n // 超级块语法 https://,github.com/88250/lute/issues/111\r\n\r\n NodeSuperBlock: 475, // 超级块节点\r\n NodeSuperBlockOpenMarker: 476, // 开始超级块标记符 {{{\r\n NodeSuperBlockLayoutMarker: 477, // 超级块布局 row/col\r\n NodeSuperBlockCloseMarker: 478, // 结束超级块标记符 }}}\r\n\r\n // 上标下标语法 https://,github.com/88250/lute/issues/113\r\n\r\n NodeSup: 485, // 上标\r\n NodeSupOpenMarker: 486, // 开始上标标记符 ^\r\n NodeSupCloseMarker: 487, // 结束上标标记符 ^\r\n NodeSub: 490, // 下标\r\n NodeSubOpenMarker: 491, // 开始下标标记符 ~\r\n NodeSubCloseMarker: 492, // 结束下标标记符 ~\r\n\r\n // Git 冲突标记 https://,github.com/88250/lute/issues/131\r\n\r\n NodeGitConflict: 495, // Git 冲突标记\r\n NodeGitConflictOpenMarker: 496, // 开始 Git 冲突标记标记符 <<<<<<<\r\n NodeGitConflictContent: 497, // Git 冲突标记内容\r\n NodeGitConflictCloseMarker: 498, // 结束 Git 冲突标记标记符 >>>>>>>\r\n\r\n // <iframe> 标签\r\n\r\n NodeIFrame: 500, // <iframe> 标签\r\n\r\n // <audio> 标签\r\n\r\n NodeAudio: 505, // <audio> 标签\r\n\r\n // <video> 标签\r\n\r\n NodeVideo: 510, // <video> 标签\r\n\r\n // <kbd> 标签\r\n\r\n NodeKbd: 515, // 键盘\r\n NodeKbdOpenMarker: 516, // 开始 kbd 标记符 <kbd>\r\n NodeKbdCloseMarker: 517, // 结束 kbd 标记符 </kbd>\r\n\r\n // <u> 标签\r\n\r\n NodeUnderline: 520, // 下划线\r\n NodeUnderlineOpenMarker: 521, // 开始下划线标记符 <u>\r\n NodeUnderlineCloseMarker: 522, // 结束下划线标记符 </u>\r\n\r\n // <br> 标签\r\n\r\n NodeBr: 525, // <br> 换行\r\n\r\n // <span data-type=\"mark\">foo</span> 通用的行级文本标记,不能嵌套\r\n\r\n NodeTextMark: 530, // 文本标记,该节点因为不存在嵌套,所以不使用 Open/Close 标记符\r\n\r\n // Protyle 挂件,<iframe data-type=\"NodeWidget\">\r\n\r\n NodeWidget: 535, // <iframe data-type=\"NodeWidget\" data-subtype=\"widget\"></iframe>\r\n\r\n // 文件注解引用 https://,github.com/88250/lute/issues/155\r\n\r\n NodeFileAnnotationRef: 540, // 文件注解引用节点\r\n NodeFileAnnotationRefID: 541, // 被引用的文件注解 ID(file/annotation)\r\n NodeFileAnnotationRefSpace: 542, // 被引用的文件注解 ID 和文件注解引用锚文本之间的空格\r\n NodeFileAnnotationRefText: 543, // 文件注解引用锚文本(不能为空,如果为空的话会自动使用 ID 渲染)\r\n\r\n // 属性视图 https://,github.com/siyuan-note/siyuan/issues/7535 <div data-type=\"NodeAttributeView\" data-av-type=\"table\" data-av-id=\"xxx\"></div>\r\n\r\n NodeAttributeView: 550, // 属性视图\r\n\r\n // 自定义块 https://,github.com/siyuan-note/siyuan/issues/8418 ;;;info\r\n\r\n NodeCustomBlock: 560, // 自定义块\r\n\r\n NodeTypeMaxVal: 1024, // 节点类型最大值\r\n};\r\n","/** ════════════════════════🏳🌈 cache 🏳🌈════════════════════════\r\n * 对于思源内核 api 的调用存到内存,通过快取技术避免重复请求和没有必要的请求,加速程序运行速度,但这可能会导致数据不是最新的\r\n ** ════════════════════════🚧 cache 🚧════════════════════════ */\r\n\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, DB_block_path, S_Node } from './siyuan_type.ts'\r\n\r\nlet cache = true\r\n/** 控制是否启用快取功能 */\r\nexport function setCache(b: boolean) {\r\n cache = b\r\n}\r\n\r\n/** sql->查询结果 */\r\nconst sqlCacheMap = new Map<string, any>()\r\n/** hpath->S_Node文档节点 */\r\nconst hpathCacheMap = new Map<string, S_Node>()\r\n/** id->S_Node */\r\nconst idCacheMap = new Map</** id */ string, S_Node>()\r\n/** id->DB_block */\r\nconst blockCacheMap = new Map</** id */ string, DB_block>()\r\n\r\nexport async function getIDsByHPath(p: {\r\n path: string\r\n notebook: string\r\n}): Promise<string[]> {\r\n if (cache && hpathCacheMap.has(p.path)) {\r\n const id = hpathCacheMap.get(p.path)?.ID\r\n // TODO 也许会有重复hpath这里暂不考虑\r\n return id ? [id] : []\r\n }\r\n const ids = await API.filetree_getIDsByHPath(p)\r\n return ids\r\n}\r\n\r\n/** 设置快取 sqlCacheMap */\r\nexport async function query_sql(stmt: string): Promise<any> {\r\n if (cache && sqlCacheMap.has(stmt)) {\r\n return sqlCacheMap.get(stmt)\r\n }\r\n const res = await API.query_sql({\r\n stmt,\r\n })\r\n if (cache) {\r\n sqlCacheMap.set(stmt, res)\r\n }\r\n return res\r\n}\r\n\r\n/** 设置快取 hpathCacheMap idCacheMap */\r\nexport async function get_doc_by_hpath(hpath: string): Promise<S_Node> {\r\n if (cache) {\r\n const c = hpathCacheMap.get(hpath)\r\n if (c) return c\r\n }\r\n const docBlock = (\r\n (await query_sql(\r\n `SELECT * FROM blocks WHERE hpath = '${hpath}'`,\r\n )) as DB_block[]\r\n )[0]\r\n if (docBlock === undefined) throw new Error(`not doc by:${hpath}`)\r\n const res = await get_doc_by_SyPath(DB_block_path(docBlock))\r\n if (cache) {\r\n hpathCacheMap.set(hpath, res)\r\n }\r\n return res\r\n}\r\n/** 设置快取 idCacheMap */\r\nexport async function get_doc_by_SyPath(path: string): Promise<S_Node> {\r\n const res = parentRef(\r\n (await API.file_getFile({\r\n path,\r\n })) as S_Node,\r\n )\r\n if (cache) {\r\n idCache(res)\r\n }\r\n return res\r\n}\r\n\r\nexport async function get_block_by_id(id: string) {\r\n if (cache) {\r\n const block = blockCacheMap.get(id)\r\n if (block) return block\r\n }\r\n const blocks = (await query_sql(`\r\n SELECT * from blocks\r\n WHERE id = '${id}'\r\n `)) as DB_block[]\r\n if (blocks.length === 0) {\r\n return\r\n }\r\n if (cache) blockCacheMap.set(id, blocks[0])\r\n return blocks[0]\r\n}\r\nexport async function get_node_by_id(id?: string) {\r\n if (id === undefined) return\r\n if (cache) {\r\n const node = idCacheMap.get(id)\r\n if (node) return node\r\n }\r\n const doc = await get_doc_by_child_id(id)\r\n if (doc === undefined) return\r\n return findNode(doc)\r\n\r\n function findNode(node: S_Node): S_Node | undefined {\r\n if (node.ID === id) return node\r\n if (node.Children) {\r\n return node.Children.find((child) => findNode(child))\r\n }\r\n }\r\n}\r\n/** set blockCacheMap*/\r\n// TODO 需要更换成能够完全遍历一个笔记本的写法\r\nexport async function allDocBlock_by_bookId(id: string) {\r\n const res = (await query_sql(`\r\n SELECT * from blocks\r\n WHERE box = '${id}'\r\n AND type = 'd'\r\n limit 150000 OFFSET 0\r\n `)) as DB_block[]\r\n if (cache) {\r\n res.forEach((block) => blockCacheMap.set(block.id, block))\r\n }\r\n return res\r\n}\r\n\r\nexport async function get_doc_by_child_id(\r\n id: string,\r\n): Promise<S_Node | undefined> {\r\n if (cache) {\r\n const child = idCacheMap.get(id)\r\n if (child) {\r\n let node = child\r\n while (true) {\r\n if (node.Type === 'NodeDocument') {\r\n return node\r\n } else if (node === undefined) {\r\n break\r\n }\r\n node = node.Parent\r\n }\r\n }\r\n }\r\n const block = await get_block_by_id(id)\r\n if (block === undefined) return\r\n return await get_doc_by_hpath(block.hpath)\r\n}\r\n\r\nfunction idCache(node: S_Node) {\r\n if (node.ID) {\r\n idCacheMap.set(node.ID, node)\r\n }\r\n if (node.Children) {\r\n node.Children.forEach(idCache)\r\n }\r\n}\r\n\r\n/** 为 children 节点附加 Parent 引用 */\r\nexport function parentRef(sy: S_Node) {\r\n for (const child of sy?.Children ?? []) {\r\n child.Parent = sy\r\n parentRef(child)\r\n }\r\n return sy\r\n}\r\n","import { get_node_by_id } from './cache.ts'\nimport type { Config } from './config.ts'\nimport { storeDep } from './dependency.ts'\nimport type { Render } from './render.ts'\nimport type { DB_block } from './siyuan_type.ts'\n\n/** 生成当前实例所有引用文档的RSS XML */\nexport async function generateRSSXML(\n path: string,\n renderInstance: Render,\n config: Config,\n): Promise<string> {\n const refNode = (\n await Promise.all([...renderInstance.refs.values()].map(get_node_by_id))\n ).filter((el) => el)\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n <channel>\n <title>${config.sitemap.title}</title>\n <link>${config.sitemap.siteLink}</link>\n <description>${config.sitemap.description}</description>\n <atom:link href=\"${\n config.sitemap.sitePrefix\n }${path}\" rel=\"self\" type=\"application/rss+xml\"/>\n <lastBuildDate>${new Date().toISOString()}</lastBuildDate>\n ${(\n await Promise.all(\n refNode.map(\n async (node) => `<item>\n <title>${node?.Properties?.title}</title>\n <link>${config.sitemap.sitePrefix}${\n node?.ID ? (await storeDep.getHPathByID_Node(node?.ID)) + '.html' : ''\n }</link>\n <description>${'' /** TODO 或许可以加入ai 进行摘要 */}</description>\n <pubDate>${\n node?.Properties?.updated\n ? new Date(\n node.Properties.updated.replace(\n /(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})/,\n '$1/$2/$3 $4:$5:$6',\n ),\n ).toISOString()\n : ''\n }</pubDate>\n </item>`,\n ),\n )\n ).join('\\n')}\n </channel>\n </rss>`\n}\n\n/** 生成 sitemap.xml 文件内容 */\nexport function sitemap_xml(\n docArr: DB_block[],\n config: {\n sitePrefix: string\n },\n) {\n const urlList: string = docArr\n .map((doc) => {\n let lastmod = ''\n const time = doc.ial.match(/updated=\\\"(\\d+)\\\"/)?.[1] ?? doc.created\n if (time) {\n lastmod = `\\n<lastmod>${time.slice(0, 4)}-${time.slice(\n 4,\n 6,\n )}-${time.slice(6, 8)}</lastmod>`\n }\n return `<url>\n <loc>${config.sitePrefix}${doc.hpath}.html</loc>${lastmod}\n </url>\\n`\n })\n .join('')\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n ${urlList}\n </urlset>`\n}\n","import { Config, currentConfig, tempConfig } from '~/core/config.ts'\r\nimport { htmlTemplate } from './htmlTemplate.ts'\r\nimport { getRender, renderHTML } from './render.ts'\r\nimport { API } from './siyuan_api.ts'\r\nimport { DB_block, DB_block_path, S_Node } from './siyuan_type.ts'\r\nimport { deepAssign } from '~/util/deep_assign.ts'\r\nimport {\r\n allDocBlock_by_bookId,\r\n get_doc_by_SyPath,\r\n get_node_by_id,\r\n} from './cache.ts'\r\nimport packageJson from '~/../package.json' with { type: 'json' };\r\nimport { generateRSSXML, sitemap_xml } from './genRssXml.ts'\r\nimport { downloadZIP } from './genZip.ts'\r\n\r\nexport interface DocTree {\r\n [/** \"/计算机基础课/自述\" */ docPath: string]: {\r\n sy: S_Node\r\n docBlock: DB_block\r\n }\r\n}\r\nexport interface FileTree {\r\n [path: string]: string | ArrayBuffer\r\n}\r\nexport type Build = typeof build\r\n/** 根据配置文件进行编译\r\n * TODO 将浏览器写文件的部分抽离出去,也改成使用 onFileTree\r\n */\r\nexport async function build(\r\n config: Config,\r\n effect:{\r\n log: (msg:string)=>void,\r\n percentage:(_n: number)=>void,\r\n },\r\n otherConfig?: {\r\n // 监听文件准备完毕 TODO:应该修改实现,而非目前直接全量加载到内存\r\n onFileTree?: (tree: FileTree) => void\r\n renderHtmlFn?: typeof renderHTML\r\n },\r\n) {\r\n const _renderHTML = otherConfig?.renderHtmlFn ?? renderHTML\r\n const book = config.notebook\r\n const docTree: DocTree = {}\r\n const skipBuilds = useSkipBuilds()\r\n\r\n let oldPercentage = 0\r\n let total = 0\r\n /** 较为精准的估计进度 */\r\n function processPercentage(\r\n /** 0~1 的小数 表示这个数占整体百分之多少 */ percentage: number,\r\n ) {\r\n total += oldPercentage\r\n return (/** 0~1 的小数 */ process: number) => {\r\n oldPercentage = process * percentage\r\n effect.percentage((total + oldPercentage) * 100)\r\n }\r\n }\r\n effect.log( `=== 开始编译 ${book.name} ===`)\r\n let process = processPercentage(0.4)\r\n /** 查询所有文档级block\r\n * TODO 增量编译时不应该全部获取\r\n */\r\n const Doc_blocks: DB_block[] = await allDocBlock_by_bookId(book.id)\r\n /** docBlock 的引用没有更新:true */\r\n function refsNotUpdated(docBlock: DB_block): boolean {\r\n const refs = config.__skipBuilds__[docBlock.id]?.refs ?? []\r\n for (const ref_id of refs) {\r\n const new_doc_hash = Doc_blocks.find(\r\n (docBlock) => docBlock.id === ref_id,\r\n )?.hash\r\n const old_doc_hash = config.__skipBuilds__[ref_id]?.hash\r\n if (new_doc_hash === undefined || old_doc_hash === undefined) {\r\n /** 不应该进入此分支的,如果进来了就重新编译吧 */\r\n return false\r\n } else if (new_doc_hash === old_doc_hash) {\r\n continue\r\n } else {\r\n return false\r\n }\r\n }\r\n /** 引用的都没有更新 */\r\n return true\r\n }\r\n effect.log (`=== 查询文档级block完成 ===`)\r\n let i = 0\r\n await Promise.all(\r\n Doc_blocks.map(async (docBlock) => {\r\n const sy = await get_doc_by_SyPath(DB_block_path(docBlock))\r\n docTree[docBlock.hpath] = { sy, docBlock }\r\n i++\r\n process(i / Doc_blocks.length)\r\n }),\r\n )\r\n const fileTree: FileTree = {}\r\n\r\n process = processPercentage(0.4)\r\n\r\n const enableIncrementalCompilation_doc = (() => {\r\n if (packageJson.version !== config.OceanPress.version) {\r\n effect.log(\r\n `配置文件版本号[${config.OceanPress.version}]与OceanPress版本[${packageJson.version}]不一致,将进行文档全量编译`,\r\n )\r\n return false\r\n }\r\n return config.enableIncrementalCompilation_doc\r\n })()\r\n effect.log (`=== 开始渲染文档 ===`)\r\n await Promise.all(\r\n Object.entries(docTree).map(async ([path, { sy, docBlock }]) => {\r\n if (\r\n config.enableIncrementalCompilation &&\r\n enableIncrementalCompilation_doc &&\r\n /** 文档本身没有发生变化 */\r\n config.__skipBuilds__[docBlock.id]?.hash === docBlock.hash &&\r\n /** docBlock所引用的文档也没有更新 */\r\n refsNotUpdated(docBlock)\r\n )\r\n return /** skip */\r\n\r\n try {\r\n const rootLevel =\r\n path.split('/').length -\r\n 2 /** 最开头有一个 / 还有一个 data 目录所以减二 */\r\n const renderInstance = getRender()\r\n\r\n fileTree[path + '.html'] = await htmlTemplate(\r\n {\r\n title: sy.Properties?.title || '',\r\n htmlContent: await _renderHTML(sy, renderInstance),\r\n level: rootLevel,\r\n },\r\n {\r\n ...tempConfig.cdn,\r\n embedCode: config.embedCode,\r\n },\r\n )\r\n\r\n /** rss.xml 生成 */\r\n if (config.sitemap.rss && path.endsWith('.rss.xml')) {\r\n const rssPath = path\r\n fileTree[rssPath] =await generateRSSXML(rssPath, renderInstance, config)\r\n effect.log(`渲染 rss.xml:${rssPath} 完毕`)\r\n }\r\n if (\r\n config.enableIncrementalCompilation &&\r\n config.enableIncrementalCompilation_doc\r\n ) {\r\n /** 更新为当前hash */\r\n skipBuilds.add(docBlock.id, {\r\n hash: docBlock.hash,\r\n })\r\n }\r\n /** 无论是否配置增量更新都要更新正向引用,不然开启增量更新后没有引用数据可用 */\r\n skipBuilds.add(docBlock.id, {\r\n refs: /** 保存引用 */ [...renderInstance.refs.values()],\r\n })\r\n } catch (error) {\r\n effect.log(`${path} 渲染失败:${error}`)\r\n console.log(error)\r\n }\r\n process(i / Doc_blocks.length)\r\n effect.log(`渲染完毕:${path}`)\r\n }),\r\n )\r\n effect.log( `=== 渲染文档完成 ===`)\r\n effect.log( `=== 开始生成 sitemap.xml ===`)\r\n if (config.sitemap.enable) {\r\n fileTree['sitemap.xml'] = sitemap_xml(Doc_blocks, config.sitemap)\r\n }\r\n if (config.excludeAssetsCopy === false) {\r\n effect.log( `=== 开始复制资源文件 ===`)\r\n const assets: {\r\n box: string\r\n docpath: string\r\n path: string\r\n hash: string\r\n id: string\r\n }[] = await API.query_sql({\r\n stmt: `SELECT * from assets\r\n WHERE box = '${book.id}'\r\n limit 150000 OFFSET 0`,\r\n })\r\n await Promise.all(\r\n assets.map(async (item) => {\r\n if (\r\n config.enableIncrementalCompilation &&\r\n /** 资源没有变化,直接跳过 */\r\n config.__skipBuilds__[item.id]?.hash === item.hash\r\n ) {\r\n return /** skip */\r\n } else {\r\n fileTree[item.path] = await API.get_assets({\r\n path: item.path,\r\n })\r\n if (config.enableIncrementalCompilation) {\r\n skipBuilds.add(item.id, { hash: item.hash })\r\n }\r\n }\r\n }),\r\n )\r\n effect.log( `=== 开始复制挂件资源文件 ===`)\r\n const widgetList: DB_block[] = await API.query_sql({\r\n stmt: `\r\n SELECT *\r\n from blocks\r\n WHERE box = '${book.id}'\r\n AND type = 'widget'\r\n limit 150000 OFFSET 0\r\n `,\r\n })\r\n const widgetNode = (\r\n await Promise.all(\r\n widgetList.map(async (el) => await get_node_by_id(el.id)),\r\n )\r\n )\r\n .filter(\r\n (widget) =>\r\n (widget?.Properties as any)?.['custom-oceanpress-widget-update'],\r\n )\r\n .map(async (widget) => {\r\n if (!widget || !widget?.ID) return\r\n const update = (widget?.Properties as any)?.[\r\n 'custom-oceanpress-widget-update'\r\n ] as string\r\n if (\r\n config.enableIncrementalCompilation &&\r\n config.__skipBuilds__[widget.ID]?.updated === update\r\n ) {\r\n return /** 资源没有变化,直接跳过 */\r\n } else {\r\n const id = widget.ID\r\n // 快照保存的位置 `/data/storage/oceanpress/widget_img/${id}.jpg`\r\n fileTree[`assets/widget/${id}.jpg`] = (await API.file_getFile({\r\n path: `data/storage/oceanpress/widget_img/${id}.jpg`,\r\n })) as ArrayBuffer\r\n if (config.enableIncrementalCompilation) {\r\n skipBuilds.add(id, { updated: update })\r\n }\r\n }\r\n })\r\n await Promise.all(widgetNode)\r\n }\r\n\r\n // === 输出编译成果 ===\r\n if (otherConfig?.onFileTree) {\r\n otherConfig.onFileTree(fileTree)\r\n }\r\n if (config.compressedZip) {\r\n effect.log( `=== 开始生成压缩包 ===`)\r\n await downloadZIP(fileTree, {\r\n // TODO 这里应该移出来成为全局的写选项\r\n withoutZip: tempConfig.withoutPublicZip,\r\n publicZip: tempConfig.cdn.publicZip,\r\n })\r\n }\r\n config.OceanPress.version = packageJson.version\r\n /** 更新跳过编译的资源 */\r\n skipBuilds.write()\r\n effect.percentage(100)\r\n effect.log( '编译完毕')\r\n\r\n return {fileTree}\r\n}\r\n\r\n\r\nfunction useSkipBuilds() {\r\n const obj: { [k: string]: { hash?: string } } = {}\r\n return {\r\n add(\r\n id: string,\r\n value: { hash?: string; refs?: string[]; updated?: string },\r\n ) {\r\n if (obj[id] === undefined) {\r\n obj[id] = {}\r\n }\r\n deepAssign(obj[id], value)\r\n },\r\n /** 将缓存的写入到配置文件 */\r\n write() {\r\n deepAssign(currentConfig.value.__skipBuilds__, obj)\r\n },\r\n }\r\n}\r\n","import { createRPC } from 'oceanpress-rpc'\r\nimport type { API } from 'oceanpress-server'\r\nimport { stringify } from 'superjson'\r\nimport { type Config } from '~/core/config.ts'\r\nimport { genZIP } from '~/core/genZip.ts'\r\nimport type { OceanPressPlugin } from '~/core/ocean_press.ts'\r\n\r\n/** 上传数据到 s3 适配云端 */\r\nexport function deployOceanPressServer_plugin(config: Config) {\r\n const plugin: OceanPressPlugin = {\r\n async build_onFileTree([tree], next) {\r\n next(tree)\r\n\r\n const client = await createRPC<API>('apiConsumer', {\r\n async remoteCall(method, data) {\r\n let body: ReadableStream | string | Blob\r\n // 如果第一参数是 ReadableStream 的时候,直接使用 ReadableStream 作为 body,不用考虑其他参数,因为这种情况只支持一个参数\r\n let content_type\r\n if (data[0] instanceof ReadableStream) {\r\n // body = data[0] //会遇到一些兼容性问题, http 1.1 不支持使用流作为 body,需要转换为 blob 或者 arraybuffer\r\n\r\n body = await new Response(data[0]).blob()\r\n content_type = 'application/octet-stream'\r\n } else {\r\n body = stringify(data)\r\n console.log('[body]', body)\r\n content_type = 'application/json'\r\n }\r\n return fetch(`${config.oceanPressServer.apiBase}/api/${method}`, {\r\n method: 'POST',\r\n body,\r\n headers: {\r\n 'x-api-key': config.oceanPressServer.apiKey,\r\n 'Content-Type': content_type,\r\n },\r\n // @ts-expect-error 在 node 运行的时候需要声明双工模式才能正确发送 ReadableStream,TODO 需要验证浏览器端可以这样运行吗\r\n duplex: 'half', // 关键:显式声明半双工模式\r\n })\r\n .then((res) => res.json())\r\n .then((r) => {\r\n if (r.error) {\r\n console.log('[r]', r)\r\n throw new Error()\r\n }\r\n return r.result\r\n })\r\n },\r\n })\r\n const zip = await genZIP(tree, { withoutZip: true })\r\n const sizeInMB = zip.size / (1024 * 1024)\r\n console.log('[zip.size in MB]', sizeInMB.toFixed(2))\r\n // 将 Blob 转换为 ReadableStream\r\n const readableStream = zip.stream()\r\n const { chunkCount, fileId } = await client.API.upload(readableStream)\r\n\r\n console.log('[res]', { chunkCount, fileId })\r\n const res = await client.API.deploy({ zipFileId: fileId })\r\n console.log('[deploy res]', res)\r\n },\r\n }\r\n return plugin\r\n}\r\n","import { MeilisearchPlugin } from '~/plugins/meilisearch_plugin/meilisearch_upload.ts'\r\nimport { Config } from './config.ts'\r\nimport { PluginCenter } from './plugin.ts'\r\nimport { s3Upload_plugin } from '~/plugins/publish/s3.ts'\r\nimport { FileTree, build } from './build.ts'\r\nimport { renderHTML } from './render.ts'\r\nimport { deployOceanPressServer_plugin } from '~/plugins/publish/OceanPressServer.ts'\r\n\r\nexport type OceanPressPlugin = PluginCenter<OceanPress['funMap']>['pluginType']\r\n\r\n/** OceanPress 核心类,用于管理插件和配置,执行构建过程。 */\r\nexport class OceanPress {\r\n async build(effect: {\r\n log: (msg: string) => void\r\n percentage: (_n: number) => void\r\n }) {\r\n const build_res = this.pluginCenter.fun.build(this.config, effect, {\r\n renderHtmlFn: this.pluginCenter.fun.build_renderHTML,\r\n onFileTree: this.pluginCenter.fun.build_onFileTree,\r\n })\r\n return build_res\r\n }\r\n funMap = {\r\n /** 开始整体编译 */\r\n build,\r\n /** 用于渲染文档的函数 */\r\n build_renderHTML: renderHTML,\r\n /** 编译完成后文件树的处理回调函数 */\r\n build_onFileTree: (_tree: FileTree) => {},\r\n }\r\n pluginCenter: PluginCenter<OceanPress['funMap']> = new PluginCenter(\r\n this.funMap,\r\n )\r\n constructor(public config: Config) {\r\n // TODO 内置插件,以后应该改成由用户配置\r\n if (config.meilisearch.enable) {\r\n this.pluginCenter.registerPlugin(\r\n new MeilisearchPlugin(config.meilisearch),\r\n )\r\n }\r\n if (config.s3.enable) {\r\n this.pluginCenter.registerPlugin(s3Upload_plugin)\r\n }\r\n if (config.oceanPressServer.enable) {\r\n this.pluginCenter.registerPlugin(\r\n deployOceanPressServer_plugin(this.config),\r\n )\r\n }\r\n }\r\n}\r\n","import { storeDep } from '~/core/dependency.ts'\r\nimport { DB_block_path, type S_Node } from './siyuan_type.ts'\r\nimport { get_block_by_id, get_doc_by_child_id } from './cache.ts'\r\n\r\nstoreDep.getDocByChildID = async (id: string) => {\r\n return await get_doc_by_child_id(id)\r\n}\r\n\r\nstoreDep.getDocPathBySY = async (sy?: S_Node) => {\r\n if (sy?.ID) {\r\n const block = await get_block_by_id(sy.ID)\r\n if (block) {\r\n return DB_block_path(block)\r\n }\r\n }\r\n}\r\n\r\n/** TODO 应该可以从cache中获取,而不需要查询 */\r\nstoreDep.getHPathByID_Node = async (\r\n id_node: string | S_Node,\r\n): Promise<string> => {\r\n const id = typeof id_node === 'string' ? id_node : id_node.ID\r\n if (id === undefined) throw new Error('id is undefined')\r\n const docNode = await get_doc_by_child_id(id)\r\n if (docNode === undefined) throw new Error('docNode is undefined')\r\n const docBlock = await get_block_by_id(id)\r\n if (docBlock === undefined) throw new Error('docBlock is undefined')\r\n return docBlock.hpath\r\n}\r\n\r\nstoreDep.getNodeByID = async (id?: string): Promise<S_Node | undefined> => {\r\n if (id === undefined) return\r\n const doc = await storeDep.getDocByChildID(id)\r\n if (doc === undefined) return\r\n return getNode(doc)\r\n function getNode(node: S_Node): S_Node | undefined {\r\n if (node.ID === id) return node\r\n if (node.Children === undefined) return\r\n for (const child of node.Children) {\r\n const n = getNode(child)\r\n if (n) return n\r\n }\r\n }\r\n}\r\n","import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'node:fs'\r\nimport { storeDep } from '~/core/dependency.ts'\r\n\r\nstoreDep.getItem = getItem\r\nstoreDep.setItem = setItem\r\n\r\nexport function setItem(key: string, value: string) {\r\n if (!existsSync('./store/')) {\r\n // 目录不存在,递归创建目录\r\n mkdirSync('./store/', { recursive: true })\r\n }\r\n return writeFileSync(`./store/${key}`, value, {\r\n encoding: 'utf-8',\r\n })\r\n}\r\n\r\nexport function getItem(key: string): string | undefined {\r\n try {\r\n return readFileSync(`./store/${key}`, 'utf-8')\r\n } catch (_) {\r\n return undefined\r\n }\r\n}\r\n","import '~/core/render.api.dep'\nimport '~/util/store.node.dep'\nimport { Command } from 'commander'\n\nexport const program = new Command()\n\nprogram\n .name('OceanPress')\n .description('这是一款从思源笔记本生成一个静态站点的工具')\n","import { Command } from 'commander'\nimport { mkdir, readFile, writeFile } from 'fs/promises'\nimport { resolve } from 'path'\nimport { join } from 'path/posix'\nimport { program } from './common.ts'\nimport { currentConfig, loadConfigFile } from '~/core/config.ts'\nimport { OceanPress } from '~/core/ocean_press.ts'\n\nprogram\n .command('build')\n .description('输出静态站点源码')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-o, --output <string>', '指定输出目录位置')\n .action(async (opt: { config: string; output: string }) => {\n if (!opt.config || !opt.output) {\n console.log(`请设置配置文件位置和输出目录位置`)\n throw new Error('请设置配置文件位置和输出目录位置')\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n const filePath = resolve(opt.output)\n const ocean_press = new OceanPress(currentConfig.value)\n\n // node 端写磁盘插件\n ocean_press.pluginCenter.registerPlugin({\n async build_onFileTree([tree]) {\n for (const [path, data] of Object.entries(tree)) {\n const fullPath = join(filePath, './', path)\n const pathArray = fullPath.split('/').slice(0, -1)\n const dirPath = pathArray.join('/')\n mkdir(dirPath, { recursive: true })\n try {\n if (typeof data === 'string') {\n await writeFile(fullPath, data, 'utf-8')\n } else {\n await writeFile(fullPath, new DataView(data))\n }\n } catch (error) {\n console.log(`${fullPath} 无法写入`)\n }\n }\n },\n })\n\n await ocean_press.build({\n log: (msg) => {\n if (msg.startsWith('渲染:')) {\n process.stdout.write(`\\r\\x1b[K${msg}`)\n } else {\n process.stdout.write(`\\n${msg}`)\n }\n },\n percentage: (n) => {\n process.stdout.write(`\\r\\x1b[K进度:${n}%`)\n },\n })\n })\n","import { readFile } from 'fs/promises'\nimport { setCache } from '~/core/cache.ts'\nimport { loadConfigFile } from '~/core/config.ts'\nimport { server } from '~/server.ts'\nimport { program } from './common.ts'\nprogram\n .command('server')\n .description('启动动态代理')\n .option('-c, --config <string>', '指定配置文件的位置')\n .option('-h, --host <string>', 'web服务绑定到的地址', '127.0.0.1')\n .option('-p, --port <number>', 'web服务绑定到的端口', '80')\n .option(\n '--cache <boolean>',\n '配置为 true 时开启缓存,默认为 false 不开启缓存',\n 'false',\n )\n .action(\n async (opt: {\n config: string\n host: string\n port: string\n cache: 'false'\n }) => {\n if (!opt.config) {\n console.log(`请设置配置文件位置`)\n }\n const config = await readFile(opt.config, 'utf-8')\n loadConfigFile(JSON.parse(config))\n setCache(opt.cache !== 'false')\n server({\n hostname: opt.host,\n port: Number(opt.port),\n })\n },\n )\n","import { serve } from '@hono/node-server'\r\nimport { createHonoApp } from './core/hono_server.ts'\r\nimport { serveStatic } from '@hono/node-server/serve-static'\r\nimport { Hono } from 'hono'\r\nimport { join, resolve } from 'path/posix'\r\nconsole.log(join(import.meta.url.slice(5), '../../public/'))\r\n\r\nexport function server(config = { port: 80, hostname: '0.0.0.0' }) {\r\n const app = new Hono()\r\n\r\n // 方便开发调试样式\r\n app.use(\r\n '/notebook/*',\r\n serveStatic({\r\n root: './public/',\r\n onNotFound(path, c) {\r\n console.log('[onNotFound notebook path]', path)\r\n },\r\n }),\r\n )\r\n createHonoApp(app)\r\n return new Promise((resolve, _reject) => {\r\n serve(\r\n {\r\n fetch: app.fetch,\r\n port: config.port,\r\n hostname: config.hostname,\r\n },\r\n (info) => {\r\n resolve({ info, app })\r\n console.log(`Listening on http://${info.address}:${info.port}`)\r\n },\r\n )\r\n })\r\n}\r\n","import { Context, Hono } from 'hono'\r\nimport { currentConfig, tempConfig } from './config.ts'\r\nimport { get_doc_by_hpath } from './cache.ts'\r\nimport { htmlTemplate } from './htmlTemplate.ts'\r\nimport { renderHTML } from './render.ts'\r\nimport { stream } from 'hono/streaming'\r\nimport type { StatusCode } from 'hono/utils/http-status'\r\n\r\nexport function createHonoApp(app: Hono = new Hono()) {\r\n app.get('/', (c) => c.redirect('/index.html'))\r\n app.get('/assets/*', assetsHandle)\r\n app.get('*', async (c) => {\r\n const path = decodeURIComponent(c.req.path)\r\n\r\n const r = await renderHtmlByUriPath(path).catch(async (err: Error) => {\r\n if (err.message.includes('not doc')) {\r\n return await assetsHandle(c)\r\n }\r\n throw err\r\n })\r\n\r\n if (r instanceof Error) {\r\n throw r\r\n } else if (typeof r === 'string') {\r\n return c.html(r)\r\n } else {\r\n return r\r\n }\r\n })\r\n return app\r\n}\r\nasync function assetsHandle(c: Context) {\r\n // TODO 处于安全考虑应该防范 file 跳出 assets\r\n const file = c.req.path\r\n const widgetPrefix = '/assets/widget/'\r\n const isWidget = file.startsWith(widgetPrefix)\r\n const apiPath = `${currentConfig.value.apiPrefix}${\r\n isWidget ? '/api/file/getFile' : file\r\n }`\r\n const r = await fetch(apiPath, {\r\n headers: {\r\n Authorization: `Token ${currentConfig.value.authorized}`,\r\n },\r\n method: isWidget ? 'POST' : 'GET',\r\n body: isWidget\r\n ? JSON.stringify({\r\n path: `/data/storage/oceanpress/widget_img/${file.substring(\r\n widgetPrefix.length,\r\n )}`,\r\n })\r\n : undefined,\r\n })\r\n const body = r.body\r\n if (!body) {\r\n return c.text('响应体为 null', 500, { 'Content-Type': 'text/plain' })\r\n }\r\n c.status(r.status as StatusCode)\r\n return stream(c, async (writeStream) => {\r\n const reader = body.getReader()\r\n while (true) {\r\n const r = await reader.read()\r\n if (r.done) {\r\n writeStream.close()\r\n break\r\n } else {\r\n writeStream.write(r.value)\r\n }\r\n }\r\n })\r\n}\r\nasync function renderHtmlByUriPath(path: string): Promise<string | Error> {\r\n const hpath = decodeURIComponent(path)\r\n .replace(/\\#(.*)?$/, '')\r\n .replace(/\\.html$/, '')\r\n\r\n const doc = await get_doc_by_hpath(hpath)\r\n\r\n return await htmlTemplate(\r\n {\r\n title: doc.Properties?.title || '',\r\n htmlContent: await renderHTML(doc),\r\n level: path.split('/').length - 1 /** 最开头有一个 / */,\r\n },\r\n {\r\n ...tempConfig.cdn,\r\n embedCode: currentConfig.value.embedCode,\r\n },\r\n )\r\n}\r\n","\r\n\r\nimport './cli/deploy.ts'\r\nimport './cli/build.ts'\r\nimport './cli/server.ts'\r\nimport { program } from './cli/common.ts'\r\n\r\nprogram.parse(process.argv)\r\n"],"mappings":"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","names":["API","stringify","html","html","c","version","watch","watch","usePromiseComputed","fn","html","sy","process","docBlock","res","stringify","readFile","readFile","readFile","r","Hono","join","resolve","readFile"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oceanpress",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oceanpress": "./dist-cli/cli.js"
|
|
@@ -32,9 +32,7 @@
|
|
|
32
32
|
"vditor": "^3.10.9",
|
|
33
33
|
"vue": "^3.5.13",
|
|
34
34
|
"vue-router": "^4.5.0",
|
|
35
|
-
"zstd-codec": "^0.1.5"
|
|
36
|
-
"oceanpress-rpc": "1.0.1",
|
|
37
|
-
"oceanpress-server": "1.0.6"
|
|
35
|
+
"zstd-codec": "^0.1.5"
|
|
38
36
|
},
|
|
39
37
|
"devDependencies": {
|
|
40
38
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
@@ -44,7 +42,9 @@
|
|
|
44
42
|
"typescript": "^5.8.2",
|
|
45
43
|
"vite": "^6.2.2",
|
|
46
44
|
"vite-plugin-vue-devtools": "^7.7.2",
|
|
47
|
-
"vue-tsc": "^2.2.8"
|
|
45
|
+
"vue-tsc": "^2.2.8",
|
|
46
|
+
"oceanpress-rpc": "1.0.1",
|
|
47
|
+
"oceanpress-server": "1.0.6"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"dev": "vite",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"build": "vite build && npm run build_lib",
|
|
54
54
|
"build_lib": "vite build --config vite.sw.config.ts",
|
|
55
55
|
"build_app": "vite build --mode library",
|
|
56
|
+
"build_cli": "tsup",
|
|
56
57
|
"build_plugin_ui": "vite build --config vite.plugin.config.ts",
|
|
57
58
|
"dev_plugin_ui": "vite build --watch --config vite.plugin.config.ts",
|
|
58
59
|
"generate_dependency_graph": "depcruise src --include-only '^src' --output-type dot > ./assets/dep.dot",
|