@riebeckite/honox 0.0.2 → 0.0.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/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export { loadRiebeckiteConfig, resolveHonoxConfig, } from "./src/config_loader.js";
2
+ export { replaceHonoxIslandDependencyPlugin } from "./src/honox_islands.js";
3
+ export type { ScaffoldSiteOptions, ScaffoldSiteResult, } from "./src/scaffold/index.js";
4
+ export { ScaffoldSiteError, scaffoldRiebeckiteSite, } from "./src/scaffold/index.js";
2
5
  export { createRiebeckiteSsg, defaultSsgEntry, riebeckiteSsgExtensionMap, } from "./src/ssg.js";
3
6
  export type { RiebeckiteSsgOptions } from "./src/ssg_plugin.js";
4
7
  export { riebeckiteSsg } from "./src/ssg_plugin.js";
5
8
  export type { RiebeckiteIntegrationOptions, RiebeckiteViteOptions, } from "./src/vite_plugin.js";
6
9
  export { defaultSsrExternals, riebeckite, riebeckiteVite, } from "./src/vite_plugin.js";
7
- export type { ScaffoldSiteOptions, ScaffoldSiteResult, } from "./src/scaffold/index.js";
8
- export { ScaffoldSiteError, scaffoldRiebeckiteSite, } from "./src/scaffold/index.js";
9
10
  export type { ResolvedHonoxApplication, ResolveHonoxApplicationOptions, } from "./src/vite_runner.js";
10
11
  export { buildHonoxApplication, resolveHonoxApplication, resolveHonoxApplicationRoot, startHonoxDevServer, } from "./src/vite_runner.js";
package/dist/index.js CHANGED
@@ -154,480 +154,162 @@ function pathToFileUrl(filePath) {
154
154
  return `file:///${filePath.replace(/\\/g, "/").replace(/^([A-Za-z]):/, "$1:")}`;
155
155
  }
156
156
 
