czon 0.6.2 → 0.6.3

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.
@@ -70,7 +70,7 @@ npx czon@latest ls-files
70
70
 
71
71
  基于内容,进行 MBTI 分析,分析内容创作者的性格倾向和行为特征,必须给出每个倾向维度的证据。
72
72
 
73
- 基于内容,进行价值观分析,探讨内容所反映的核心价值观和信念体系,给出价值观的排序和具体例子。
73
+ 基于内容,进行施瓦茨价值观分析,探讨内容所反映的核心价值观和信念体系,给出价值观的排序和具体例子。
74
74
 
75
75
  基于内容,进行精神分析 (包括心理防御机制、潜意识动机等),必须为每个评价标签给出置信度,给出具体例子,解释其作用和影响。
76
76
 
@@ -63,13 +63,15 @@ const spiderStaticSiteGenerator = async () => {
63
63
  for (const lang of metadata_1.MetaData.options.langs || []) {
64
64
  const markdown = await fs.readFile(path.join(paths_1.CZON_SRC_DIR, lang, file.path), 'utf-8');
65
65
  const { frontmatter, body } = (0, frontmatter_1.parseFrontmatter)(markdown);
66
- const markdownHtml = (0, convertMarkdownToHtml_1.convertMarkdownToHtml)(file.path, lang, body);
67
- contents.push({
66
+ const article = {
68
67
  lang,
69
68
  file,
70
- body: markdownHtml,
69
+ body: '',
71
70
  frontmatter,
72
- });
71
+ headings: [],
72
+ };
73
+ (0, convertMarkdownToHtml_1.convertMarkdownToHtml)(article, file.path, lang, body);
74
+ contents.push(article);
73
75
  }
74
76
  }
