@riebeckite/plugin-l10n 0.0.22 → 0.0.23

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 CHANGED
@@ -34,7 +34,7 @@ Conventions may be mixed. Built-in precedence is **frontmatter > custom detector
34
34
 
35
35
  `translation` is independent of locale and filename. Use it to group files with unrelated paths or names:
36
36
 
37
- ```text
37
+ ```
38
38
  日本語/はじめに.md lang: ja, translation: getting-started
39
39
  English/getting-started.md lang: en, translation: getting-started
40
40
  ```
@@ -45,26 +45,7 @@ The default language keeps Core's resolved URL (`/about`); other languages are p
45
45
 
46
46
  No fallback pages are generated. `getLocalization(manifest, slug)` returns `availableLanguages` and language-to-href `translations` only for notes that exist; `getLocalizedContent(manifest, slug, lang)` returns `null` for a missing translation.
47
47
 
48
- ## Standard LanguageSwitcher
49
-
50
- `l10n(...)` publishes the built-in, styled LanguageSwitcher in the standard `article.metadata` layout slot. A standard Site consumer renders that slot, so no l10n-specific article integration is needed. It is omitted when a page has fewer than two real translations.
51
-
52
- ```ts
53
- // Keep URLs and metadata but do not publish UI.
54
- l10n({ defaultLang: "ja", languages: ["ja", "en"], ui: false });
55
-
56
- // Use another standard slot, or replace the server-rendered component.
57
- l10n({
58
- defaultLang: "ja",
59
- languages: ["ja", "en"],
60
- ui: {
61
- slot: "article.footer",
62
- render: ({ localization }) => `<p>${localization.lang}</p>`,
63
- },
64
- });
65
- ```
66
-
67
- Themes can override the default component through its `.l10n-switcher` CSS classes. `ui.render` is framework-neutral HTML so custom Sites can supply their own server-rendered component without coupling the plugin to a specific app.
48
+ `l10n(...)` publishes the built-in, styled LanguageSwitcher in the standard article layout. A standard Site consumer renders that, so no l10n-specific article integration is needed. It is omitted when a page has fewer than two real translations.
68
49
 
69
50
  ## Custom detector
70
51
 
package/README_ja.md CHANGED
@@ -44,26 +44,7 @@ English/getting-started.md lang: en, translation: getting-started
44
44
 
45
45
  テーマは `getLocalization(manifest, slug)` から現在の言語、存在する言語、各翻訳の href を取得できます。`getLocalizedContent()` は翻訳がなければ `null` を返します。
46
46
 
47
- ## 標準 LanguageSwitcher
48
-
49
- `l10n(...)` は標準記事レイアウトの `article.metadata` スロットへ、組み込みの LanguageSwitcher を登録します。標準 Site consumer がこのスロットを描画するため、l10n 専用の記事レイアウト実装は不要です。実在する翻訳が 2 つ未満のページには表示されません。
50
-
51
- ```ts
52
- // URL とメタデータは維持し、UI だけを無効化します。
53
- l10n({ defaultLang: "ja", languages: ["ja", "en"], ui: false });
54
-
55
- // 配置の変更、またはサーバー描画コンポーネントの置換。
56
- l10n({
57
- defaultLang: "ja",
58
- languages: ["ja", "en"],
59
- ui: {
60
- slot: "article.footer",
61
- render: ({ localization }) => `<p>${localization.lang}</p>`,
62
- },
63
- });
64
- ```
65
-
66
- Theme は `.l10n-switcher` の CSS class を上書きできます。`ui.render` はフレームワーク非依存の HTML renderer なので、カスタム Site は任意のサーバー描画コンポーネントへ置き換えられます。
47
+ `l10n(...)` は標準記事レイアウトへ組み込みの言語切替 UI を登録します。標準 Site consumer がこの UI を描画するため、l10n 専用の記事レイアウト実装は不要です。実在する翻訳が 2 つ未満のページには表示されません。
67
48
 
68
49
  各ページには Core の `headTags` 拡張を通じ、実在する翻訳だけを対象に `hreflang` の alternate link を追加します。サイトシェルはこれらのタグの描画と、リクエストに応じた `<html lang>` の選択を担当します。WikiLink の Content Graph は同言語の翻訳を優先し、なければ元のリンク先を使います。本文では Obsidian WikiLink を `@riebeckite/plugin-obsidian-markdown` が解決した後、WikiLink と Markdown の内部リンクを同じ規則で処理します。現在のページと同じ言語の翻訳があればその URL に切り替え、なければ original/default のリンク先を維持します。クエリ文字列とフラグメントは維持し、外部 URL、フラグメントのみのリンク、不明な URL、asset などコンテンツ以外の URL は変更しません。Content Graph と本文リンクは同じ解決ポリシーを使います。
69
50
 
@@ -0,0 +1,6 @@
1
+ import type { LocalizedContent } from "../src/l10n.js";
2
+ export type LanguageSwitcherProps = {
3
+ localization: LocalizedContent | null;
4
+ };
5
+ declare const LanguageSwitcher: (props: Readonly<LanguageSwitcherProps>) => import("hono/jsx/jsx-dev-runtime").JSX.Element;
6
+ export default LanguageSwitcher;
@@ -0,0 +1,28 @@
1
+ // components/language-switcher.tsx
2
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
3
+ var LanguageSwitcher = ((props) => {
4
+ const localization = props.localization;
5
+ if (!localization || localization.availableLanguages.length < 2) return null;
6
+ return /* @__PURE__ */ jsxs("nav", { class: "l10n-switcher", "aria-label": "Language", children: [
7
+ /* @__PURE__ */ jsx("span", { class: "l10n-switcher__label", children: "Language" }),
8
+ /* @__PURE__ */ jsx("ul", { class: "l10n-switcher__list", children: localization.availableLanguages.map((lang) => {
9
+ const href = localization.translations[lang];
10
+ if (!href) return null;
11
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
12
+ "a",
13
+ {
14
+ class: "l10n-switcher__link",
15
+ href,
16
+ hreflang: lang,
17
+ lang,
18
+ "aria-current": lang === localization.lang ? "page" : void 0,
19
+ children: lang
20
+ }
21
+ ) }, lang);
22
+ }) })
23
+ ] });
24
+ });
25
+ var language_switcher_default = LanguageSwitcher;
26
+ export {
27
+ language_switcher_default as default
28
+ };
package/dist/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export { getLanguageFromPath, getLocalization, getLocalizedContent, type L10nContent, type L10nDetectorContext, type L10nDetectorResult, type L10nOptions, type L10nUiOptions, type LanguageSwitcherRenderContext, type LocalizedContent, l10n, l10nPlugin, renderLanguageSwitcher, } from "./src/l10n.js";
1
+ export type { LanguageSwitcherProps } from "./components/language-switcher.js";
2
+ export { default as LanguageSwitcher } from "./components/language-switcher.js";
3
+ export { getLanguageFromPath, getLocalization, getLocalizedContent, type L10nContent, type L10nDetectorContext, type L10nDetectorResult, type L10nOptions, type LocalizedContent, l10n, l10nPlugin, } from "./src/l10n.js";
package/dist/index.js CHANGED
@@ -1,43 +1,57 @@
1
+ // components/language-switcher.tsx
2
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
3
+ var LanguageSwitcher = ((props) => {
4
+ const localization = props.localization;
5
+ if (!localization || localization.availableLanguages.length < 2) return null;
6
+ return /* @__PURE__ */ jsxs("nav", { class: "l10n-switcher", "aria-label": "Language", children: [
7
+ /* @__PURE__ */ jsx("span", { class: "l10n-switcher__label", children: "Language" }),
8
+ /* @__PURE__ */ jsx("ul", { class: "l10n-switcher__list", children: localization.availableLanguages.map((lang) => {
9
+ const href = localization.translations[lang];
10
+ if (!href) return null;
11
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
12
+ "a",
13
+ {
14
+ class: "l10n-switcher__link",
15
+ href,
16
+ hreflang: lang,
17
+ lang,
18
+ "aria-current": lang === localization.lang ? "page" : void 0,
19
+ children: lang
20
+ }
21
+ ) }, lang);
22
+ }) })
23
+ ] });
24
+ });
25
+ var language_switcher_default = LanguageSwitcher;
26
+
1
27
  // src/l10n.ts
2
28
  import {
3
- appendContentBodySlot,
4
29
  attachErrorPath,
5
30
  createStyleAsset,
6
31
  definePlugin
7
32
  } from "@riebeckite/core";
8
33
  import { parse } from "yaml";
9
-
10
- // src/language-switcher.ts
11
- import { escapeHtml, escapeHtmlAttribute } from "@riebeckite/core";
12
- function renderLanguageSwitcher({
13
- localization
14
- }) {
15
- if (localization.availableLanguages.length < 2) return null;
16
- const links = localization.availableLanguages.map((lang) => {
17
- const href = localization.translations[lang];
18
- if (!href) return "";
19
- const current = lang === localization.lang ? ' aria-current="page"' : "";
20
- const escaped = escapeHtml(lang);
21
- return `<li><a class="l10n-switcher__link" href="${escapeHtmlAttribute(href)}" hreflang="${escapeHtmlAttribute(lang)}" lang="${escapeHtmlAttribute(lang)}"${current}>${escaped}</a></li>`;
22
- }).join("");
23
- if (!links) return null;
24
- return `<nav class="l10n-switcher" aria-label="Language"><span class="l10n-switcher__label">Language</span><ul class="l10n-switcher__list">${links}</ul></nav>`;
25
- }
26
-
27
- // src/l10n.ts
28
34
  var TRANSLATION_METADATA_KEY = "l10n.translationId";
29
35
  function l10n(options) {
30
36
  const resolved = resolveOptions(options);
31
37
  let state = emptyState();
32
38
  return definePlugin({
33
39
  name: "l10n",
40
+ processedContentCache: {
41
+ version: "l10n-global-content-locations-v1",
42
+ dependencyMode: "global"
43
+ },
34
44
  provides: ["content.localization"],
35
- outputDependencies: [{ type: "global" }],
45
+ contentOutputDependencies: [{ type: "global" }],
36
46
  options,
37
- assets: [createStyleAsset("l10n")],
47
+ assets: [createStyleAsset("l10n", "@riebeckite/plugin-l10n/style.css")],
38
48
  validateOptions: () => validateOptions(options).map((message) => ({ path: "l10n", message })),
39
49
  extendContentLocations: ({ entries, locations }) => {
40
- state = { ...detectContents(entries, resolved), locations };
50
+ state = {
51
+ ...detectContents(entries, resolved),
52
+ locations,
53
+ slugsByPermalink: /* @__PURE__ */ new Map()
54
+ };
41
55
  throwForStrictDiagnostics(state.diagnostics, resolved.strict);
42
56
  for (const content of state.contents.values()) {
43
57
  const location = locations.get(content.slug);
@@ -47,6 +61,12 @@ function l10n(options) {
47
61
  withLocalization(location, content, resolved)
48
62
  );
49
63
  }
64
+ state = {
65
+ ...state,
66
+ slugsByPermalink: new Map(
67
+ [...locations].map(([slug, location]) => [location.permalink, slug])
68
+ )
69
+ };
50
70
  },
51
71
  extendMarkdownPipeline: (pipeline, context) => {
52
72
  pipeline.use(remarkLocalizedLinks, {
@@ -68,7 +88,6 @@ function l10n(options) {
68
88
  },
69
89
  onManifestCreated: ({ manifest }) => {
70
90
  addLocalizationHeadTags(manifest, state);
71
- addLanguageSwitchers(manifest, resolved.ui);
72
91
  },
73
92
  addDiagnostics: () => state.diagnostics
74
93
  });
@@ -78,13 +97,7 @@ function remarkLocalizedLinks(options) {
78
97
  return (tree) => {
79
98
  const source = options.sourceSlug ? options.state.contents.get(options.sourceSlug) : void 0;
80
99
  if (!source || !options.state.locations) return;
81
- const slugsByPermalink = new Map(
82
- [...options.state.locations].map(([slug, location]) => [
83
- location.permalink,
84
- slug
85
- ])
86
- );
87
- localizeLinks(tree, source, options, slugsByPermalink);
100
+ localizeLinks(tree, source, options, options.state.slugsByPermalink);
88
101
  };
89
102
  }
90
103
  function localizeLinks(node, source, options, slugsByPermalink) {
@@ -106,13 +119,13 @@ function splitLinkUrl(url) {
106
119
  const suffixIndex = url.search(/[?#]/);
107
120
  return suffixIndex < 0 ? { permalink: url, suffix: "" } : { permalink: url.slice(0, suffixIndex), suffix: url.slice(suffixIndex) };
108
121
  }
109
- function getLocalization(manifest, slug) {
110
- const entry = manifest.bySlug.get(slug);
122
+ function getLocalization(view, slug) {
123
+ const entry = findLocalizedEntry(view, slug);
111
124
  if (!entry) return null;
112
125
  const lang = entry.publicLocation.language;
113
126
  const translationId = entry.publicLocation.metadata?.[TRANSLATION_METADATA_KEY];
114
127
  if (!lang || !translationId) return null;
115
- const candidates = manifest.discoverableEntries.filter(
128
+ const candidates = getLocalizedDiscoverableEntries(view).filter(
116
129
  (candidate) => candidate.publicLocation.metadata?.[TRANSLATION_METADATA_KEY] === translationId
117
130
  );
118
131
  const translations = Object.fromEntries(
@@ -130,6 +143,12 @@ function getLocalization(manifest, slug) {
130
143
  translations
131
144
  };
132
145
  }
146
+ function findLocalizedEntry(view, slug) {
147
+ return "findRoutableBySlug" in view ? view.findRoutableBySlug(slug) : view.bySlug.get(slug);
148
+ }
149
+ function getLocalizedDiscoverableEntries(view) {
150
+ return view.discoverableEntries;
151
+ }
133
152
  function getLocalizedContent(manifest, slug, lang) {
134
153
  const localization = getLocalization(manifest, slug);
135
154
  if (!localization) return null;
@@ -158,8 +177,7 @@ function resolveOptions(options) {
158
177
  languages.map((language) => [language.toLowerCase(), language])
159
178
  ),
160
179
  strict: options.strict ?? false,
161
- detect: options.detect,
162
- ui: resolveUiOptions(options.ui)
180
+ detect: options.detect
163
181
  };
164
182
  }
165
183
  function validateOptions(options) {
@@ -194,24 +212,8 @@ function validateOptions(options) {
194
212
  if (options.detect !== void 0 && typeof options.detect !== "function") {
195
213
  errors.push("l10n.detect must be a function.");
196
214
  }
197
- if (options.ui !== void 0 && options.ui !== false) {
198
- if (typeof options.ui !== "object") {
199
- errors.push("l10n.ui must be false or an object.");
200
- } else if (options.ui.slot !== void 0 && (typeof options.ui.slot !== "string" || !options.ui.slot.trim())) {
201
- errors.push("l10n.ui.slot must be a non-empty string.");
202
- } else if (options.ui.render !== void 0 && typeof options.ui.render !== "function") {
203
- errors.push("l10n.ui.render must be a function.");
204
- }
205
- }
206
215
  return errors;
207
216
  }
208
- function resolveUiOptions(ui) {
209
- if (ui === false) return false;
210
- return {
211
- slot: ui?.slot ?? "article.metadata",
212
- render: ui?.render ?? renderLanguageSwitcher
213
- };
214
- }
215
217
  function canonicalLanguage(value) {
216
218
  if (typeof value !== "string" || !value.trim()) {
217
219
  throw new Error("A l10n language tag must be a non-empty string.");
@@ -224,6 +226,7 @@ function canonicalLanguage(value) {
224
226
  }
225
227
  function detectContents(entries, options) {
226
228
  const contents = /* @__PURE__ */ new Map();
229
+ const contentsByTranslationAndLanguage = /* @__PURE__ */ new Map();
227
230
  const diagnostics = [];
228
231
  const owners = /* @__PURE__ */ new Map();
229
232
  const conflictedGroups = /* @__PURE__ */ new Set();
@@ -284,9 +287,17 @@ function detectContents(entries, options) {
284
287
  diagnostics.push(duplicateDiagnostic(previous, content, options.strict));
285
288
  } else {
286
289
  owners.set(key, content);
290
+ contentsByTranslationAndLanguage.set(key, content);
287
291
  }
288
292
  }
289
- return { contents, diagnostics, conflictedGroups, locations: null };
293
+ return {
294
+ contents,
295
+ contentsByTranslationAndLanguage,
296
+ diagnostics,
297
+ conflictedGroups,
298
+ locations: null,
299
+ slugsByPermalink: /* @__PURE__ */ new Map()
300
+ };
290
301
  }
291
302
  function parseFrontmatter(entry) {
292
303
  const match = entry.markdown.match(
@@ -375,9 +386,7 @@ function escapeRegExp(value) {
375
386
  function findTranslation(state, translationId, lang) {
376
387
  const key = `${translationId}\0${lang}`;
377
388
  if (state.conflictedGroups.has(key)) return null;
378
- return [...state.contents.values()].find(
379
- (content) => content.translationId === translationId && content.lang === lang
380
- ) ?? null;
389
+ return state.contentsByTranslationAndLanguage.get(key) ?? null;
381
390
  }
382
391
  function resolveLocalizedTarget(state, source, targetSlug) {
383
392
  const target = state.contents.get(targetSlug);
@@ -385,14 +394,11 @@ function resolveLocalizedTarget(state, source, targetSlug) {
385
394
  return findTranslation(state, target.translationId, source.lang) ?? target;
386
395
  }
387
396
  function addLocalizationHeadTags(manifest, state) {
397
+ const translationsById = collectDiscoverableTranslations(manifest);
388
398
  for (const entry of manifest.discoverableEntries) {
389
399
  const content = state.contents.get(entry.slug);
390
400
  if (!content) continue;
391
- const translations = uniqueLanguageEntries(
392
- manifest.discoverableEntries.filter(
393
- (candidate) => candidate.publicLocation.metadata?.[TRANSLATION_METADATA_KEY] === content.translationId
394
- )
395
- );
401
+ const translations = translationsById.get(content.translationId) ?? [];
396
402
  const headTags = translations.map(
397
403
  (translation) => ({
398
404
  tag: "link",
@@ -411,25 +417,35 @@ function addLocalizationHeadTags(manifest, state) {
411
417
  ];
412
418
  }
413
419
  }
414
- function addLanguageSwitchers(manifest, ui) {
415
- if (ui === false) return;
420
+ function collectDiscoverableTranslations(manifest) {
421
+ const candidatesById = /* @__PURE__ */ new Map();
416
422
  for (const entry of manifest.discoverableEntries) {
417
- const localization = getLocalization(manifest, entry.slug);
418
- if (!localization) continue;
419
- const html = ui.render({ localization });
420
- if (html && !entry.bodySlots?.[ui.slot]?.includes(html)) {
421
- appendContentBodySlot(entry, ui.slot, html);
422
- }
423
+ const translationId = entry.publicLocation.metadata?.[TRANSLATION_METADATA_KEY];
424
+ if (!translationId) continue;
425
+ const candidates = candidatesById.get(translationId) ?? [];
426
+ candidates.push(entry);
427
+ candidatesById.set(translationId, candidates);
423
428
  }
429
+ return new Map(
430
+ [...candidatesById].map(([translationId, candidates]) => [
431
+ translationId,
432
+ uniqueLanguageEntries(candidates)
433
+ ])
434
+ );
424
435
  }
425
436
  function sameHeadTag(left, right) {
426
437
  return left.tag === right.tag && left.attrs?.rel === right.attrs?.rel && left.attrs?.hreflang === right.attrs?.hreflang && left.attrs?.href === right.attrs?.href;
427
438
  }
428
439
  function uniqueLanguageEntries(entries) {
429
- return entries.filter((entry) => {
430
- const lang = entry.publicLocation.language;
431
- return lang !== void 0 && entries.filter((other) => other.publicLocation.language === lang).length === 1;
432
- });
440
+ const entriesByLanguage = /* @__PURE__ */ new Map();
441
+ for (const entry of entries) {
442
+ const language = entry.publicLocation.language;
443
+ if (!language) continue;
444
+ const candidates = entriesByLanguage.get(language) ?? [];
445
+ candidates.push(entry);
446
+ entriesByLanguage.set(language, candidates);
447
+ }
448
+ return [...entriesByLanguage.values()].filter((candidates) => candidates.length === 1).flatMap((candidates) => candidates[0] ? [candidates[0]] : []);
433
449
  }
434
450
  function compactSignals(signals) {
435
451
  return Object.fromEntries(
@@ -489,16 +505,18 @@ function throwForStrictDiagnostics(diagnostics, strict) {
489
505
  function emptyState() {
490
506
  return {
491
507
  contents: /* @__PURE__ */ new Map(),
508
+ contentsByTranslationAndLanguage: /* @__PURE__ */ new Map(),
492
509
  diagnostics: [],
493
510
  conflictedGroups: /* @__PURE__ */ new Set(),
494
- locations: null
511
+ locations: null,
512
+ slugsByPermalink: /* @__PURE__ */ new Map()
495
513
  };
496
514
  }
497
515
  export {
516
+ language_switcher_default as LanguageSwitcher,
498
517
  getLanguageFromPath,
499
518
  getLocalization,
500
519
  getLocalizedContent,
501
520
  l10n,
502
- l10nPlugin,
503
- renderLanguageSwitcher
521
+ l10nPlugin
504
522
  };
@@ -1,4 +1,4 @@
1
- import { type ContentBodySlot, type ContentManifest, type ContentManifestEntry, type PostFrontmatter } from "@riebeckite/core";
1
+ import { type ContentManifest, type ContentManifestEntry, type PostFrontmatter, type PublicContentView } from "@riebeckite/core";
2
2
  export type L10nContent = {
3
3
  readonly path: string;
4
4
  readonly slug: string;
@@ -17,17 +17,6 @@ export type L10nOptions = {
17
17
  languages: readonly string[];
18
18
  strict?: boolean;
19
19
  detect?: (content: L10nDetectorContext) => L10nDetectorResult | undefined;
20
- /**
21
- * Publishes the built-in switcher into a standard article layout slot.
22
- * Pass `false` to keep localization metadata and URLs without UI.
23
- */
24
- ui?: L10nUiOptions;
25
- };
26
- export type L10nUiOptions = false | {
27
- /** Defaults to the standard `article.metadata` slot. */
28
- slot?: ContentBodySlot;
29
- /** Replaces the built-in server-rendered LanguageSwitcher. */
30
- render?: (context: LanguageSwitcherRenderContext) => string | null;
31
20
  };
32
21
  export type LocalizedContent = {
33
22
  readonly slug: string;
@@ -37,14 +26,10 @@ export type LocalizedContent = {
37
26
  readonly availableLanguages: readonly string[];
38
27
  readonly translations: Readonly<Record<string, string>>;
39
28
  };
40
- export type LanguageSwitcherRenderContext = {
41
- readonly localization: LocalizedContent;
42
- };
43
29
  export declare function l10n(options: L10nOptions): import("@riebeckite/core").RiebeckitePlugin<L10nOptions>;
44
30
  export declare const l10nPlugin: typeof l10n;
45
31
  /** Returns one entry's language and available real translations. */
46
- export declare function getLocalization(manifest: ContentManifest, slug: string): LocalizedContent | null;
32
+ export declare function getLocalization(view: ContentManifest | PublicContentView, slug: string): LocalizedContent | null;
47
33
  /** Resolves an existing translation; missing translations return `null`. */
48
34
  export declare function getLocalizedContent(manifest: ContentManifest, slug: string, lang: string): ContentManifestEntry | null;
49
35
  export declare function getLanguageFromPath(manifest: ContentManifest, pathname: string): string | undefined;
50
- export { renderLanguageSwitcher } from "./language-switcher.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-l10n",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,15 +12,22 @@
12
12
  "source": "./index.ts",
13
13
  "default": "./dist/index.js"
14
14
  },
15
+ "./components": {
16
+ "types": "./dist/components/language-switcher.d.ts",
17
+ "import": "./dist/components/language-switcher.js",
18
+ "source": "./components/language-switcher.tsx",
19
+ "default": "./dist/components/language-switcher.js"
20
+ },
15
21
  "./style.css": "./style.css"
16
22
  },
17
23
  "dependencies": {
24
+ "hono": "^4.12.25",
18
25
  "yaml": "^2.9.0",
19
- "@riebeckite/core": "0.0.22"
26
+ "@riebeckite/core": "0.0.23"
20
27
  },
21
28
  "devDependencies": {
22
29
  "tsx": "^4.22.4",
23
- "@riebeckite/plugin-obsidian-markdown": "0.0.22"
30
+ "@riebeckite/plugin-obsidian-markdown": "0.0.23"
24
31
  },
25
32
  "publishConfig": {
26
33
  "access": "public"
@@ -1,3 +0,0 @@
1
- import type { LanguageSwitcherRenderContext } from "./l10n.js";
2
- /** Framework-neutral default renderer for the standard LanguageSwitcher. */
3
- export declare function renderLanguageSwitcher({ localization, }: LanguageSwitcherRenderContext): string | null;