@sugarat/theme 0.1.28 → 0.1.29

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/node.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DefaultTheme, UserConfig } from 'vitepress';
2
2
  import { ElButton } from 'element-plus';
3
+ export { tabsMarkdownPlugin } from 'vitepress-plugin-tabs';
3
4
 
4
5
  declare namespace BlogPopover {
5
6
  interface Title {
@@ -180,6 +181,11 @@ declare namespace Theme {
180
181
  popover?: Popover;
181
182
  friend?: FriendLink[];
182
183
  authorList?: Omit<FriendLink, 'avatar'>[];
184
+ /**
185
+ * 启用 [vitepress-plugin-tabs](https://www.npmjs.com/package/vitepress-plugin-tabs)
186
+ * @default false
187
+ */
188
+ tabs: boolean;
183
189
  }
184
190
  interface Config extends DefaultTheme.Config {
185
191
  blog?: BlogConfig;
package/node.js CHANGED
@@ -31,7 +31,8 @@ __export(node_exports, {
31
31
  getDefaultTitle: () => getDefaultTitle,
32
32
  getFileBirthTime: () => getFileBirthTime,
33
33
  getGitTimestamp: () => getGitTimestamp,
34
- getThemeConfig: () => getThemeConfig
34
+ getThemeConfig: () => getThemeConfig,
35
+ tabsMarkdownPlugin: () => tabsPlugin
35
36
  });
36
37
  module.exports = __toCommonJS(node_exports);
37
38
  var import_fast_glob = __toESM(require("fast-glob"));
@@ -40,6 +41,170 @@ var import_fs = __toESM(require("fs"));
40
41
  var import_child_process = require("child_process");
41
42
  var import_path = __toESM(require("path"));
42
43
 
44
+ // ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-alpha.75_vue@3.2.45/node_modules/vitepress-plugin-tabs/dist/index.js
45
+ var tabsMarker = "=tabs";
46
+ var tabsMarkerLen = tabsMarker.length;
47
+ var ruleBlockTabs = (state, startLine, endLine, silent) => {
48
+ if (state.sCount[startLine] - state.blkIndent >= 4) {
49
+ return false;
50
+ }
51
+ let pos = state.bMarks[startLine] + state.tShift[startLine];
52
+ let max = state.eMarks[startLine];
53
+ if (pos + 3 > max) {
54
+ return false;
55
+ }
56
+ const marker = state.src.charCodeAt(pos);
57
+ if (marker !== 58) {
58
+ return false;
59
+ }
60
+ const mem = pos;
61
+ pos = state.skipChars(pos, marker);
62
+ let len = pos - mem;
63
+ if (len < 3) {
64
+ return false;
65
+ }
66
+ if (state.src.slice(pos, pos + tabsMarkerLen) !== tabsMarker) {
67
+ return false;
68
+ }
69
+ pos += tabsMarkerLen;
70
+ if (silent) {
71
+ return true;
72
+ }
73
+ const markup = state.src.slice(mem, pos);
74
+ const params = state.src.slice(pos, max);
75
+ let nextLine = startLine;
76
+ let haveEndMarker = false;
77
+ for (; ; ) {
78
+ nextLine++;
79
+ if (nextLine >= endLine) {
80
+ break;
81
+ }
82
+ pos = state.bMarks[nextLine] + state.tShift[nextLine];
83
+ const mem2 = pos;
84
+ max = state.eMarks[nextLine];
85
+ if (pos < max && state.sCount[nextLine] < state.blkIndent) {
86
+ break;
87
+ }
88
+ if (state.src.charCodeAt(pos) !== marker) {
89
+ continue;
90
+ }
91
+ if (state.sCount[nextLine] - state.blkIndent >= 4) {
92
+ continue;
93
+ }
94
+ pos = state.skipChars(pos, marker);
95
+ if (pos - mem2 < len) {
96
+ continue;
97
+ }
98
+ pos = state.skipSpaces(pos);
99
+ if (pos < max) {
100
+ continue;
101
+ }
102
+ haveEndMarker = true;
103
+ break;
104
+ }
105
+ len = state.sCount[startLine];
106
+ state.line = nextLine + (haveEndMarker ? 1 : 0);
107
+ const token = state.push("tabs", "div", 0);
108
+ token.info = params;
109
+ token.content = state.getLines(startLine + 1, nextLine, len, true);
110
+ token.markup = markup;
111
+ token.map = [startLine, state.line];
112
+ return true;
113
+ };
114
+ var tabBreakRE = /^\s*::(.+)$/;
115
+ var forbiddenCharsInSlotNames = /[ '"]/;
116
+ var parseTabBreakLine = (line) => {
117
+ const m = line.match(tabBreakRE);
118
+ if (!m)
119
+ return null;
120
+ const trimmed = m[1].trim();
121
+ if (forbiddenCharsInSlotNames.test(trimmed)) {
122
+ throw new Error(
123
+ `contains forbidden chars in slot names (space and quotes) (${JSON.stringify(
124
+ line
125
+ )})`
126
+ );
127
+ }
128
+ return trimmed;
129
+ };
130
+ var lastLineBreakRE = /\n$/;
131
+ var parseTabsContent = (content) => {
132
+ const lines = content.replace(lastLineBreakRE, "").split("\n");
133
+ const tabInfos = [];
134
+ const tabLabels = /* @__PURE__ */ new Set();
135
+ let currentTab = null;
136
+ const createTabInfo = (label) => {
137
+ if (tabLabels.has(label)) {
138
+ throw new Error(`a tab labelled ${JSON.stringify(label)} already exists`);
139
+ }
140
+ const newTab = { label, content: [] };
141
+ tabInfos.push(newTab);
142
+ tabLabels.add(label);
143
+ return newTab;
144
+ };
145
+ for (const line of lines) {
146
+ const tabLabel = parseTabBreakLine(line);
147
+ if (currentTab === null) {
148
+ if (tabLabel === null) {
149
+ throw new Error(
150
+ `tabs should start with \`::\${tabLabel}\` (e.g. "::foo"). (received: ${JSON.stringify(
151
+ line
152
+ )})`
153
+ );
154
+ }
155
+ currentTab = createTabInfo(tabLabel);
156
+ continue;
157
+ }
158
+ if (tabLabel === null) {
159
+ currentTab.content.push(line);
160
+ } else {
161
+ currentTab = createTabInfo(tabLabel);
162
+ }
163
+ }
164
+ if (tabInfos.length < 0) {
165
+ throw new Error("tabs should include at least one tab");
166
+ }
167
+ return tabInfos.map((info) => ({
168
+ label: info.label,
169
+ content: info.content.join("\n").replace(lastLineBreakRE, "")
170
+ }));
171
+ };
172
+ var parseParams = (input) => {
173
+ if (!input.startsWith("=")) {
174
+ return {
175
+ shareStateKey: void 0
176
+ };
177
+ }
178
+ const splitted = input.split("=");
179
+ return {
180
+ shareStateKey: splitted[1]
181
+ };
182
+ };
183
+ var tabsPlugin = (md) => {
184
+ md.block.ruler.before("fence", "=tabs", ruleBlockTabs, {
185
+ alt: ["paragraph", "reference", "blockquote", "list"]
186
+ });
187
+ md.renderer.rules.tabs = (tokens, index, _options, env) => {
188
+ const token = tokens[index];
189
+ const tabs = parseTabsContent(token.content);
190
+ const renderedTabs = tabs.map((tab) => ({
191
+ label: tab.label,
192
+ content: md.render(tab.content, env)
193
+ }));
194
+ const params = parseParams(token.info);
195
+ const tabLabelsProp = `:tabLabels="${md.utils.escapeHtml(
196
+ JSON.stringify(tabs.map((tab) => tab.label))
197
+ )}"`;
198
+ const shareStateKeyProp = params.shareStateKey ? `sharedStateKey="${md.utils.escapeHtml(params.shareStateKey)}"` : "";
199
+ const slots = renderedTabs.map(
200
+ (tab) => `<template #${tab.label}>${tab.content}</template>`
201
+ );
202
+ return `<PluginTabs ${tabLabelsProp} ${shareStateKeyProp}>${slots.join(
203
+ ""
204
+ )}</PluginTabs>`;
205
+ };
206
+ };
207
+
43
208
  // src/utils/index.ts
44
209
  function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") {
45
210
  if (!(d instanceof Date)) {
@@ -174,6 +339,13 @@ function getThemeConfig(cfg) {
174
339
  ]
175
340
  };
176
341
  }
342
+ if (cfg?.tabs) {
343
+ extraConfig.markdown = {
344
+ config(md) {
345
+ tabsPlugin(md);
346
+ }
347
+ };
348
+ }
177
349
  return {
178
350
  themeConfig: {
179
351
  blog: {
@@ -195,7 +367,7 @@ function getThemeConfig(cfg) {
195
367
  function getDefaultTitle(content) {
196
368
  const title = clearMatterContent(content).split("\n")?.find((str) => {
197
369
  return str.startsWith("# ");
198
- })?.slice(2).replace(/[\s]/g, "") || "";
370
+ })?.slice(2).replace(/^\s+|\s+$/g, "") || "";
199
371
  return title;
200
372
  }
201
373
  function clearMatterContent(content) {
@@ -266,5 +438,6 @@ function defineConfig(config) {
266
438
  getDefaultTitle,
267
439
  getFileBirthTime,
268
440
  getGitTimestamp,
269
- getThemeConfig
441
+ getThemeConfig,
442
+ tabsMarkdownPlugin
270
443
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -47,7 +47,8 @@
47
47
  "tsup": " ^6.5.0",
48
48
  "typescript": "^4.8.2",
49
49
  "vitepress": "1.0.0-alpha.75",
50
- "vue": "^3.2.45"
50
+ "vue": "^3.2.45",
51
+ "vitepress-plugin-tabs": "^0.2.0"
51
52
  },
52
53
  "scripts": {
53
54
  "dev": "npm run build:node && npm run dev:docs",
@@ -196,6 +196,11 @@ export namespace Theme {
196
196
  popover?: Popover
197
197
  friend?: FriendLink[]
198
198
  authorList?: Omit<FriendLink, 'avatar'>[]
199
+ /**
200
+ * 启用 [vitepress-plugin-tabs](https://www.npmjs.com/package/vitepress-plugin-tabs)
201
+ * @default false
202
+ */
203
+ tabs: boolean
199
204
  }
200
205
 
201
206
  export interface Config extends DefaultTheme.Config {
package/src/node.ts CHANGED
@@ -5,6 +5,7 @@ import fs from 'fs'
5
5
  import { execSync, spawn, spawnSync } from 'child_process'
6
6
  import path from 'path'
7
7
  import type { SiteConfig, UserConfig } from 'vitepress'
8
+ import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
8
9
  import { formatDate } from './utils/index'
9
10
  import type { Theme } from './composables/config/index'
10
11
 
@@ -161,6 +162,13 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
161
162
  ]
162
163
  }
163
164
  }
165
+ if (cfg?.tabs) {
166
+ extraConfig.markdown = {
167
+ config(md: any) {
168
+ tabsMarkdownPlugin(md)
169
+ }
170
+ }
171
+ }
164
172
  return {
165
173
  themeConfig: {
166
174
  blog: {
@@ -190,7 +198,7 @@ export function getDefaultTitle(content: string) {
190
198
  return str.startsWith('# ')
191
199
  })
192
200
  ?.slice(2)
193
- .replace(/[\s]/g, '') || ''
201
+ .replace(/^\s+|\s+$/g, '') || ''
194
202
  return title
195
203
  }
196
204
 
@@ -295,3 +303,5 @@ export function defineConfig(config: UserConfig<Theme.Config>) {
295
303
  }
296
304
  return config
297
305
  }
306
+
307
+ export { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'