75
77
  while (queue.length > 0) {
@@ -25,7 +25,7 @@ const ContentPage = props => {
25
25
  // 查找指向当前文章的其他文章
26
26
  const thisPath = (0, node_path_1.resolve)('/', props.file.path);
27
27
  const referencedFiles = props.ctx.site.files.filter(f => f.links.some(link => (0, node_path_1.resolve)('/', (0, node_path_1.dirname)(f.path), link) === thisPath));
28
- return (react_1.default.createElement("html", { lang: props.lang, style: { background: 'black', overflow: 'hidden' } },
28
+ return (react_1.default.createElement("html", { lang: props.lang },
29
29
  react_1.default.createElement("head", null,
30
30
  react_1.default.createElement("meta", { charSet: "UTF-8" }),
31
31
  react_1.default.createElement("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }),
@@ -51,6 +51,11 @@ const ContentPage = props => {
51
51
  react_1.default.createElement(PageLayout_1.PageLayout, { header: react_1.default.createElement(CZONHeader_1.CZONHeader, { ctx: props.ctx, lang: props.lang, file: props.file }), navigator: react_1.default.createElement("nav", { className: "sidebar hidden md:block" },
52
52
  react_1.default.createElement(Navigator_1.Navigator, { ctx: props.ctx, file: props.file, lang: props.lang })), main: react_1.default.createElement("main", { className: "content" },
53
53
  react_1.default.createElement(ContentMeta_1.ContentMeta, { ctx: props.ctx, file: props.file, lang: props.lang }),
54
+ react_1.default.createElement("div", { className: "border-b mb-4 pb-2" },
55
+ react_1.default.createElement("h2", { className: "text-2xl font-semibold mb-2" }, "Table of Contents"),
56
+ props.content.headings.map(heading => (react_1.default.createElement("a", { key: heading.id, href: `#${heading.id}`,
57
+ // 按照 heading.depth 设置缩进
58
+ className: `block ps-${heading.depth * 4} mb-2` }, heading.text)))),
54
59
  react_1.default.createElement("div", { className: "content-body" },
55
60
  react_1.default.createElement("article", { dangerouslySetInnerHTML: { __html: props.content.body } }),
56
61
  relatedContents.length > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
package/dist/ssg/style.js CHANGED
@@ -40,7 +40,6 @@ html, body {
40
40
  margin: 0;
41
41
  padding: 0;
42
42
  width: 100%;
43
- height: 100%;
44
43
  }
45
44
 
46
45
  html[lang='ar-SA'] {
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.convertMarkdownToHtml = void 0;
7
7
  const highlight_js_1 = __importDefault(require("highlight.js"));
8
8
  const marked_1 = require("marked");
9
- const marked_katex_extension_1 = __importDefault(require("marked-katex-extension"));
10
9
  const marked_footnote_1 = __importDefault(require("marked-footnote"));
11
- const metadata_1 = require("../metadata");
10
+ const marked_katex_extension_1 = __importDefault(require("marked-katex-extension"));
12
11
  const path_1 = require("path");
12
+ const metadata_1 = require("../metadata");
13
13
  // 辅助函数:转义 HTML 特殊字符
14
14
  function escapeHtml(unsafe) {
15
15
  return unsafe
@@ -26,7 +26,8 @@ marked_1.marked.use((0, marked_footnote_1.default)());
26
26
  * @param mdContent Markdown 内容字符串
27
27
  * @returns 转换后的 HTML 字符串
28
28
  */
29
- const convertMarkdownToHtml = (path, lang, mdContent) => {
29
+ const convertMarkdownToHtml = (article, path, lang, mdContent) => {
30
+ const { headings } = article;
30
31
  const sourceFileMeta = metadata_1.MetaData.files.find(f => f.path === path);
31
32
  // 创建自定义渲染器
32
33
  const renderer = new marked_1.marked.Renderer();
@@ -87,6 +88,25 @@ const convertMarkdownToHtml = (path, lang, mdContent) => {
87
88
  const imagePath = (0, path_1.join)((0, path_1.dirname)(path), image.href);
88
89
  return `<img src="${(0, path_1.join)('..', '__raw__', imagePath)}" alt="${image.text}" />`;
89
90
  };
91
+ renderer.heading = function (heading) {
92
+ // 添加 id 属性以支持锚点链接
93
+ const id = (function () {
94
+ // 生成唯一的 ID,避免重复
95
+ for (let i = 0;; i++) {
96
+ const potentialId = i === 0 ? heading.text : `${heading.text}-${i}`;
97
+ if (!headings.find(h => h.id === potentialId)) {
98
+ return potentialId;
99
+ }
100
+ }
101
+ })();
102
+ headings.push({
103
+ id,
104
+ text: heading.text,
105
+ depth: heading.depth,
106
+ });
107
+ // TODO: 处理重复的标题文本以避免重复的 id
108
+ return `<h${heading.depth} id="${id}">${heading.text}</h${heading.depth}>`;
109
+ };
90
110
  // 重写代码块渲染器以支持 Mermaid - 使用 any 类型绕过类型检查
91
111
  renderer.code = function (code, language, isEscaped) {
92
112
  // 在 marked 17+ 中,code 参数是一个对象,包含 text 和 lang 属性
@@ -137,18 +157,12 @@ const convertMarkdownToHtml = (path, lang, mdContent) => {
137
157
  xhtml: false,
138
158
  async: false, // 强制同步模式
139
159
  });
140
- // 如果结果是 Promise,等待它(虽然我们设置了 async: false)
141
- if (result && typeof result.then === 'function') {
142
- // 这不应该发生,但如果发生了,返回一个占位符
143
- console.warn('marked.parse returned a Promise despite async: false');
144
- return '<!-- Markdown conversion in progress -->';
145
- }
146
- return result;
160
+ article.body = result;
147
161
  }
148
162
  catch (error) {
149
163
  console.error('Error converting Markdown to HTML:', error);
150
164
  const errorMessage = error instanceof Error ? error.message : String(error);
151
- return `<div class="error">Error converting Markdown: ${errorMessage}</div>`;
165
+ article.body = `<div class="error">Error converting Markdown: ${errorMessage}</div>`;
152
166
  }
153
167
  };
154
168
  exports.convertMarkdownToHtml = convertMarkdownToHtml;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "czon",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "CZone - AI enhanced Markdown content engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",