@xingwangzhe/stalux 1.7.9 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.7.9",
3
+ "version": "1.9.0",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -25,6 +25,7 @@
25
25
  "files": [
26
26
  "src/index.ts",
27
27
  "src/config.ts",
28
+ "src/expressive-code.ts",
28
29
  "src/components/**/*.astro",
29
30
  "src/components/**/*.ts",
30
31
  "src/layouts/**/*.astro",
@@ -45,6 +46,7 @@
45
46
  "exports": {
46
47
  ".": "./src/index.ts",
47
48
  "./config": "./src/config.ts",
49
+ "./expressive-code": "./src/expressive-code.ts",
48
50
  "./schemas": "./src/schemas/config.ts",
49
51
  "./schemas/collections": "./src/schemas/collections.ts",
50
52
  "./components/*": "./src/components/*",
@@ -59,9 +59,9 @@ const mdSourceUrl = exportMd
59
59
  )
60
60
  }
61
61
  </div>
62
- {
63
- <div class={style.pageStats}>
64
- {(props.readingTime || props.readingMinutes) && (
62
+ {
63
+ <div class={style.pageStats}>
64
+ {(Boolean(props.readingTime) || (props.readingMinutes ?? 0) > 0) && (
65
65
  <span class={style.readingTime}>
66
66
  {t("post.readingTime")}{props.readingMinutes && props.readingMinutes > 0
67
67
  ? (props.readingMinutes < 1
@@ -70,7 +70,7 @@ const mdSourceUrl = exportMd
70
70
  : props.readingTime}
71
71
  </span>
72
72
  )}
73
- {props.wordCount && props.wordCount > 0 && (
73
+ {(props.wordCount ?? 0) > 0 && (
74
74
  <span class={style.wordCount}>
75
75
  {t("post.wordCount")}{props.wordCount}
76
76
  </span>
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Stalux 封装的 Expressive Code 集成 —— 默认启用代码块行号。
3
+ *
4
+ * 插件模式下直接从包导入,无需单独安装 @expressive-code/plugin-line-numbers:
5
+ * ```js
6
+ * import { expressiveCode } from "@xingwangzhe/stalux";
7
+ *
8
+ * export default defineConfig({
9
+ * integrations: [stalux({ contentDir: "stalux" }), expressiveCode({ themes: [...] })],
10
+ * });
11
+ * ```
12
+ *
13
+ * 行号插件是 Expressive Code 引擎级插件(必须通过 expressiveCode() 的 plugins 选项传入,
14
+ * 无法由 stalux 集成自动注入),因此这里把 pluginLineNumbers 与用户配置合并,
15
+ * 让行号成为默认行为。
16
+ */
17
+ import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";
18
+ import expressiveCodeBase from "astro-expressive-code";
19
+
20
+ type ExpressiveCodeOptions = NonNullable<Parameters<typeof expressiveCodeBase>[0]>;
21
+
22
+ /**
23
+ * 创建带默认行号插件的 Expressive Code 集成。
24
+ * @param options - 透传 astro-expressive-code 的选项;用户传入的 plugins 会追加在行号插件之后
25
+ */
26
+ export function expressiveCode(options: ExpressiveCodeOptions = {}) {
27
+ const plugins = [pluginLineNumbers(), ...(options.plugins ?? [])];
28
+ return expressiveCodeBase({ ...options, plugins });
29
+ }
30
+
31
+ export default expressiveCode;
package/src/index.ts CHANGED
@@ -21,6 +21,8 @@ import { createIndex as pagefindCreateIndex } from "pagefind";
21
21
  import type { StaluxOptions } from "./config";
22
22
  import { staluxComponentsAlias } from "./internal/components-plugin";
23
23
  import { runFontSubsetting } from "./internal/font-subset";
24
+ import { featureFlagsHast, featureFlagsMdast } from "./plugins/feature-flags";
25
+ import { temml } from "./plugins/satteri-temml";
24
26
 
25
27
  // ---------------------------------------------------------------------------
26
28
  // 页面条目定义
@@ -191,7 +193,43 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration {
191
193
 
192
194
  logger.info(`Stalux initialized (contentDir: ${opt.contentDir})`);
193
195
 
194
- // 5. 站点 URL 单源化:以 stalux/config/site.yml 的 url 为准
196
+ // 5. 注入 satteri 插件(字数统计/特性标记/数学公式),按插件 name 去重
197
+ // 源码模式下 astro.config 会显式注册同款插件,插件模式则由集成补齐,
198
+ // 保证两种模式行为一致(wordCount/readingMinutes/hasImage 由构建期插件写入)。
199
+ // 去重是必须的:重复注册 featureFlagsMdast 会导致字数统计翻倍。
200
+ try {
201
+ const processor = (config.markdown?.processor ?? undefined) as
202
+ | { name?: string; options?: { mdastPlugins?: any[]; hastPlugins?: any[] } }
203
+ | undefined;
204
+ if (processor?.name === "satteri") {
205
+ const mdastPlugins = processor.options?.mdastPlugins ?? [];
206
+ const hastPlugins = processor.options?.hastPlugins ?? [];
207
+ const seen = new Set<string>();
208
+ for (const p of [...mdastPlugins, ...hastPlugins]) {
209
+ if (p?.name) seen.add(p.name);
210
+ }
211
+ const pushUnique = (list: any[], plugin: any) => {
212
+ if (plugin?.name) {
213
+ if (seen.has(plugin.name)) return;
214
+ seen.add(plugin.name);
215
+ }
216
+ list.push(plugin);
217
+ };
218
+ pushUnique(mdastPlugins, temml());
219
+ pushUnique(mdastPlugins, featureFlagsMdast);
220
+ pushUnique(hastPlugins, featureFlagsHast);
221
+ logger.debug("Stalux: injected satteri plugins (temml/feature-flags)");
222
+ } else {
223
+ logger.warn(
224
+ "Stalux: markdown.processor 不是 satteri,无法注入字数统计/数学公式插件。" +
225
+ "请在 astro.config 中配置 `processor: satteri({...})`。",
226
+ );
227
+ }
228
+ } catch (error) {
229
+ logger.warn(`Stalux: 注入 markdown 插件失败: ${String(error)}`);
230
+ }
231
+
232
+ // 6. 站点 URL 单源化:以 stalux/config/site.yml 的 url 为准
195
233
  // sitemap 与 context.site 都派生自 astro.config 的 site 字段,
196
234
  // 这里在构建前将其与主题配置对齐,避免输出与配置不一致的 URL
197
235
  // (例如 README 里的 https://example.com 占位、或用户只改了 site.yml 忘了改 astro.config)。
@@ -229,7 +267,7 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration {
229
267
  logger.debug("Stalux: site.yml not found, skip site sync");
230
268
  }
231
269
 
232
- // 6. 字体裁剪(在 config:setup 阶段执行,保证 dev/build 都能生成)
270
+ // 7. 字体裁剪(在 config:setup 阶段执行,保证 dev/build 都能生成)
233
271
  try {
234
272
  const projectRoot = process.cwd();
235
273
  await runFontSubsetting(projectRoot, logger, true);
@@ -239,7 +277,7 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration {
239
277
  },
240
278
 
241
279
  "astro:build:start": async ({ logger }) => {
242
- // 7. 字体裁剪(构建时,生成全部路由子集)
280
+ // 8. 字体裁剪(构建时,生成全部路由子集)
243
281
  try {
244
282
  const projectRoot = process.cwd();
245
283
  await runFontSubsetting(projectRoot, logger);
@@ -249,7 +287,7 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration {
249
287
  },
250
288
 
251
289
  "astro:server:setup": async ({ server, logger }) => {
252
- // 8. 字体裁剪(开发模式,生成 common 子集 + 按需路由切片)
290
+ // 9. 字体裁剪(开发模式,生成 common 子集 + 按需路由切片)
253
291
  try {
254
292
  const projectRoot = process.cwd();
255
293
  // 清除旧的字体缓存
@@ -315,3 +353,6 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration {
315
353
  }
316
354
 
317
355
  export default stalux;
356
+
357
+ // 便捷导出:带默认行号的 Expressive Code 集成(也可从 @xingwangzhe/stalux/expressive-code 导入)
358
+ export { expressiveCode } from "./expressive-code";