@purview-dev/astroc4 1.0.0-prerelease.2 → 1.0.0-prerelease.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.
- package/README.md +2 -2
- package/package.json +22 -14
- package/src/components/labels.ts +5 -1
- package/src/expressive-code.d.mts +0 -28
- package/src/expressive-code.mjs +0 -46
- package/src/fences.mjs +0 -288
- package/src/grammar/langium.mjs +0 -559
- package/src/grammar/like-c4.langium +0 -1357
- package/src/grammar/likec4.tmLanguage.json +0 -327
- package/src/grammar/source.mjs +0 -410
- package/src/grammar/textmate.mjs +0 -439
- package/src/index.d.mts +0 -64
- package/src/index.mjs +0 -228
- package/src/types.d.ts +0 -12
- /package/src/{translations.mjs → translations.ts} +0 -0
package/src/index.mjs
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
// index.mjs
|
|
2
|
-
// path: src/index.mjs
|
|
3
|
-
// Starlight plugin that renders LikeC4 architecture diagrams:
|
|
4
|
-
//
|
|
5
|
-
// import astroc4 from '@purview-dev/astroc4';
|
|
6
|
-
// starlight({ plugins: [astroc4()] })
|
|
7
|
-
//
|
|
8
|
-
// It wires up everything a site previously had to configure by hand:
|
|
9
|
-
// - LikeC4VitePlugin, which compiles every .c4 project under the site root
|
|
10
|
-
// into the `likec4:model` / `likec4:icons` / `likec4:projects` modules;
|
|
11
|
-
// - the ```likec4 fence transform (./fences.mjs), appended to the site's
|
|
12
|
-
// Sätteri processor;
|
|
13
|
-
// - the build-time preload that avoids a Windows-only crash (see
|
|
14
|
-
// `preloadLikeC4` in ./fences.mjs);
|
|
15
|
-
// - LikeC4 syntax highlighting, resolved from the live Langium grammar and
|
|
16
|
-
// injected into the site's Expressive Code options (see below);
|
|
17
|
-
// - the component UI strings, through Starlight's i18n system.
|
|
18
|
-
//
|
|
19
|
-
// The highlighting injection is why this is a Starlight plugin and not just an
|
|
20
|
-
// integration: Starlight runs plugin `config:setup` hooks *before* it builds
|
|
21
|
-
// its Expressive Code integration, and a plugin can `updateConfig` the
|
|
22
|
-
// `expressiveCode` option — so the grammar reaches Shiki without the site
|
|
23
|
-
// having to create an `ec.config.mjs`. Expressive Code concatenates
|
|
24
|
-
// `shiki.langs` when it merges integration options with an `ec.config.mjs`, so
|
|
25
|
-
// a site that has one keeps its own languages too.
|
|
26
|
-
|
|
27
|
-
import { fileURLToPath } from 'node:url';
|
|
28
|
-
|
|
29
|
-
import { LikeC4VitePlugin } from 'likec4/vite-plugin';
|
|
30
|
-
|
|
31
|
-
import { likec4Fences, preloadLikeC4 } from './fences.mjs';
|
|
32
|
-
import { resolveLikeC4Grammar } from './grammar/source.mjs';
|
|
33
|
-
import { LANGUAGE_ALIASES, LANGUAGE_NAME } from './grammar/textmate.mjs';
|
|
34
|
-
import { translations } from './translations.mjs';
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* The published package name. Scoped because npm refuses the unscoped
|
|
38
|
-
* `astroc4` — "too similar to existing package astro" — and because the scope
|
|
39
|
-
* makes the specifiers this plugin writes into a site's pages unambiguous.
|
|
40
|
-
*/
|
|
41
|
-
const PACKAGE_NAME = '@purview-dev/astroc4';
|
|
42
|
-
|
|
43
|
-
/** @typedef {import('./index.d.mts').StarlightLikeC4Options} StarlightLikeC4Options */
|
|
44
|
-
/** @typedef {import('./index.d.mts').LikeC4HighlightingOptions} LikeC4HighlightingOptions */
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @param {StarlightLikeC4Options} [options]
|
|
48
|
-
* @returns {import('@astrojs/starlight/types').StarlightPlugin}
|
|
49
|
-
*/
|
|
50
|
-
export default function starlightLikeC4(options = {}) {
|
|
51
|
-
return {
|
|
52
|
-
name: PACKAGE_NAME,
|
|
53
|
-
hooks: {
|
|
54
|
-
'i18n:setup'({ injectTranslations }) {
|
|
55
|
-
injectTranslations(translations);
|
|
56
|
-
},
|
|
57
|
-
async 'config:setup'({ config, astroConfig, updateConfig, addIntegration, logger }) {
|
|
58
|
-
addIntegration(likec4Integration(options));
|
|
59
|
-
|
|
60
|
-
if (options.highlighting === false) return;
|
|
61
|
-
|
|
62
|
-
await injectHighlighting({
|
|
63
|
-
// `config` is the Starlight config, `astroConfig` the Astro one:
|
|
64
|
-
// the site root and the cache directory live on the latter.
|
|
65
|
-
root: fileURLToPath(astroConfig.root),
|
|
66
|
-
expressiveCode: config.expressiveCode,
|
|
67
|
-
updateConfig,
|
|
68
|
-
logger,
|
|
69
|
-
options: options.highlighting ?? {},
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Register the LikeC4 grammar with whatever Expressive Code the site ends up
|
|
78
|
-
* with.
|
|
79
|
-
*
|
|
80
|
-
* This is deliberately not wrapped in a try/catch: a ref that does not exist,
|
|
81
|
-
* or a grammar that cannot be read, fails `astro dev`, `astro build`,
|
|
82
|
-
* `astro check` and `astro sync` exactly like any other build error. Sites that
|
|
83
|
-
* cannot reach github.com on every build opt out with `offline: true` or
|
|
84
|
-
* `onError: 'warn'`.
|
|
85
|
-
*
|
|
86
|
-
* @param {{
|
|
87
|
-
* root: string,
|
|
88
|
-
* expressiveCode: unknown,
|
|
89
|
-
* updateConfig: (config: { expressiveCode?: unknown }) => void,
|
|
90
|
-
* logger: import('astro').AstroIntegrationLogger,
|
|
91
|
-
* options: LikeC4HighlightingOptions,
|
|
92
|
-
* }} context
|
|
93
|
-
*/
|
|
94
|
-
async function injectHighlighting({ root, expressiveCode, updateConfig, logger, options }) {
|
|
95
|
-
if (expressiveCode === false) {
|
|
96
|
-
logger.warn(
|
|
97
|
-
'LikeC4 syntax highlighting is skipped: `expressiveCode: false` disables the code blocks it ' +
|
|
98
|
-
'would highlight. Diagrams are unaffected.',
|
|
99
|
-
);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const source = await resolveLikeC4Grammar({ root, ...options, logger });
|
|
104
|
-
|
|
105
|
-
const registration = {
|
|
106
|
-
...source.grammar,
|
|
107
|
-
name: LANGUAGE_NAME,
|
|
108
|
-
aliases: [...LANGUAGE_ALIASES],
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
updateConfig({ expressiveCode: withLikeC4Language(expressiveCode, registration) });
|
|
112
|
-
|
|
113
|
-
const { repo, ref, sha, source: from } = source.meta;
|
|
114
|
-
logger.info(
|
|
115
|
-
`LikeC4 grammar ${repo}@${ref} (${sha})${from === 'network' ? '' : ` from ${from}`} — ` +
|
|
116
|
-
'highlighting ```c4 and ```likec4 fences',
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Add the LikeC4 language to a site's Expressive Code options without
|
|
122
|
-
* disturbing anything already set.
|
|
123
|
-
*
|
|
124
|
-
* Replacing an existing entry rather than appending matters: a site that
|
|
125
|
-
* pinned `likec4Language` from `@purview-dev/astroc4/expressive-code` should get the
|
|
126
|
-
* grammar for the ref it configured here, not two grammars for the same scope.
|
|
127
|
-
* Expressive Code concatenates `shiki.langs` when it merges these options with
|
|
128
|
-
* an `ec.config.mjs`, so a site's own languages survive either way.
|
|
129
|
-
*
|
|
130
|
-
* @param {unknown} expressiveCode The site's `expressiveCode` option.
|
|
131
|
-
* @param {Record<string, unknown>} registration Shiki language registration.
|
|
132
|
-
* @returns {Record<string, unknown> & { shiki: { langs: unknown[] } }}
|
|
133
|
-
*/
|
|
134
|
-
export function withLikeC4Language(expressiveCode, registration) {
|
|
135
|
-
const current = isObject(expressiveCode) ? expressiveCode : {};
|
|
136
|
-
const shiki = isObject(current.shiki) ? current.shiki : {};
|
|
137
|
-
const langs = Array.isArray(shiki.langs) ? [...shiki.langs] : [];
|
|
138
|
-
const existing = langs.findIndex(isLikeC4Language);
|
|
139
|
-
|
|
140
|
-
if (existing === -1) langs.push(registration);
|
|
141
|
-
else langs[existing] = registration;
|
|
142
|
-
|
|
143
|
-
return /** @type {Record<string, unknown> & { shiki: { langs: unknown[] } }} */ ({
|
|
144
|
-
...current,
|
|
145
|
-
shiki: { ...shiki, langs },
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** A Shiki `langs` entry that already covers LikeC4, as an id or a registration. */
|
|
150
|
-
function isLikeC4Language(entry) {
|
|
151
|
-
if (typeof entry === 'string') return entry === LANGUAGE_NAME || LANGUAGE_ALIASES.includes(entry);
|
|
152
|
-
if (!isObject(entry)) return false;
|
|
153
|
-
|
|
154
|
-
if (entry.name === LANGUAGE_NAME || entry.scopeName === 'source.likec4') return true;
|
|
155
|
-
|
|
156
|
-
return Array.isArray(entry.aliases) && entry.aliases.some((alias) => LANGUAGE_ALIASES.includes(alias));
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function isObject(value) {
|
|
160
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* @param {StarlightLikeC4Options} options
|
|
166
|
-
* @returns {import('astro').AstroIntegration}
|
|
167
|
-
*/
|
|
168
|
-
function likec4Integration({ vitePlugin = {}, fences = true }) {
|
|
169
|
-
return {
|
|
170
|
-
name: `${PACKAGE_NAME}/integration`,
|
|
171
|
-
hooks: {
|
|
172
|
-
'astro:config:setup': async ({ command, config, updateConfig, logger }) => {
|
|
173
|
-
updateConfig({
|
|
174
|
-
vite: {
|
|
175
|
-
plugins: [LikeC4VitePlugin(vitePlugin)],
|
|
176
|
-
// The components ship as .astro/.tsx source, so Vite has to
|
|
177
|
-
// transform them rather than hand them to Node as-is.
|
|
178
|
-
ssr: { noExternal: [PACKAGE_NAME] },
|
|
179
|
-
},
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
if (fences) {
|
|
183
|
-
await registerFences(config, updateConfig, logger);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// `command` is only available here, not in `astro:config:done` — and
|
|
187
|
-
// this must stay build-only; see `loadLikeC4` in ./fences.mjs.
|
|
188
|
-
if (command === 'build') {
|
|
189
|
-
await preloadLikeC4();
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Append the fence transform to the site's existing Sätteri processor, keeping
|
|
198
|
-
* whatever Starlight and other integrations already registered on it.
|
|
199
|
-
*/
|
|
200
|
-
async function registerFences(config, updateConfig, logger) {
|
|
201
|
-
const { satteri, isSatteriProcessor } = await import('@astrojs/markdown-satteri');
|
|
202
|
-
const existing = config.markdown?.processor;
|
|
203
|
-
|
|
204
|
-
// No processor configured means Astro's default, which is Sätteri.
|
|
205
|
-
if (existing === undefined) {
|
|
206
|
-
updateConfig({ markdown: { processor: satteri({ mdastPlugins: [likec4Fences()] }) } });
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (!isSatteriProcessor(existing)) {
|
|
211
|
-
logger.warn(
|
|
212
|
-
'```likec4 fences are disabled: the site is not using the Sätteri Markdown processor. ' +
|
|
213
|
-
'<LikeC4View /> still works.',
|
|
214
|
-
);
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const existingOptions = existing.options ?? {};
|
|
219
|
-
|
|
220
|
-
updateConfig({
|
|
221
|
-
markdown: {
|
|
222
|
-
processor: satteri({
|
|
223
|
-
...existingOptions,
|
|
224
|
-
mdastPlugins: [...(existingOptions.mdastPlugins ?? []), likec4Fences()],
|
|
225
|
-
}),
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
}
|
package/src/types.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// types.d.ts
|
|
2
|
-
// path: src/types.d.ts
|
|
3
|
-
// Ambient types for the package source: the `likec4:*` virtual modules created
|
|
4
|
-
// by LikeC4VitePlugin, and the plugin's keys in Starlight's `t()`.
|
|
5
|
-
|
|
6
|
-
/// <reference types="likec4/vite-plugin-modules" />
|
|
7
|
-
|
|
8
|
-
declare namespace StarlightApp {
|
|
9
|
-
type LikeC4UIStrings = (typeof import('./translations.mjs'))['translations']['en'];
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- declaration merging
|
|
11
|
-
interface I18n extends LikeC4UIStrings {}
|
|
12
|
-
}
|
|
File without changes
|