157
- // src/ssg_plugin.ts
158
- import { defaultExtensionMap, toSSG } from "hono/ssg";
159
- import { relative } from "node:path";
160
- import { createServer } from "vite";
161
- var defaultEntry = "./src/index.tsx";
162
- function riebeckiteSsg(options = {}) {
163
- const virtualId = "virtual:riebeckite-ssg-void-entry";
164
- const resolvedVirtualId = `\0${virtualId}`;
165
- const entry = options.entry ?? defaultEntry;
166
- let resolvedConfig;
157
+ // src/honox_islands.ts
158
+ import fs3 from "node:fs/promises";
159
+ import path3 from "node:path";
160
+ import { parse } from "@babel/parser";
161
+ var honoxIslandDependencyPluginName = "inject-importing-islands";
162
+ var importingIslandsExport = "__importing_islands";
163
+ function replaceHonoxIslandDependencyPlugin(plugins) {
164
+ return [
165
+ ...plugins.map(disableHonoxIslandDependencyPlugin),
166
+ scopedIslandDependencyPlugin()
167
+ ];
168
+ }
169
+ function disableHonoxIslandDependencyPlugin(plugin) {
170
+ if (plugin instanceof Promise) {
171
+ return plugin.then(disableHonoxIslandDependencyPlugin);
172
+ }
173
+ if (plugin.name !== honoxIslandDependencyPluginName) return plugin;
174
+ return { ...plugin, transform: void 0 };
175
+ }
176
+ function scopedIslandDependencyPlugin() {
177
+ let appDirectory = "";
178
+ let islandDirectory = "";
167
179
  return {
168
- name: "riebeckite-ssg",
169
- apply: "build",
170
- enforce: "post",
171
- config() {
172
- return {
173
- build: {
174
- rollupOptions: {
175
- input: [virtualId]
176
- }
177
- }
178
- };
179
- },
180
+ name: "riebeckite-inject-importing-islands",
180
181
  configResolved(config) {
181
- resolvedConfig = config;
182
- },
183
- resolveId(id) {
184
- return id === virtualId ? resolvedVirtualId : void 0;
182
+ appDirectory = path3.resolve(config.root, "app");
183
+ islandDirectory = path3.join(appDirectory, "islands");
185
184
  },
186
- load(id) {
187
- return id === resolvedVirtualId ? 'console.log("suppress empty chunk message")' : void 0;
188
- },
189
- async generateBundle(_outputOptions, bundle) {
190
- const config = resolvedConfig;
191
- if (!config) {
192
- throw new Error("Riebeckite SSG could not resolve the Vite configuration.");
193
- }
194
- removeVirtualEntryChunk(bundle, resolvedVirtualId);
195
- const server2 = await createServer({
196
- root: config.root,
197
- define: config.define,
198
- resolve: {
199
- ...config.resolve,
200
- builtins: [...config.resolve.builtins, /^node:/]
201
- },
202
- plugins: [],
203
- build: { ssr: true },
204
- mode: config.mode
205
- });
206
- try {
207
- const module = await server2.ssrLoadModule(entry);
208
- const app = module.default;
209
- if (!app) {
210
- throw new Error(`Failed to find a default export from ${entry}.`);
211
- }
212
- const generatedHtml = [];
213
- const result = await toSSG(
214
- app,
215
- {
216
- writeFile: async (filePath, data) => {
217
- const fileName = relative(config.build.outDir, filePath).replaceAll(
218
- "\\",
219
- "/"
220
- );
221
- if (fileName.endsWith(".html") && typeof data === "string") {
222
- generatedHtml.push({ path: fileName, html: data });
223
- }
224
- this.emitFile({
225
- type: "asset",
226
- fileName,
227
- source: data
228
- });
229
- },
230
- async mkdir() {
231
- }
232
- },
233
- {
234
- dir: config.build.outDir,
235
- plugins: options.plugins ?? [],
236
- extensionMap: options.extensionMap ?? defaultExtensionMap
237
- }
238
- );
239
- if (!result.success) throw result.error;
240
- await emitGeneratedOutputs(
241
- module,
242
- (asset) => this.emitFile(asset)
243
- );
244
- inspectGeneratedHtmlPages(module, generatedHtml, {
245
- warn: (message) => this.warn(message),
246
- info: (message) => this.info(message)
247
- });
248
- } finally {
249
- await server2.close();
185
+ async transform(sourceCode, id) {
186
+ const modulePath = toFilePath(id);
187
+ if (!isInDirectory(modulePath, appDirectory) || !isJavaScriptModule(modulePath)) {
188
+ return;
250
189
  }
190
+ if (!await importsIsland(modulePath, sourceCode, this)) return;
191
+ return {
192
+ code: `${sourceCode}
193
+ export const ${importingIslandsExport} = true;
194
+ `,
195
+ map: null
196
+ };
251
197
  }
252
198
  };
253
- }
254
- async function emitGeneratedOutputs(module, emit) {
255
- const content = module.content;
256
- if (!content) return;
257
- const manifest = await content.getManifest();
258
- for (const output of manifest.generatedOutputs ?? []) {
259
- emit({
260
- type: "asset",
261
- fileName: output.path,
262
- source: output.content
263
- });
264
- }
265
- }
266
- function inspectGeneratedHtmlPages(module, pages, log) {
267
- const plugins = module.config?.plugins ?? [];
268
- for (const plugin of plugins) {
269
- const inspector = plugin.inspectGeneratedHtml;
270
- if (typeof inspector !== "function") continue;
271
- for (const page of pages) {
272
- for (const diagnostic of inspector(page) ?? []) {
273
- const label = `[${plugin.name ?? "plugin"}] ${page.path}: ${diagnostic.message}`;
274
- if (diagnostic.severity === "info") log.info(label);
275
- else log.warn(label);
199
+ async function importsIsland(modulePath, sourceCode, pluginContext) {
200
+ const visited = /* @__PURE__ */ new Set();
201
+ const visit = async (currentModulePath, currentSourceCode) => {
202
+ if (visited.has(currentModulePath)) return false;
203
+ visited.add(currentModulePath);
204
+ if (isInDirectory(currentModulePath, islandDirectory)) return true;
205
+ const importSources = getStaticImportSources(currentSourceCode);
206
+ for (const importSource of importSources) {
207
+ const resolved = await pluginContext.resolve(
208
+ importSource,
209
+ currentModulePath
210
+ );
211
+ if (!resolved) continue;
212
+ const dependencyPath = toFilePath(resolved.id);
213
+ if (!isInDirectory(dependencyPath, appDirectory) || !isJavaScriptModule(dependencyPath)) {
214
+ continue;
215
+ }
216
+ try {
217
+ const dependencySourceCode = await fs3.readFile(
218
+ dependencyPath,
219
+ "utf8"
220
+ );
221
+ if (await visit(dependencyPath, dependencySourceCode)) return true;
222
+ } catch {
223
+ }
276
224
  }
277
- }
225
+ return false;
226
+ };
227
+ return visit(modulePath, sourceCode);
278
228
  }
279
229
  }
280
- function removeVirtualEntryChunk(bundle, virtualEntryId) {
281
- for (const chunk of Object.values(bundle)) {
282
- if (chunk.type === "chunk" && chunk.moduleIds?.includes(virtualEntryId)) {
283
- delete bundle[chunk.fileName];
230
+ function getStaticImportSources(sourceCode) {
231
+ const ast = parse(sourceCode, {
232
+ sourceType: "module",
233
+ plugins: ["typescript", "jsx"]
234
+ });
235
+ return ast.program.body.flatMap((statement) => {
236
+ if (statement.type === "ImportDeclaration" || statement.type === "ExportNamedDeclaration" || statement.type === "ExportAllDeclaration") {
237
+ return statement.source ? [statement.source.value] : [];
284
238
  }
285
- }
239
+ return [];
240
+ });
286
241
  }
287
-
288
- // src/ssg.ts
289
- var defaultSsgEntry = "./app/server.ts";
290
- function riebeckiteSsgExtensionMap() {
291
- return {
292
- "application/atom+xml": "xml",
293
- "application/json": "json",
294
- "application/rss+xml": "xml",
295
- "application/xml": "xml",
296
- "text/html": "html",
297
- "text/plain": "txt",
298
- "text/xml": "xml"
299
- };
242
+ function toFilePath(id) {
243
+ return id.split("?", 1)[0] ?? id;
300
244
  }
301
- function createRiebeckiteSsg(options = {}) {
302
- return riebeckiteSsg({
303
- ...options,
304
- entry: options.entry ?? defaultSsgEntry,
305
- extensionMap: {
306
- ...riebeckiteSsgExtensionMap(),
307
- ...options.extensionMap
308
- }
309
- });
245
+ function isInDirectory(filePath, directory) {
246
+ const relativePath = path3.relative(directory, filePath);
247
+ return relativePath !== "" && !relativePath.startsWith(`..${path3.sep}`) && !path3.isAbsolute(relativePath);
248
+ }
249
+ function isJavaScriptModule(filePath) {
250
+ return /\.[cm]?[jt]sx?$/.test(filePath);
310
251
  }
311
252
 
312
- // src/vite_plugin.ts
313
- import path5 from "node:path";
253
+ // src/scaffold/index.ts
254
+ import fs4 from "node:fs/promises";
255
+ import path4 from "node:path";
314
256
 
315
- // src/asset_entries.ts
316
- import fs3 from "node:fs";
317
- import path3 from "node:path";
318
- import { uniqueStrings } from "@riebeckite/core";
319
- function writeRiebeckiteAssetEntries(config, paths2) {
320
- writeGeneratedFile(paths2.pluginStyles, createPluginStylesEntry(config));
321
- writeGeneratedFile(paths2.themeStyles, createThemeStylesEntry(config));
257
+ // src/scaffold/localized-content.ts
258
+ var SCAFFOLD_LANGUAGES = [
259
+ "en",
260
+ "ja",
261
+ "zh-CN",
262
+ "es",
263
+ "de",
264
+ "fr",
265
+ "ko"
266
+ ];
267
+ function defaultLanguageForLocale(locale) {
268
+ const normalized = locale.toLowerCase();
269
+ if (normalized.startsWith("ja")) return "ja";
270
+ if (normalized.startsWith("zh")) return "zh-CN";
271
+ if (normalized.startsWith("es")) return "es";
272
+ if (normalized.startsWith("de")) return "de";
273
+ if (normalized.startsWith("fr")) return "fr";
274
+ if (normalized.startsWith("ko")) return "ko";
275
+ return "en";
322
276
  }
323
- function createPluginStylesEntry(config) {
324
- return createStylesheetEntry(
325
- collectPluginStyleSpecifiers(config),
326
- "Plugin default styles, in resolved plugin order. Generated by @riebeckite/honox; do not edit. Import this before the theme stylesheet so a theme can override plugin defaults."
327
- );
277
+ var HELPERS = {
278
+ en: "https://github.com/Rerurate514/riebeckite/blob/main/docs/en/README.md",
279
+ ja: "https://github.com/Rerurate514/riebeckite/blob/main/docs/ja/README.md"
280
+ };
281
+ var PLUGIN_INDEX_URL = "https://github.com/Rerurate514/riebeckite/tree/main/packages/plugins";
282
+ var THEMES_INDEX_URL = "https://github.com/Rerurate514/riebeckite/tree/main/packages/themes";
283
+ function pluginReadmeUrl(slug) {
284
+ return `https://github.com/Rerurate514/riebeckite/blob/main/packages/plugins/${slug}/README.md`;
328
285
  }
329
- function createThemeStylesEntry(config) {
330
- return createStylesheetEntry(
331
- config.theme.styles.map((style2) => style2.moduleSpecifier),
332
- "Theme styles. Generated by @riebeckite/honox; do not edit. Import this after the plugin stylesheet so the theme wins the plugin/theme cascade."
333
- );
286
+ function themeReadmeUrl(slug) {
287
+ return `https://github.com/Rerurate514/riebeckite/blob/main/packages/themes/${slug}/README.md`;
334
288
  }
335
- function collectPluginStyleSpecifiers(config) {
336
- return config.plugins.flatMap(
337
- (plugin) => (plugin.assets ?? []).filter((asset) => asset.kind === "style").map((asset) => asset.moduleSpecifier)
338
- );
289
+ function localizedContentFiles(variables) {
290
+ const defaultLang = defaultLanguageForLocale(variables.locale);
291
+ const pages = [
292
+ { basePath: "index", build: (language) => indexContent(variables, language) },
293
+ { basePath: "framework/plugins", build: (language) => pluginsContent(language) },
294
+ { basePath: "framework/themes", build: (language) => themesContent(language) }
295
+ ];
296
+ const files = [];
297
+ for (const page of pages) {
298
+ for (const language of SCAFFOLD_LANGUAGES) {
299
+ const suffix = language === defaultLang ? "" : `.${language}`;
300
+ files.push({
301
+ path: `content/${page.basePath}${suffix}.md`,
302
+ content: page.build(language)
303
+ });
304
+ }
305
+ }
306
+ return files;
339
307
  }
340
- function createStylesheetEntry(moduleSpecifiers, banner) {
341
- const imports = uniqueStrings(moduleSpecifiers).map((specifier) => `@import ${JSON.stringify(specifier)};`).join("\n");
342
- if (!banner) return imports;
343
- const header = `/* ${banner.replace(/\*\//g, "* /")} */`;
344
- return imports ? `${header}
345
- ${imports}
346
- ` : `${header}
347
- `;
308
+ function read(text, language) {
309
+ return text[language];
348
310
  }
349
- function writeGeneratedFile(filePath, contents) {
350
- fs3.mkdirSync(path3.dirname(filePath), { recursive: true });
351
- fs3.writeFileSync(filePath, contents);
352
- }
353
-
354
- // src/client_module.ts
355
- var clientModuleId = "virtual:riebeckite/client";
356
- var resolvedClientModuleId = `\0${clientModuleId}`;
357
- function riebeckiteClientModule(getConfig) {
358
- return {
359
- name: "riebeckite-client-module",
360
- resolveId(id) {
361
- if (id === clientModuleId) return resolvedClientModuleId;
362
- return null;
363
- },
364
- load(id) {
365
- if (id !== resolvedClientModuleId) return null;
366
- return createClientModule(getConfig());
367
- }
368
- };
369
- }
370
- function createClientModule(config) {
371
- const imports = [];
372
- const initializers = [];
373
- for (const [index, entry] of config.plugins.flatMap((plugin) => plugin.clientEntries ?? []).entries()) {
374
- const localName = `pluginClientInitializer${index}`;
375
- const importTarget = entry.exportName ? `{ ${entry.exportName} as ${localName} }` : localName;
376
- imports.push(
377
- `import ${importTarget} from ${JSON.stringify(entry.moduleSpecifier)};`
378
- );
379
- initializers.push(localName);
380
- }
381
- return `${imports.join("\n")}
382
-
383
- export function initRiebeckiteClient() {
384
- ${initializers.map((name) => ` ${name}();`).join("\n")}
385
- }
386
- `;
387
- }
388
-
389
- // src/vite_runner.ts
390
- import fs4 from "node:fs/promises";
391
- import path4 from "node:path";
392
- import { build, createServer as createServer2 } from "vite";
393
- var viteConfigFileNames = [
394
- "vite.config.ts",
395
- "vite.config.js",
396
- "vite.config.mjs"
397
- ];
398
- async function resolveHonoxApplicationRoot(configRoot) {
399
- const roots = await findViteApplicationRoots(configRoot);
400
- if (roots.length === 1) return roots[0];
401
- if (roots.length === 0) {
402
- throw new HonoxApplicationRootError(
403
- `Could not find a Vite application under ${configRoot}.`
404
- );
405
- }
406
- throw new HonoxApplicationRootError(
407
- `Found multiple Vite applications under ${configRoot}: ${roots.join(", ")}.`
408
- );
409
- }
410
- var HonoxApplicationRootError = class extends Error {
411
- constructor(message) {
412
- super(message);
413
- this.name = "HonoxApplicationRootError";
414
- }
415
- };
416
- async function resolveHonoxApplication(options) {
417
- const configRoot = path4.resolve(options.configRoot);
418
- const appRoot = options.appRoot ? path4.resolve(options.appRoot) : await resolveHonoxApplicationRoot(configRoot);
419
- const workspaceRoot = options.workspaceRoot ?? await findWorkspaceRoot(configRoot);
420
- const rawConfig = await loadRiebeckiteConfig({
421
- configRoot,
422
- configFile: options.configFile,
423
- workspaceRoot
424
- });
425
- const config = resolveHonoxConfig(rawConfig, appRoot);
426
- return {
427
- config,
428
- configRoot,
429
- appRoot,
430
- contentRoot: config.content.directory
431
- };
432
- }
433
- async function findWorkspaceRoot(configRoot) {
434
- try {
435
- const workspaceConfig = path4.join(configRoot, "pnpm-workspace.yaml");
436
- return (await fs4.stat(workspaceConfig)).isFile() ? configRoot : void 0;
437
- } catch {
438
- return void 0;
439
- }
440
- }
441
- async function startHonoxDevServer(options) {
442
- const server2 = await createServer2({ root: options.root });
443
- await server2.listen();
444
- server2.printUrls();
445
- await waitForShutdown(server2);
446
- }
447
- async function buildHonoxApplication(options) {
448
- await runTraced(
449
- options.tracer,
450
- "integration.honox.client_build",
451
- () => build({ root: options.root, mode: "client" })
452
- );
453
- await runTraced(
454
- options.tracer,
455
- "integration.honox.server_build",
456
- () => build({ root: options.root })
457
- );
458
- }
459
- async function runTraced(tracer, name, buildTask) {
460
- return tracer ? await tracer.span(name, {}, buildTask) : await buildTask();
461
- }
462
- async function waitForShutdown(server2) {
463
- await new Promise((resolve) => {
464
- const close = () => {
465
- void server2.close().finally(resolve);
466
- };
467
- process.once("SIGINT", close);
468
- process.once("SIGTERM", close);
469
- });
470
- }
471
- async function findViteApplicationRoots(root) {
472
- const directories = [root];
473
- const applicationRoots = [];
474
- while (directories.length > 0) {
475
- const directory = directories.pop();
476
- if (!directory) continue;
477
- if (await hasViteConfig(directory)) applicationRoots.push(directory);
478
- const entries = await fs4.readdir(directory, { withFileTypes: true });
479
- for (const entry of entries) {
480
- if (!entry.isDirectory() || entry.name === "node_modules" || entry.name === ".git" || entry.name === "tests") {
481
- continue;
482
- }
483
- directories.push(path4.join(directory, entry.name));
484
- }
485
- }
486
- return applicationRoots;
487
- }
488
- async function hasViteConfig(directory) {
489
- for (const fileName of viteConfigFileNames) {
490
- try {
491
- if ((await fs4.stat(path4.join(directory, fileName))).isFile()) return true;
492
- } catch {
493
- }
494
- }
495
- return false;
496
- }
497
-
498
- // src/vite_plugin.ts
499
- var defaultSsrExternals = [
500
- "extend",
501
- "debug",
502
- "node:fs/promises",
503
- "node:path",
504
- "parse-numeric-range",
505
- "slugify",
506
- "vfile-matter"
507
- ];
508
- function riebeckite(options = {}) {
509
- let resolvedConfig;
510
- const getConfig = () => {
511
- if (!resolvedConfig) {
512
- throw new Error("Riebeckite config has not been loaded yet.");
513
- }
514
- return resolvedConfig;
515
- };
516
- return [
517
- {
518
- name: "riebeckite-host-integration",
519
- async config(userConfig) {
520
- const root = userConfig.root ? path5.resolve(userConfig.root) : process.cwd();
521
- const appRoot = options.appRoot ?? root;
522
- const application = await resolveHonoxApplication({
523
- configRoot: options.configRoot ?? appRoot,
524
- configFile: options.configFile,
525
- appRoot,
526
- workspaceRoot: options.workspaceRoot
527
- });
528
- resolvedConfig = application.config;
529
- writeRiebeckiteAssetEntries(resolvedConfig, {
530
- pluginStyles: path5.join(appRoot, "app/.riebeckite/plugin-styles.css"),
531
- themeStyles: path5.join(appRoot, "app/.riebeckite/theme-styles.css")
532
- });
533
- return {
534
- define: {
535
- "process.env.RIEBECKITE_APP_ROOT": JSON.stringify(appRoot)
536
- },
537
- resolve: {
538
- alias: options.workspaceRoot ? createWorkspacePackageAliases(options.workspaceRoot) : []
539
- }
540
- };
541
- }
542
- },
543
- riebeckiteClientModule(getConfig)
544
- ];
545
- }
546
- function riebeckiteVite(options = {}) {
547
- const { ssg, ssrExternals, ...integration } = options;
548
- return [
549
- ...riebeckite(integration),
550
- riebeckiteSsrExternals([...defaultSsrExternals, ...ssrExternals ?? []]),
551
- createRiebeckiteSsg(ssg)
552
- ];
553
- }
554
- function riebeckiteSsrExternals(externals) {
555
- return {
556
- name: "riebeckite-ssr-externals",
557
- config() {
558
- return {
559
- environments: {
560
- ssr: {
561
- resolve: {
562
- external: [...externals]
563
- }
564
- }
565
- }
566
- };
567
- }
568
- };
569
- }
570
-
571
- // src/scaffold/index.ts
572
- import fs5 from "node:fs/promises";
573
- import path6 from "node:path";
574
-
575
- // src/scaffold/localized-content.ts
576
- var SCAFFOLD_LANGUAGES = [
577
- "en",
578
- "ja",
579
- "zh-CN",
580
- "es",
581
- "de",
582
- "fr",
583
- "ko"
584
- ];
585
- function defaultLanguageForLocale(locale) {
586
- const normalized = locale.toLowerCase();
587
- if (normalized.startsWith("ja")) return "ja";
588
- if (normalized.startsWith("zh")) return "zh-CN";
589
- if (normalized.startsWith("es")) return "es";
590
- if (normalized.startsWith("de")) return "de";
591
- if (normalized.startsWith("fr")) return "fr";
592
- if (normalized.startsWith("ko")) return "ko";
593
- return "en";
594
- }
595
- var HELPERS = {
596
- en: "https://github.com/Rerurate514/riebeckite/blob/main/docs/en/README.md",
597
- ja: "https://github.com/Rerurate514/riebeckite/blob/main/docs/ja/README.md"
598
- };
599
- var PLUGIN_INDEX_URL = "https://github.com/Rerurate514/riebeckite/tree/main/packages/plugins";
600
- var THEMES_INDEX_URL = "https://github.com/Rerurate514/riebeckite/tree/main/packages/themes";
601
- function pluginReadmeUrl(slug) {
602
- return `https://github.com/Rerurate514/riebeckite/blob/main/packages/plugins/${slug}/README.md`;
603
- }
604
- function themeReadmeUrl(slug) {
605
- return `https://github.com/Rerurate514/riebeckite/blob/main/packages/themes/${slug}/README.md`;
606
- }
607
- function localizedContentFiles(variables) {
608
- const defaultLang = defaultLanguageForLocale(variables.locale);
609
- const pages = [
610
- { basePath: "index", build: (language) => indexContent(variables, language) },
611
- { basePath: "framework/plugins", build: (language) => pluginsContent(language) },
612
- { basePath: "framework/themes", build: (language) => themesContent(language) }
613
- ];
614
- const files = [];
615
- for (const page of pages) {
616
- for (const language of SCAFFOLD_LANGUAGES) {
617
- const suffix = language === defaultLang ? "" : `.${language}`;
618
- files.push({
619
- path: `content/${page.basePath}${suffix}.md`,
620
- content: page.build(language)
621
- });
622
- }
623
- }
624
- return files;
625
- }
626
- function read(text, language) {
627
- return text[language];
628
- }
629
- function frontmatter() {
630
- return ["---", "publish: true", "---", ""].join("\n");
311
+ function frontmatter() {
312
+ return ["---", "publish: true", "---", ""].join("\n");
631
313
  }
632
314
  function heading(level, text) {
633
315
  return `${"#".repeat(level)} ${text}`;
@@ -1539,18 +1221,18 @@ function packageJson(variables) {
1539
1221
  inspect: "riebeckite inspect"
1540
1222
  },
1541
1223
  dependencies: {
1542
- "@riebeckite/core": "^0.0.1",
1543
- "@riebeckite/honox": "^0.0.1",
1544
- "@riebeckite/plugin-color-mode": "^0.0.1",
1545
- "@riebeckite/plugin-l10n": "^0.0.1",
1546
- "@riebeckite/plugin-obsidian-markdown": "^0.0.1",
1547
- "@riebeckite/theme-default": "^0.0.1",
1224
+ "@riebeckite/core": "^0.0.3",
1225
+ "@riebeckite/honox": "^0.0.3",
1226
+ "@riebeckite/plugin-color-mode": "^0.0.3",
1227
+ "@riebeckite/plugin-l10n": "^0.0.3",
1228
+ "@riebeckite/plugin-obsidian-markdown": "^0.0.3",
1229
+ "@riebeckite/theme-default": "^0.0.3",
1548
1230
  hono: "^4.12.25",
1549
1231
  honox: "0.1.56"
1550
1232
  },
1551
1233
  devDependencies: {
1552
1234
  "@hono/vite-build": "^1.11.1",
1553
- "@riebeckite/cli": "^0.0.1",
1235
+ "@riebeckite/cli": "^0.0.3",
1554
1236
  "@types/node": "^24.5.2",
1555
1237
  typescript: "^5.0.0",
1556
1238
  vite: "^8.0.9"
@@ -2102,7 +1784,7 @@ var ScaffoldSiteError = class extends Error {
2102
1784
  }
2103
1785
  };
2104
1786
  async function scaffoldRiebeckiteSite(options) {
2105
- const targetDirectory = path6.resolve(options.targetDirectory);
1787
+ const targetDirectory = path4.resolve(options.targetDirectory);
2106
1788
  const files = siteTemplateFiles(templateVariables(options, targetDirectory));
2107
1789
  await assertTargetWritable(
2108
1790
  targetDirectory,
@@ -2110,15 +1792,15 @@ async function scaffoldRiebeckiteSite(options) {
2110
1792
  options.overwrite ?? false
2111
1793
  );
2112
1794
  for (const file of files) {
2113
- const filePath = path6.join(targetDirectory, file.path);
2114
- await fs5.mkdir(path6.dirname(filePath), { recursive: true });
2115
- await fs5.writeFile(filePath, file.content, "utf8");
1795
+ const filePath = path4.join(targetDirectory, file.path);
1796
+ await fs4.mkdir(path4.dirname(filePath), { recursive: true });
1797
+ await fs4.writeFile(filePath, file.content, "utf8");
2116
1798
  }
2117
1799
  return { targetDirectory, files: files.map((file) => file.path) };
2118
1800
  }
2119
1801
  function templateVariables(options, targetDirectory) {
2120
1802
  const name = normalizePackageName(
2121
- options.name ?? path6.basename(targetDirectory)
1803
+ options.name ?? path4.basename(targetDirectory)
2122
1804
  );
2123
1805
  return {
2124
1806
  name,
@@ -2131,7 +1813,7 @@ function templateVariables(options, targetDirectory) {
2131
1813
  async function assertTargetWritable(targetDirectory, files, overwrite) {
2132
1814
  let entries;
2133
1815
  try {
2134
- entries = await fs5.readdir(targetDirectory);
1816
+ entries = await fs4.readdir(targetDirectory);
2135
1817
  } catch (error) {
2136
1818
  if (isNotFoundError(error)) return;
2137
1819
  throw error;
@@ -2154,6 +1836,427 @@ function normalizePackageName(value) {
2154
1836
  function isNotFoundError(error) {
2155
1837
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
2156
1838
  }
1839
+
1840
+ // src/ssg_plugin.ts
1841
+ import { defaultExtensionMap, toSSG } from "hono/ssg";
1842
+ import { relative } from "node:path";
1843
+ import { createServer } from "vite";
1844
+ var defaultEntry = "./src/index.tsx";
1845
+ function riebeckiteSsg(options = {}) {
1846
+ const virtualId = "virtual:riebeckite-ssg-void-entry";
1847
+ const resolvedVirtualId = `\0${virtualId}`;
1848
+ const entry = options.entry ?? defaultEntry;
1849
+ let resolvedConfig;
1850
+ return {
1851
+ name: "riebeckite-ssg",
1852
+ apply: "build",
1853
+ enforce: "post",
1854
+ config() {
1855
+ return {
1856
+ build: {
1857
+ rollupOptions: {
1858
+ input: [virtualId]
1859
+ }
1860
+ }
1861
+ };
1862
+ },
1863
+ configResolved(config) {
1864
+ resolvedConfig = config;
1865
+ },
1866
+ resolveId(id) {
1867
+ return id === virtualId ? resolvedVirtualId : void 0;
1868
+ },
1869
+ load(id) {
1870
+ return id === resolvedVirtualId ? 'console.log("suppress empty chunk message")' : void 0;
1871
+ },
1872
+ async generateBundle(_outputOptions, bundle) {
1873
+ const config = resolvedConfig;
1874
+ if (!config) {
1875
+ throw new Error("Riebeckite SSG could not resolve the Vite configuration.");
1876
+ }
1877
+ removeVirtualEntryChunk(bundle, resolvedVirtualId);
1878
+ const server2 = await createServer({
1879
+ root: config.root,
1880
+ define: config.define,
1881
+ resolve: {
1882
+ ...config.resolve,
1883
+ builtins: [...config.resolve.builtins, /^node:/]
1884
+ },
1885
+ plugins: [],
1886
+ build: { ssr: true },
1887
+ mode: config.mode
1888
+ });
1889
+ try {
1890
+ const module = await server2.ssrLoadModule(entry);
1891
+ const app = module.default;
1892
+ if (!app) {
1893
+ throw new Error(`Failed to find a default export from ${entry}.`);
1894
+ }
1895
+ const generatedHtml = [];
1896
+ const result = await toSSG(
1897
+ app,
1898
+ {
1899
+ writeFile: async (filePath, data) => {
1900
+ const fileName = relative(config.build.outDir, filePath).replaceAll(
1901
+ "\\",
1902
+ "/"
1903
+ );
1904
+ if (fileName.endsWith(".html") && typeof data === "string") {
1905
+ generatedHtml.push({ path: fileName, html: data });
1906
+ }
1907
+ this.emitFile({
1908
+ type: "asset",
1909
+ fileName,
1910
+ source: data
1911
+ });
1912
+ },
1913
+ async mkdir() {
1914
+ }
1915
+ },
1916
+ {
1917
+ dir: config.build.outDir,
1918
+ plugins: options.plugins ?? [],
1919
+ extensionMap: options.extensionMap ?? defaultExtensionMap
1920
+ }
1921
+ );
1922
+ if (!result.success) throw result.error;
1923
+ await emitGeneratedOutputs(
1924
+ module,
1925
+ (asset) => this.emitFile(asset)
1926
+ );
1927
+ inspectGeneratedHtmlPages(module, generatedHtml, {
1928
+ warn: (message) => this.warn(message),
1929
+ info: (message) => this.info(message)
1930
+ });
1931
+ } finally {
1932
+ await server2.close();
1933
+ }
1934
+ }
1935
+ };
1936
+ }
1937
+ async function emitGeneratedOutputs(module, emit) {
1938
+ const content = module.content;
1939
+ if (!content) return;
1940
+ const manifest = await content.getManifest();
1941
+ for (const output of manifest.generatedOutputs ?? []) {
1942
+ emit({
1943
+ type: "asset",
1944
+ fileName: output.path,
1945
+ source: output.content
1946
+ });
1947
+ }
1948
+ }
1949
+ function inspectGeneratedHtmlPages(module, pages, log) {
1950
+ const plugins = module.config?.plugins ?? [];
1951
+ for (const plugin of plugins) {
1952
+ const inspector = plugin.inspectGeneratedHtml;
1953
+ if (typeof inspector !== "function") continue;
1954
+ for (const page of pages) {
1955
+ for (const diagnostic of inspector(page) ?? []) {
1956
+ const label = `[${plugin.name ?? "plugin"}] ${page.path}: ${diagnostic.message}`;
1957
+ if (diagnostic.severity === "info") log.info(label);
1958
+ else log.warn(label);
1959
+ }
1960
+ }
1961
+ }
1962
+ }
1963
+ function removeVirtualEntryChunk(bundle, virtualEntryId) {
1964
+ for (const chunk of Object.values(bundle)) {
1965
+ if (chunk.type === "chunk" && chunk.moduleIds?.includes(virtualEntryId)) {
1966
+ delete bundle[chunk.fileName];
1967
+ }
1968
+ }
1969
+ }
1970
+
1971
+ // src/ssg.ts
1972
+ var defaultSsgEntry = "./app/server.ts";
1973
+ function riebeckiteSsgExtensionMap() {
1974
+ return {
1975
+ "application/atom+xml": "xml",
1976
+ "application/json": "json",
1977
+ "application/rss+xml": "xml",
1978
+ "application/xml": "xml",
1979
+ "text/html": "html",
1980
+ "text/plain": "txt",
1981
+ "text/xml": "xml"
1982
+ };
1983
+ }
1984
+ function createRiebeckiteSsg(options = {}) {
1985
+ return riebeckiteSsg({
1986
+ ...options,
1987
+ entry: options.entry ?? defaultSsgEntry,
1988
+ extensionMap: {
1989
+ ...riebeckiteSsgExtensionMap(),
1990
+ ...options.extensionMap
1991
+ }
1992
+ });
1993
+ }
1994
+
1995
+ // src/vite_plugin.ts
1996
+ import path7 from "node:path";
1997
+
1998
+ // src/asset_entries.ts
1999
+ import fs5 from "node:fs";
2000
+ import path5 from "node:path";
2001
+ import { uniqueStrings } from "@riebeckite/core";
2002
+ function writeRiebeckiteAssetEntries(config, paths2) {
2003
+ writeGeneratedFile(paths2.pluginStyles, createPluginStylesEntry(config));
2004
+ writeGeneratedFile(paths2.themeStyles, createThemeStylesEntry(config));
2005
+ }
2006
+ function createPluginStylesEntry(config) {
2007
+ return createStylesheetEntry(
2008
+ collectPluginStyleSpecifiers(config),
2009
+ "Plugin default styles, in resolved plugin order. Generated by @riebeckite/honox; do not edit. Import this before the theme stylesheet so a theme can override plugin defaults."
2010
+ );
2011
+ }
2012
+ function createThemeStylesEntry(config) {
2013
+ return createStylesheetEntry(
2014
+ config.theme.styles.map((style2) => style2.moduleSpecifier),
2015
+ "Theme styles. Generated by @riebeckite/honox; do not edit. Import this after the plugin stylesheet so the theme wins the plugin/theme cascade."
2016
+ );
2017
+ }
2018
+ function collectPluginStyleSpecifiers(config) {
2019
+ return config.plugins.flatMap(
2020
+ (plugin) => (plugin.assets ?? []).filter((asset) => asset.kind === "style").map((asset) => asset.moduleSpecifier)
2021
+ );
2022
+ }
2023
+ function createStylesheetEntry(moduleSpecifiers, banner) {
2024
+ const imports = uniqueStrings(moduleSpecifiers).map((specifier) => `@import ${JSON.stringify(specifier)};`).join("\n");
2025
+ if (!banner) return imports;
2026
+ const header = `/* ${banner.replace(/\*\//g, "* /")} */`;
2027
+ return imports ? `${header}
2028
+ ${imports}
2029
+ ` : `${header}
2030
+ `;
2031
+ }
2032
+ function writeGeneratedFile(filePath, contents) {
2033
+ fs5.mkdirSync(path5.dirname(filePath), { recursive: true });
2034
+ fs5.writeFileSync(filePath, contents);
2035
+ }
2036
+
2037
+ // src/client_module.ts
2038
+ import {
2039
+ serializePublicClientConfig
2040
+ } from "@riebeckite/core";
2041
+ var clientModuleId = "virtual:riebeckite/client";
2042
+ var resolvedClientModuleId = `\0${clientModuleId}`;
2043
+ function riebeckiteClientModule(getConfig) {
2044
+ return {
2045
+ name: "riebeckite-client-module",
2046
+ resolveId(id) {
2047
+ if (id === clientModuleId) return resolvedClientModuleId;
2048
+ return null;
2049
+ },
2050
+ load(id) {
2051
+ if (id !== resolvedClientModuleId) return null;
2052
+ return createClientModule(getConfig());
2053
+ }
2054
+ };
2055
+ }
2056
+ function createClientModule(config) {
2057
+ const imports = [];
2058
+ const initializers = [];
2059
+ for (const [index, entry] of config.plugins.flatMap((plugin) => plugin.clientEntries ?? []).entries()) {
2060
+ const localName = `pluginClientInitializer${index}`;
2061
+ const importTarget = entry.exportName ? `{ ${entry.exportName} as ${localName} }` : localName;
2062
+ imports.push(
2063
+ `import ${importTarget} from ${JSON.stringify(entry.moduleSpecifier)};`
2064
+ );
2065
+ const publicConfig = entry.publicConfig;
2066
+ initializers.push(
2067
+ publicConfig === void 0 ? `${localName}()` : `${localName}(${serializePublicClientConfig(publicConfig)})`
2068
+ );
2069
+ }
2070
+ return `${imports.join("\n")}
2071
+
2072
+ export function initRiebeckiteClient() {
2073
+ ${initializers.map((initializer) => ` ${initializer};`).join("\n")}
2074
+ }
2075
+ `;
2076
+ }
2077
+
2078
+ // src/vite_runner.ts
2079
+ import fs6 from "node:fs/promises";
2080
+ import path6 from "node:path";
2081
+ import { build, createServer as createServer2 } from "vite";
2082
+ var viteConfigFileNames = [
2083
+ "vite.config.ts",
2084
+ "vite.config.js",
2085
+ "vite.config.mjs"
2086
+ ];
2087
+ async function resolveHonoxApplicationRoot(configRoot) {
2088
+ const roots = await findViteApplicationRoots(configRoot);
2089
+ if (roots.length === 1) return roots[0];
2090
+ if (roots.length === 0) {
2091
+ throw new HonoxApplicationRootError(
2092
+ `Could not find a Vite application under ${configRoot}.`
2093
+ );
2094
+ }
2095
+ throw new HonoxApplicationRootError(
2096
+ `Found multiple Vite applications under ${configRoot}: ${roots.join(", ")}.`
2097
+ );
2098
+ }
2099
+ var HonoxApplicationRootError = class extends Error {
2100
+ constructor(message) {
2101
+ super(message);
2102
+ this.name = "HonoxApplicationRootError";
2103
+ }
2104
+ };
2105
+ async function resolveHonoxApplication(options) {
2106
+ const configRoot = path6.resolve(options.configRoot);
2107
+ const appRoot = options.appRoot ? path6.resolve(options.appRoot) : await resolveHonoxApplicationRoot(configRoot);
2108
+ const workspaceRoot = options.workspaceRoot ?? await findWorkspaceRoot(configRoot);
2109
+ const rawConfig = await loadRiebeckiteConfig({
2110
+ configRoot,
2111
+ configFile: options.configFile,
2112
+ workspaceRoot
2113
+ });
2114
+ const config = resolveHonoxConfig(rawConfig, appRoot);
2115
+ return {
2116
+ config,
2117
+ configRoot,
2118
+ appRoot,
2119
+ contentRoot: config.content.directory
2120
+ };
2121
+ }
2122
+ async function findWorkspaceRoot(configRoot) {
2123
+ try {
2124
+ const workspaceConfig = path6.join(configRoot, "pnpm-workspace.yaml");
2125
+ return (await fs6.stat(workspaceConfig)).isFile() ? configRoot : void 0;
2126
+ } catch {
2127
+ return void 0;
2128
+ }
2129
+ }
2130
+ async function startHonoxDevServer(options) {
2131
+ const server2 = await createServer2({ root: options.root });
2132
+ await server2.listen();
2133
+ server2.printUrls();
2134
+ await waitForShutdown(server2);
2135
+ }
2136
+ async function buildHonoxApplication(options) {
2137
+ await runTraced(
2138
+ options.tracer,
2139
+ "integration.honox.client_build",
2140
+ () => build({ root: options.root, mode: "client" })
2141
+ );
2142
+ await runTraced(
2143
+ options.tracer,
2144
+ "integration.honox.server_build",
2145
+ () => build({ root: options.root })
2146
+ );
2147
+ }
2148
+ async function runTraced(tracer, name, buildTask) {
2149
+ return tracer ? await tracer.span(name, {}, buildTask) : await buildTask();
2150
+ }
2151
+ async function waitForShutdown(server2) {
2152
+ await new Promise((resolve) => {
2153
+ const close = () => {
2154
+ void server2.close().finally(resolve);
2155
+ };
2156
+ process.once("SIGINT", close);
2157
+ process.once("SIGTERM", close);
2158
+ });
2159
+ }
2160
+ async function findViteApplicationRoots(root) {
2161
+ const directories = [root];
2162
+ const applicationRoots = [];
2163
+ while (directories.length > 0) {
2164
+ const directory = directories.pop();
2165
+ if (!directory) continue;
2166
+ if (await hasViteConfig(directory)) applicationRoots.push(directory);
2167
+ const entries = await fs6.readdir(directory, { withFileTypes: true });
2168
+ for (const entry of entries) {
2169
+ if (!entry.isDirectory() || entry.name === "node_modules" || entry.name === ".git" || entry.name === "tests") {
2170
+ continue;
2171
+ }
2172
+ directories.push(path6.join(directory, entry.name));
2173
+ }
2174
+ }
2175
+ return applicationRoots;
2176
+ }
2177
+ async function hasViteConfig(directory) {
2178
+ for (const fileName of viteConfigFileNames) {
2179
+ try {
2180
+ if ((await fs6.stat(path6.join(directory, fileName))).isFile()) return true;
2181
+ } catch {
2182
+ }
2183
+ }
2184
+ return false;
2185
+ }
2186
+
2187
+ // src/vite_plugin.ts
2188
+ var defaultSsrExternals = [
2189
+ "extend",
2190
+ "debug",
2191
+ "node:fs/promises",
2192
+ "node:path",
2193
+ "parse-numeric-range",
2194
+ "slugify",
2195
+ "vfile-matter",
2196
+ "yaml"
2197
+ ];
2198
+ function riebeckite(options = {}) {
2199
+ let resolvedConfig;
2200
+ const getConfig = () => {
2201
+ if (!resolvedConfig) {
2202
+ throw new Error("Riebeckite config has not been loaded yet.");
2203
+ }
2204
+ return resolvedConfig;
2205
+ };
2206
+ return [
2207
+ {
2208
+ name: "riebeckite-host-integration",
2209
+ async config(userConfig) {
2210
+ const root = userConfig.root ? path7.resolve(userConfig.root) : process.cwd();
2211
+ const appRoot = options.appRoot ?? root;
2212
+ const application = await resolveHonoxApplication({
2213
+ configRoot: options.configRoot ?? appRoot,
2214
+ configFile: options.configFile,
2215
+ appRoot,
2216
+ workspaceRoot: options.workspaceRoot
2217
+ });
2218
+ resolvedConfig = application.config;
2219
+ writeRiebeckiteAssetEntries(resolvedConfig, {
2220
+ pluginStyles: path7.join(appRoot, "app/.riebeckite/plugin-styles.css"),
2221
+ themeStyles: path7.join(appRoot, "app/.riebeckite/theme-styles.css")
2222
+ });
2223
+ return {
2224
+ define: {
2225
+ "process.env.RIEBECKITE_APP_ROOT": JSON.stringify(appRoot)
2226
+ },
2227
+ resolve: {
2228
+ alias: options.workspaceRoot ? createWorkspacePackageAliases(options.workspaceRoot) : []
2229
+ }
2230
+ };
2231
+ }
2232
+ },
2233
+ riebeckiteClientModule(getConfig)
2234
+ ];
2235
+ }
2236
+ function riebeckiteVite(options = {}) {
2237
+ const { ssg, ssrExternals, ...integration } = options;
2238
+ return [
2239
+ ...riebeckite(integration),
2240
+ riebeckiteSsrExternals([...defaultSsrExternals, ...ssrExternals ?? []]),
2241
+ createRiebeckiteSsg(ssg)
2242
+ ];
2243
+ }
2244
+ function riebeckiteSsrExternals(externals) {
2245
+ return {
2246
+ name: "riebeckite-ssr-externals",
2247
+ config() {
2248
+ return {
2249
+ environments: {
2250
+ ssr: {
2251
+ resolve: {
2252
+ external: [...externals]
2253
+ }
2254
+ }
2255
+ }
2256
+ };
2257
+ }
2258
+ };
2259
+ }
2157
2260
  export {
2158
2261
  ScaffoldSiteError,
2159
2262
  buildHonoxApplication,
@@ -2161,6 +2264,7 @@ export {
2161
2264
  defaultSsgEntry,
2162
2265
  defaultSsrExternals,
2163
2266
  loadRiebeckiteConfig,
2267
+ replaceHonoxIslandDependencyPlugin,
2164
2268
  resolveHonoxApplication,
2165
2269
  resolveHonoxApplicationRoot,
2166
2270
  resolveHonoxConfig,
@@ -1,3 +1,3 @@
1
- import type { ResolvedRiebeckiteConfig } from "@riebeckite/core";
1
+ import { type ResolvedRiebeckiteConfig } from "@riebeckite/core";
2
2
  import type { Plugin } from "vite";
3
3
  export declare function riebeckiteClientModule(getConfig: () => ResolvedRiebeckiteConfig): Plugin;
@@ -0,0 +1,10 @@
1
+ import type { Plugin } from "vite";
2
+ type HonoxPlugin = Plugin | Promise<Plugin>;
3
+ /**
4
+ * Replaces HonoX's dependency walker with one that remains inside the app
5
+ * directory. Riebeckite configurations import plugins with large dependency
6
+ * graphs, which must not be traversed merely to determine whether a route
7
+ * imports an island.
8
+ */
9
+ export declare function replaceHonoxIslandDependencyPlugin(plugins: HonoxPlugin[]): HonoxPlugin[];
10
+ export {};
@@ -11,7 +11,7 @@ export type RiebeckiteIntegrationOptions = {
11
11
  * external. These are internal to the integration: sites should not have to
12
12
  * restate the Vite `environments.ssr.resolve.external` list.
13
13
  */
14
- export declare const defaultSsrExternals: readonly ["extend", "debug", "node:fs/promises", "node:path", "parse-numeric-range", "slugify", "vfile-matter"];
14
+ export declare const defaultSsrExternals: readonly ["extend", "debug", "node:fs/promises", "node:path", "parse-numeric-range", "slugify", "vfile-matter", "yaml"];
15
15
  export type RiebeckiteViteOptions = RiebeckiteIntegrationOptions & {
16
16
  /** Extra SSR externals appended after Riebeckite's defaults. */
17
17
  ssrExternals?: readonly string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/honox",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,10 +26,11 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
+ "@babel/parser": "^7.29.3",
29
30
  "esbuild": "^0.28.2",
30
31
  "hono": "^4.12.25",
31
32
  "vite": "^8.0.9",
32
- "@riebeckite/core": "0.0.1"
33
+ "@riebeckite/core": "0.0.3"
33
34
  },
34
35
  "publishConfig": {
35
36
  "access": "public"