hexo-theme-gnix 11.0.0 → 13.0.0

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/README.md CHANGED
@@ -60,5 +60,7 @@ Support multiple light and dark themes:
60
60
  - [ppoffice/hexo-theme-icarus: A simple, delicate, and modern theme for the static site generator Hexo.](https://github.com/ppoffice/hexo-theme-icarus)
61
61
  - [D0n9X1n/hexo-blog-encrypt: Yet, just another hexo plugin for security.](https://github.com/D0n9X1n/hexo-blog-encrypt)
62
62
  - [hexojs/hexo-generator-feed: Feed generator for Hexo.](https://github.com/hexojs/hexo-generator-feed)
63
+ - [hexojs/hexo-generator-sitemap: Sitemap generator for Hexo.](https://github.com/hexojs/hexo-generator-sitemap)
63
64
  - [hexojs/hexo-generator-tag: Tag generator for Hexo.](https://github.com/hexojs/hexo-generator-tag)
64
65
  - [hexojs/hexo-generator-archive: Archive generator for Hexo.](https://github.com/hexojs/hexo-generator-archive)
66
+ - [ebullient/markdown-it-obsidian-callouts: markdown-it plugin for GitHub and Obsidian callouts.](https://github.com/ebullient/markdown-it-obsidian-callouts?tab=Apache-2.0-1-ov-file)
@@ -13,8 +13,18 @@ const {
13
13
  trimSlashes,
14
14
  } = require("../util/i18n");
15
15
 
16
+ let cachedConfig = null;
17
+ let cachedHexo = null;
18
+
16
19
  function getConfig(hexo, locals = {}) {
17
- return Object.assign({}, hexo.config, hexo.config.theme_config, hexo.theme.config, locals.theme);
20
+ if (hexo !== cachedHexo || !cachedConfig) {
21
+ cachedHexo = hexo;
22
+ cachedConfig = Object.assign({}, hexo.config, hexo.config.theme_config, hexo.theme.config);
23
+ }
24
+ if (locals.theme) {
25
+ return Object.assign({}, cachedConfig, locals.theme);
26
+ }
27
+ return cachedConfig;
18
28
  }
19
29
 
20
30
  function getLocalizedPostParams(hexo, sourcePath) {
@@ -0,0 +1,210 @@
1
+ // Adapted from markdown-it-obsidian-callouts (Apache-2.0, (c) Erin Schnabel)
2
+ // https://github.com/ebullient/markdown-it-obsidian-callouts
3
+
4
+ const DEFAULT_ICONS = {
5
+ abstract: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clipboard-list"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg>',
6
+ bug: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bug"><path d="m8 2 1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg>',
7
+ danger: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>',
8
+ example: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-list"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></svg>',
9
+ failure: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',
10
+ info: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-info"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',
11
+ note: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-pencil"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>',
12
+ question: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-help-circle"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>',
13
+ quote: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-quote"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z"/></svg>',
14
+ success: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check"><path d="M20 6 9 17l-5-5"/></svg>',
15
+ tip: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-flame"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"/></svg>',
16
+ todo: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-circle-2"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',
17
+ warning: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-alert-triangle"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>',
18
+ };
19
+
20
+ DEFAULT_ICONS.attention = DEFAULT_ICONS.warning;
21
+ DEFAULT_ICONS.caution = DEFAULT_ICONS.warning;
22
+ DEFAULT_ICONS.check = DEFAULT_ICONS.success;
23
+ DEFAULT_ICONS.cite = DEFAULT_ICONS.quote;
24
+ DEFAULT_ICONS.done = DEFAULT_ICONS.success;
25
+ DEFAULT_ICONS.error = DEFAULT_ICONS.danger;
26
+ DEFAULT_ICONS.fail = DEFAULT_ICONS.failure;
27
+ DEFAULT_ICONS.faq = DEFAULT_ICONS.question;
28
+ DEFAULT_ICONS.help = DEFAULT_ICONS.question;
29
+ DEFAULT_ICONS.hint = DEFAULT_ICONS.tip;
30
+ DEFAULT_ICONS.important = DEFAULT_ICONS.tip;
31
+ DEFAULT_ICONS.missing = DEFAULT_ICONS.failure;
32
+ DEFAULT_ICONS.summary = DEFAULT_ICONS.abstract;
33
+ DEFAULT_ICONS.tldr = DEFAULT_ICONS.abstract;
34
+
35
+ const CALLOUT_RE = /^\[!([^\]]+)\](\+|-|) *(.*)? */;
36
+ const ADMONITION_RE = /^ad-([^\s]+) */;
37
+ const ADMONITION_HEADER_RE = /^(title|collapse|icon|color):(.*)/;
38
+ const HEADER_TO_ATTR = {
39
+ title: "data-callout-title",
40
+ icon: "data-callout-icon",
41
+ color: "data-callout-color",
42
+ };
43
+
44
+ function resolveIcon(token, options) {
45
+ const explicit = token.attrGet("data-callout-icon");
46
+ if (explicit) return explicit.trim();
47
+ const type = token.attrGet("data-callout");
48
+ if (!type) return "";
49
+ return options.icons?.[type] || DEFAULT_ICONS[type] || DEFAULT_ICONS.note;
50
+ }
51
+
52
+ function toTitleCase(str) {
53
+ return str
54
+ .split(" ")
55
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
56
+ .join(" ");
57
+ }
58
+
59
+ async function resolveTitle(token, md) {
60
+ const title = token.attrGet("data-callout-title");
61
+ if (title) return md.renderInlineAsync(title.trim());
62
+ const type = token.attrGet("data-callout");
63
+ return type ? toTitleCase(type) : "";
64
+ }
65
+
66
+ function escapeAttr(str) {
67
+ return String(str).replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
68
+ }
69
+
70
+ function colorStyle(token) {
71
+ const color = token.attrGet("data-callout-color");
72
+ return color ? ` style="--callout-color: ${escapeAttr(color)}"` : "";
73
+ }
74
+
75
+ async function renderCalloutPrefix(token, md, options) {
76
+ const type = token.attrGet("data-callout");
77
+ if (!type) return "";
78
+ const fold = token.attrGet("data-callout-fold");
79
+ const icon = resolveIcon(token, options);
80
+ const title = await resolveTitle(token, md);
81
+ const style = colorStyle(token);
82
+
83
+ if (fold) {
84
+ return `
85
+ <details class="callout" data-callout="${type}" data-callout-fold="${fold}"${fold === "+" ? " open" : ""}${style}>
86
+ <summary class="callout-title">
87
+ <div class="callout-title-icon">
88
+ ${icon}
89
+ </div>
90
+ <div class="callout-title-inner">${title}</div>
91
+ <div class="callout-fold"></div>
92
+ </summary>
93
+ <div class="callout-content">`;
94
+ }
95
+
96
+ return `
97
+ <div class="callout" data-callout="${type}"${style}>
98
+ <div class="callout-title">
99
+ <div class="callout-title-icon">
100
+ ${icon}
101
+ </div>
102
+ <div class="callout-title-inner">${title}</div>
103
+ </div>
104
+ <div class="callout-content">`;
105
+ }
106
+
107
+ function renderCalloutPostfix(token) {
108
+ const type = token.attrGet("data-callout");
109
+ if (!type) return "";
110
+ const fold = token.attrGet("data-callout-fold");
111
+ return fold ? "</div></details>" : "</div></div>";
112
+ }
113
+
114
+ function inspectBlockquote(tokens, startIdx) {
115
+ let content = "";
116
+ let depth = 0;
117
+ let endIdx = startIdx;
118
+ let contentIdx = startIdx;
119
+
120
+ for (let i = startIdx; i < tokens.length; i++) {
121
+ const token = tokens[i];
122
+
123
+ if (token.type === "blockquote_open") depth++;
124
+ else if (token.type === "blockquote_close") {
125
+ endIdx = i;
126
+ depth--;
127
+ }
128
+
129
+ if (depth === 0) break;
130
+ if (depth > 1) continue;
131
+
132
+ if (token.type === "inline") {
133
+ if (contentIdx === startIdx && token.content.match(CALLOUT_RE)) {
134
+ contentIdx = i;
135
+ }
136
+ content += token.content;
137
+ } else if (token.type === "paragraph_close") {
138
+ content += "\n";
139
+ }
140
+ }
141
+
142
+ const match = content.match(CALLOUT_RE);
143
+ if (!match || startIdx === endIdx) return;
144
+
145
+ const type = match[1].toLowerCase();
146
+ const fold = match[2];
147
+ const title = match[3];
148
+
149
+ tokens[startIdx].type = "callout_open";
150
+ tokens[startIdx].attrPush(["class", "callout"]);
151
+ tokens[startIdx].attrPush(["data-callout", type]);
152
+ tokens[startIdx].attrPush(["data-callout-fold", fold]);
153
+ if (title) tokens[startIdx].attrPush(["data-callout-title", title]);
154
+
155
+ tokens[endIdx].type = "callout_close";
156
+ tokens[endIdx].attrPush(["data-callout", type]);
157
+ tokens[endIdx].attrPush(["data-callout-fold", fold]);
158
+
159
+ if (contentIdx !== startIdx && tokens[contentIdx]?.children) {
160
+ tokens[contentIdx].content = tokens[contentIdx].content.replace(CALLOUT_RE, "").trim();
161
+ }
162
+ }
163
+
164
+ function inspectFence(tokens, startIdx, options) {
165
+ const token = tokens[startIdx];
166
+ if (!token.info) return;
167
+
168
+ const match = token.info.replace(options.langPrefix || "", "").match(ADMONITION_RE);
169
+ if (!match) return;
170
+
171
+ token.type = "admonition_block";
172
+ token.attrPush(["class", "callout"]);
173
+ token.attrPush(["data-callout", match[1].toLowerCase()]);
174
+
175
+ let lines = token.content.split("\n");
176
+ while (lines.length > 0 && ADMONITION_HEADER_RE.test(lines[0])) {
177
+ const headerMatch = lines[0].match(ADMONITION_HEADER_RE);
178
+ if (!headerMatch) break;
179
+ const attrName = HEADER_TO_ATTR[headerMatch[1].trim().toLowerCase()];
180
+ if (attrName) token.attrPush([attrName, headerMatch[2].trim()]);
181
+ lines = lines.slice(1);
182
+ }
183
+
184
+ token.content = lines.join("\n");
185
+ }
186
+
187
+ function obsidianCallouts(md, options = {}) {
188
+ md.core.ruler.after("block", "obsidian-callouts", (state) => {
189
+ const tokens = state.tokens;
190
+ for (let i = 0; i < tokens.length; i++) {
191
+ const token = tokens[i];
192
+ if (token.type === "blockquote_open") inspectBlockquote(tokens, i);
193
+ if (token.type === "fence") inspectFence(tokens, i, options);
194
+ }
195
+ });
196
+
197
+ md.renderer.rules.callout_open = async (tokens, idx) => renderCalloutPrefix(tokens[idx], md, options);
198
+
199
+ md.renderer.rules.admonition_block = async (tokens, idx) => {
200
+ const token = tokens[idx];
201
+ const prefix = await renderCalloutPrefix(token, md, options);
202
+ const body = await md.renderAsync(token.content);
203
+ return `${prefix}${body}\n</div>\n</div>`;
204
+ };
205
+
206
+ md.renderer.rules.callout_close = (tokens, idx) => renderCalloutPostfix(tokens[idx]);
207
+ }
208
+
209
+ module.exports = obsidianCallouts;
210
+ module.exports.DEFAULT_ICONS = DEFAULT_ICONS;
@@ -1,22 +1,211 @@
1
1
  const path = require("node:path");
2
- const { tab } = require("@mdit/plugin-tab");
3
2
  const { createMarkdownExit } = require("markdown-exit");
4
3
  const mermaidDiagram = require("markdown-exit-mermaid");
5
4
  const ratex = require("markdown-exit-ratex");
6
- const code = require("markdown-exit-shiki");
7
- const abbr = require("markdown-it-abbr");
5
+ const code = require("./shiki");
6
+ const obsidianCallouts = require("./obsidian-callouts");
8
7
  const anchor = require("markdown-it-anchor");
9
8
  const footnote = require("markdown-it-footnote");
10
- const ins = require("markdown-it-ins");
11
9
  const mark = require("markdown-it-mark");
12
- const sub = require("markdown-it-sub");
13
- const sup = require("markdown-it-sup");
14
10
  const taskLists = require("markdown-it-task-lists");
15
11
 
16
12
  function resolveDefault(module) {
17
13
  return module && typeof module === "object" && "default" in module ? module.default : module;
18
14
  }
19
15
 
16
+ function wrapMarkdownItTable(md, options = {}) {
17
+ const { figureClass = "table-wrapper", tableClass = "" } = options;
18
+
19
+ const defaultTableOpen = md.renderer.rules.table_open || ((tokens, idx, opts, _env, self) => self.renderToken(tokens, idx, opts));
20
+
21
+ const defaultTableClose = md.renderer.rules.table_close || ((tokens, idx, opts, _env, self) => self.renderToken(tokens, idx, opts));
22
+
23
+ md.renderer.rules.table_open = (tokens, idx, opts, env, self) => {
24
+ if (tableClass) {
25
+ tokens[idx].attrJoin("class", tableClass);
26
+ }
27
+
28
+ return `<figure class="${figureClass}">\n${defaultTableOpen(tokens, idx, opts, env, self)}`;
29
+ };
30
+
31
+ md.renderer.rules.table_close = (tokens, idx, opts, env, self) => {
32
+ return `${defaultTableClose(tokens, idx, opts, env, self)}\n</figure>`;
33
+ };
34
+
35
+ return md;
36
+ }
37
+
38
+ function parseTabsMarker(state, line, name) {
39
+ let pos = state.bMarks[line] + state.tShift[line];
40
+ const max = state.eMarks[line];
41
+
42
+ if (state.src.charCodeAt(pos) !== 0x3a /* : */) return false;
43
+
44
+ let markerCount = 0;
45
+ while (pos + markerCount < max && state.src.charCodeAt(pos + markerCount) === 0x3a) markerCount++;
46
+ if (markerCount < 3) return false;
47
+
48
+ pos = state.skipSpaces(pos + markerCount);
49
+ if (state.src.slice(pos, pos + name.length) !== name) return false;
50
+
51
+ pos += name.length;
52
+ if (pos < max && !state.md.utils.isSpace(state.src.charCodeAt(pos))) return false;
53
+
54
+ pos = state.skipSpaces(pos);
55
+ const id = pos < max && state.src.charCodeAt(pos) === 0x23 /* # */ ? state.src.slice(state.skipSpaces(pos + 1), max).trim() : "";
56
+
57
+ return { marker: ":".repeat(markerCount), id };
58
+ }
59
+
60
+ function parseTabMarker(state, line) {
61
+ let pos = state.bMarks[line] + state.tShift[line];
62
+ const max = state.eMarks[line];
63
+ const marker = "@tab";
64
+ const activeMarker = "@tab:active";
65
+
66
+ if (state.src.charCodeAt(pos) !== 0x40 /* @ */) return false;
67
+
68
+ let active = false;
69
+ if (state.src.slice(pos, pos + activeMarker.length) === activeMarker) {
70
+ active = true;
71
+ pos += activeMarker.length;
72
+ } else if (state.src.slice(pos, pos + marker.length) === marker) {
73
+ pos += marker.length;
74
+ } else {
75
+ return false;
76
+ }
77
+
78
+ const titleStart = state.skipSpaces(pos);
79
+ if (titleStart === pos || titleStart >= max) return false;
80
+
81
+ const rawTitle = state.src.slice(titleStart, max).trim();
82
+ const match = /^(.*?)(?:\s+#([A-Za-z0-9_-]+))?$/.exec(rawTitle);
83
+ const title = (match?.[1] || rawTitle).trim();
84
+ const id = match?.[2] || "";
85
+
86
+ return { active, title, id };
87
+ }
88
+
89
+ function customTabs(md, options = {}) {
90
+ const name = options.name || "tabs";
91
+
92
+ md.block.ruler.before(
93
+ "fence",
94
+ `${name}_container`,
95
+ (state, startLine, endLine, silent) => {
96
+ const marker = parseTabsMarker(state, startLine, name);
97
+ if (!marker) return false;
98
+ if (silent) return true;
99
+
100
+ const startIndent = state.sCount[startLine];
101
+ let nextLine = startLine + 1;
102
+ let autoClosed = false;
103
+
104
+ for (; nextLine < endLine; nextLine++) {
105
+ const pos = state.bMarks[nextLine] + state.tShift[nextLine];
106
+ const max = state.eMarks[nextLine];
107
+
108
+ if (state.sCount[nextLine] < startIndent) break;
109
+ if (state.sCount[nextLine] === startIndent && state.src.charCodeAt(pos) === 0x3a /* : */) {
110
+ let closePos = pos;
111
+ while (closePos < max && state.src.charCodeAt(closePos) === 0x3a) closePos++;
112
+ if (closePos - pos >= marker.marker.length && state.skipSpaces(closePos) >= max) {
113
+ autoClosed = true;
114
+ break;
115
+ }
116
+ }
117
+ }
118
+
119
+ const oldParent = state.parentType;
120
+ const oldLineMax = state.lineMax;
121
+ const oldBlkIndent = state.blkIndent;
122
+ const oldInTabs = state.env.__gnixInTabs;
123
+
124
+ const open = state.push("gnix_tabs_open", "", 1);
125
+ open.block = true;
126
+ open.markup = marker.marker;
127
+ open.meta = { id: marker.id };
128
+ open.map = [startLine, nextLine];
129
+
130
+ state.parentType = `${name}_container`;
131
+ state.lineMax = nextLine;
132
+ state.blkIndent = startIndent;
133
+ state.env.__gnixInTabs = true;
134
+ state.md.block.tokenize(state, startLine + 1, nextLine);
135
+ state.env.__gnixInTabs = oldInTabs;
136
+ state.parentType = oldParent;
137
+ state.lineMax = oldLineMax;
138
+ state.blkIndent = oldBlkIndent;
139
+
140
+ const close = state.push("gnix_tabs_close", "", -1);
141
+ close.block = true;
142
+ close.markup = marker.marker;
143
+
144
+ state.line = nextLine + (autoClosed ? 1 : 0);
145
+ return true;
146
+ },
147
+ { alt: ["paragraph", "reference", "blockquote", "list"] },
148
+ );
149
+
150
+ md.block.ruler.before(
151
+ "paragraph",
152
+ `${name}_tab`,
153
+ (state, startLine, endLine, silent) => {
154
+ if (!state.env.__gnixInTabs) return false;
155
+
156
+ const marker = parseTabMarker(state, startLine);
157
+ if (!marker) return false;
158
+ if (silent) return true;
159
+
160
+ const startIndent = state.sCount[startLine];
161
+ let nextLine = startLine + 1;
162
+
163
+ for (; nextLine < endLine; nextLine++) {
164
+ const pos = state.bMarks[nextLine] + state.tShift[nextLine];
165
+ if (state.sCount[nextLine] === startIndent && state.src.charCodeAt(pos) === 0x40 /* @ */ && parseTabMarker(state, nextLine)) break;
166
+ }
167
+
168
+ const oldParent = state.parentType;
169
+ const oldLineMax = state.lineMax;
170
+ const oldBlkIndent = state.blkIndent;
171
+
172
+ const open = state.push("gnix_tab_open", "", 1);
173
+ open.block = true;
174
+ open.markup = "@tab";
175
+ open.meta = marker;
176
+ open.map = [startLine, nextLine];
177
+
178
+ state.parentType = "tab";
179
+ state.lineMax = nextLine;
180
+ state.blkIndent = startIndent;
181
+ state.md.block.tokenize(state, startLine + 1, nextLine);
182
+ state.parentType = oldParent;
183
+ state.lineMax = oldLineMax;
184
+ state.blkIndent = oldBlkIndent;
185
+
186
+ const close = state.push("gnix_tab_close", "", -1);
187
+ close.block = true;
188
+
189
+ state.line = nextLine;
190
+ return true;
191
+ },
192
+ { alt: ["paragraph", "reference", "blockquote", "list"] },
193
+ );
194
+
195
+ md.renderer.rules.gnix_tabs_open = (tokens, idx) => {
196
+ const { id } = tokens[idx].meta || {};
197
+ return `<x-tabs${id ? ` group-id="${md.utils.escapeHtml(id)}"` : ""}>\n`;
198
+ };
199
+ md.renderer.rules.gnix_tabs_close = () => "</x-tabs>\n";
200
+ md.renderer.rules.gnix_tab_open = (tokens, idx) => {
201
+ const { title = "Tab", id = "", active = false } = tokens[idx].meta || {};
202
+ return `<x-tab title="${md.utils.escapeHtml(title)}"${id ? ` sync-id="${md.utils.escapeHtml(id)}"` : ""}${active ? " active" : ""}>\n`;
203
+ };
204
+ md.renderer.rules.gnix_tab_close = () => "</x-tab>\n";
205
+
206
+ return md;
207
+ }
208
+
20
209
  class MarkdownRenderer {
21
210
  constructor(hexo) {
22
211
  this.hexo = hexo;
@@ -30,11 +219,7 @@ class MarkdownRenderer {
30
219
  typographer: true,
31
220
  xhtmlOut: false,
32
221
  },
33
- code_options: {
34
- themes: {
35
- light: "catppuccin-latte",
36
- },
37
- },
222
+
38
223
  mermaid_options: {
39
224
  theme: "default",
40
225
  },
@@ -51,15 +236,13 @@ class MarkdownRenderer {
51
236
  this.md
52
237
  .use(resolveDefault(footnote))
53
238
  .use(resolveDefault(mark))
54
- .use(resolveDefault(sub))
55
- .use(resolveDefault(sup))
56
- .use(resolveDefault(abbr))
57
- .use(resolveDefault(ins))
58
239
  .use(resolveDefault(taskLists))
59
240
  .use(resolveDefault(code), this.config.code_options)
60
241
  .use(resolveDefault(mermaidDiagram), this.config.mermaid_options)
61
242
  .use(resolveDefault(ratex), this.config.ratex_options)
62
- .use(tab)
243
+ .use(obsidianCallouts, this.config.callout_options)
244
+ .use(customTabs)
245
+ .use(wrapMarkdownItTable)
63
246
  .use(resolveDefault(anchor), {
64
247
  permalink: resolveDefault(anchor).permalink.headerLink(),
65
248
  });