-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.ts
More file actions
139 lines (124 loc) · 4.89 KB
/
index.ts
File metadata and controls
139 lines (124 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import type { AstroIntegration } from "astro";
import remarkDirective from "remark-directive";
import { remarkAlert } from "./src/plugins/remark-alert.js";
import remarkCodeTabs from "./src/plugins/remark-code-tabs.js";
export interface JaamdOptions {
/**
* CSS selector for the markdown content wrapper.
* Must match the class on <MarkdownContent> (or your custom wrapper).
* @default ".jaamd-content"
*/
selector?: string;
/**
* Shiki syntax-highlighting theme.
*
* - **string** — single theme name (e.g. `"github-light"`).
* - **{ light, dark }** — enables dual-theme mode. Shiki outputs CSS
* variables for both themes and JAAMD injects the switching CSS.
* Use together with a `.dark` class on `<html>` for dark-mode toggling.
*
* @default "github-light"
*/
theme?: string | { light: string; dark: string };
/**
* Skip injecting the default CSS variable fallbacks (`jaamd/default`).
* When `false` (default), the built-in light-theme variable set is always
* loaded before the main stylesheet so unstyled pages never occur.
* Set to `true` only when you supply your own full variable set.
* @default false
*/
noDefault?: boolean;
/**
* Granular control over which remark plugins are registered.
* All enabled by default.
*/
plugins?: {
/** :::code-tabs directive — requires `directive: true` */
codeTabs?: boolean;
/** GitHub-style > [!NOTE] / [!WARNING] alerts */
alerts?: boolean;
/** remark-directive (prerequisite for codeTabs) */
directive?: boolean;
};
}
/**
* jaamd — Just Another Astro Markdown
*
* Registers remark plugins and injects the stylesheet automatically.
* Supports `astro add jaamd`.
*/
export default function jaamd(options: JaamdOptions = {}): AstroIntegration {
const {
selector = ".jaamd-content",
theme = "github-light",
noDefault = false,
plugins = {},
} = options;
const { codeTabs = true, alerts = true, directive = true } = plugins;
return {
name: "jaamd",
hooks: {
"astro:config:setup": ({ config, updateConfig, injectScript, logger }) => {
const jaamdRemarkPlugins: any[] = [];
if (alerts) jaamdRemarkPlugins.push(remarkAlert);
// directive must come before codeTabs
if (directive || codeTabs) jaamdRemarkPlugins.push(remarkDirective);
if (codeTabs) jaamdRemarkPlugins.push(remarkCodeTabs);
// Read remark/rehype plugins already set in the user's defineConfig
// and prepend jaamd's own plugins so they run first.
const existingMarkdown = (config.markdown as any) ?? {};
const existingRemarkPlugins: any[] = existingMarkdown.remarkPlugins ?? [];
const existingShikiConfig: any = existingMarkdown.shikiConfig ?? {};
// `wrap` and other keys are only filled in when absent.
const mergedShikiConfig: any = { ...existingShikiConfig };
// Dual-theme mode: { light, dark } → Shiki "themes" with CSS variables
if (typeof theme === "object" && theme.light && theme.dark) {
delete mergedShikiConfig.theme;
mergedShikiConfig.themes = { light: theme.light, dark: theme.dark };
mergedShikiConfig.defaultColor = false;
} else {
mergedShikiConfig.theme = typeof theme === "string" ? theme : "github-light";
}
if (mergedShikiConfig.wrap === undefined) mergedShikiConfig.wrap = true;
updateConfig({
vite: {
ssr: {
// Ensure jaamd source files (including .astro components) are
// processed by Vite transforms (i.e. the Astro compiler) rather
// than being treated as pre-bundled external modules.
noExternal: ["jaamd"],
},
},
markdown: {
remarkPlugins: [...jaamdRemarkPlugins, ...existingRemarkPlugins],
shikiConfig: mergedShikiConfig,
},
});
// "page" stage: bundled by Vite, tree-shaken, no duplicate injection
const isDualTheme = typeof theme === "object" && theme.light && theme.dark;
injectScript(
"page",
(!noDefault ? `import "jaamd/default";
` : "") +
(isDualTheme ? `import "jaamd/shiki-dual";
` : "") +
`import "jaamd/styles";
` +
`import { initMarkdownEnhancements } from "jaamd/client";
` +
`function __jaamdRun() { initMarkdownEnhancements(${JSON.stringify(selector)}); }
` +
`__jaamdRun();
` +
`document.addEventListener("astro:page-load", __jaamdRun);`,
);
logger.info("jaamd: markdown enhancements ready");
},
},
};
}
// Named re-exports for users who configure remark manually
export { default as remarkCodeTabs } from "./src/plugins/remark-code-tabs.js";
export { remarkAlert } from "./src/plugins/remark-alert.js";
export { default as remarkDirective } from "remark-directive";
export type { JaamdOptions as Options };