@verbaly/vue 0.22.0 → 0.23.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <img src="https://raw.githubusercontent.com/AronSoto/verbaly/develop/assets/logo.png" alt="Verbaly" width="300" />
3
3
  </p>
4
4
 
5
- <p align="center"><em>Vue 3 bindings for Verbaly composables over the reactive core.</em></p>
5
+ <p align="center"><em>Vue 3 bindings for Verbaly: composables over the reactive core.</em></p>
6
6
 
7
7
  <p align="center">
8
8
  <a href="https://www.npmjs.com/package/@verbaly/vue"><img src="https://img.shields.io/npm/v/@verbaly/vue?logo=npm&color=cb3837" alt="npm version" /></a>
@@ -11,7 +11,7 @@
11
11
 
12
12
  ---
13
13
 
14
- Vue 3 composables for [Verbaly](https://github.com/AronSoto/verbaly) a thin layer over the reactive core with per-component cleanup (`onScopeDispose`).
14
+ Vue 3 composables for [Verbaly](https://github.com/AronSoto/verbaly): a thin layer over the reactive core with per-component cleanup (`onScopeDispose`).
15
15
 
16
16
  ## 🚀 Install
17
17
 
@@ -39,7 +39,7 @@ app.use(verbalyPlugin(verbaly));
39
39
  </template>
40
40
  ```
41
41
 
42
- Or skip the keys entirely write the source text in place and the compiler extracts it, right in your `.vue` files (script and template):
42
+ Or skip the keys entirely: write the source text in place and the compiler extracts it, right in your `.vue` files (script and template):
43
43
 
44
44
  ```html
45
45
  <template>
@@ -47,7 +47,7 @@ Or skip the keys entirely — write the source text in place and the compiler ex
47
47
  </template>
48
48
  ```
49
49
 
50
- ### ✨ Rich text `<Trans>`
50
+ ### ✨ Rich text: `<Trans>`
51
51
 
52
52
  ```html
53
53
  <script setup>
@@ -61,7 +61,7 @@ Or skip the keys entirely — write the source text in place and the compiler ex
61
61
  </template>
62
62
  ```
63
63
 
64
- Named links without render functions hrefs come from your code, never from messages (`javascript:` blocked):
64
+ Whitelisted phrasing tags in a message (`<em>`, `<code>`…) render as real elements, same whitelist as `data-verbaly-rich` (`richTags` overrides it); unknown tags unwrap to inert text. Named links need no render functions; hrefs come from your code, never from messages (`javascript:` blocked):
65
65
 
66
66
  ```html
67
67
  <!-- message: 'Read the <docs>guide</docs>' -->
@@ -70,7 +70,7 @@ Named links without render functions — hrefs come from your code, never from m
70
70
 
71
71
  📖 Docs: **https://verbaly-web.vercel.app/docs/frameworks**
72
72
 
73
- > ⚠️ Early development (`0.x`) API not stable yet.
73
+ > ⚠️ Early development (`0.x`): API not stable yet.
74
74
 
75
75
  ## License
76
76
 
package/dist/index.cjs CHANGED
@@ -52,32 +52,41 @@ const Trans = (0, vue.defineComponent)({
52
52
  type: Object,
53
53
  default: void 0
54
54
  },
55
+ instance: {
56
+ type: Object,
57
+ default: void 0
58
+ },
55
59
  components: {
56
60
  type: Object,
57
61
  default: () => ({})
58
62
  },
63
+ richTags: {
64
+ type: Array,
65
+ default: void 0
66
+ },
59
67
  links: {
60
68
  type: Object,
61
69
  default: () => ({})
62
70
  }
63
71
  },
64
72
  setup(props) {
65
- const instance = useVerbaly();
73
+ const instance = props.instance ?? useVerbaly();
66
74
  const version = trackVersion(instance);
67
75
  return () => {
68
76
  version.value;
69
- return (0, vue.h)(vue.Fragment, toNodes((0, verbaly.parseTags)(instance.t(props.id, props.values)), props.components, props.links));
77
+ return (0, vue.h)(vue.Fragment, toNodes((0, verbaly.parseTags)(instance.t(props.id, props.values)), props.components, props.links, new Set(props.richTags ?? verbaly.RICH_TAGS)));
70
78
  };
71
79
  }
72
80
  });
73
- function toNodes(nodes, components, links) {
81
+ function toNodes(nodes, components, links, richTags) {
74
82
  return nodes.map((node) => {
75
83
  if (typeof node === "string") return node;
76
- const children = toNodes(node.children, components, links);
84
+ const children = toNodes(node.children, components, links, richTags);
77
85
  const fn = components[node.name];
78
86
  if (fn) return fn(children);
79
87
  const link = links[node.name];
80
88
  if (link !== void 0) return (0, vue.h)("a", (0, verbaly.normalizeLink)(link), children);
89
+ if (richTags.has(node.name)) return (0, vue.h)(node.name, null, children);
81
90
  return children;
82
91
  });
83
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Fragment"],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\nexport function useT<D extends DictionaryInput = DictionaryInput>(): TFunction<D> {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as TFunction<D>).id = instance.t.id;\n return t as TFunction<D>;\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(Fragment, toNodes(parseTags(text), props.components, props.links));\n };\n },\n});\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links);\n const fn = components[node.name];\n if (fn) return fn(children);\n const link = links[node.name];\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;;AA0BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;AAEA,SAAgB,aAAsE;CACpF,MAAM,YAAA,GAAA,IAAA,OAAA,CAAkB,KAAK,IAAI;CACjC,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,2DAA2D;CAE7E,OAAO;AACT;AAEA,SAAgB,OAAkE;CAChF,MAAM,WAAW,WAAc;CAC/B,MAAM,UAAU,aAAa,QAAQ;CACrC,MAAM,KAAK,OAAgB,GAAG,SAA4B;EACxD,QAAa;EACb,OAAQ,SAAS,EAAgD,OAAO,GAAG,IAAI;CACjF;CAEA,EAAoB,KAAK,SAAS,EAAE;CACpC,OAAO;AACT;AAEA,SAAgB,YAAyC;CACvD,MAAM,WAAW,WAAW;CAC5B,MAAM,UAAU,aAAa,QAAQ;CACrC,QAAA,GAAA,IAAA,SAAA,CAAgB;EACd,WAAW;GACT,QAAa;GACb,OAAO,SAAS;EAClB;EACA,MAAM,WAAmB,SAAS,UAAU,MAAM;CACpD,CAAC;AACH;AAEA,SAAS,aAAwC,UAA0C;CACzF,MAAM,WAAA,GAAA,IAAA,WAAA,CAAqB,SAAS,OAAO;CAC3C,CAAA,GAAA,IAAA,eAAA,CACE,SAAS,gBAAgB;EACvB,QAAQ,QAAQ,SAAS;CAC3B,CAAC,CACH;CACA,OAAO;AACT;AAKA,MAAa,SAAA,GAAA,IAAA,gBAAA,CAAwB;CACnC,MAAM;CACN,OAAO;EACL,IAAI;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnC,QAAQ;GAAE,MAAM;GAA4B,SAAS,KAAA;EAAU;EAC/D,YAAY;GAAE,MAAM;GAAqC,gBAAgB,CAAC;EAAG;EAC7E,OAAO;GAAE,MAAM;GAA8C,gBAAgB,CAAC;EAAG;CACnF;CACA,MAAM,OAAO;EACX,MAAM,WAAW,WAAW;EAC5B,MAAM,UAAU,aAAa,QAAQ;EACrC,aAAa;GACX,QAAa;GAKb,QAAA,GAAA,IAAA,EAAA,CAASA,IAAAA,UAAU,SAAA,GAAA,QAAA,UAAA,CAJL,SAAS,EACrB,MAAM,IACN,MAAM,MAEgC,CAAC,GAAG,MAAM,YAAY,MAAM,KAAK,CAAC;EAC5E;CACF;AACF,CAAC;AAED,SAAS,QACP,OACA,YACA,OACc;CACd,OAAO,MAAM,KAAK,SAAS;EACzB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,WAAW,QAAQ,KAAK,UAAU,YAAY,KAAK;EACzD,MAAM,KAAK,WAAW,KAAK;EAC3B,IAAI,IAAI,OAAO,GAAG,QAAQ;EAC1B,MAAM,OAAO,MAAM,KAAK;EACxB,IAAI,SAAS,KAAA,GACX,QAAA,GAAA,IAAA,EAAA,CAAS,MAAA,GAAA,QAAA,cAAA,CAAmB,IAAI,GAAG,QAAQ;EAE7C,OAAO;CACT,CAAC;AACH"}
1
+ {"version":3,"file":"index.cjs","names":["Fragment","RICH_TAGS"],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\nexport function useT<D extends DictionaryInput = DictionaryInput>(): TFunction<D> {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as TFunction<D>).id = instance.t.id;\n return t as TFunction<D>;\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = components[node.name];\n if (fn) return fn(children);\n const link = links[node.name];\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;;AA2BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;AAEA,SAAgB,aAAsE;CACpF,MAAM,YAAA,GAAA,IAAA,OAAA,CAAkB,KAAK,IAAI;CACjC,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,2DAA2D;CAE7E,OAAO;AACT;AAEA,SAAgB,OAAkE;CAChF,MAAM,WAAW,WAAc;CAC/B,MAAM,UAAU,aAAa,QAAQ;CACrC,MAAM,KAAK,OAAgB,GAAG,SAA4B;EACxD,QAAa;EACb,OAAQ,SAAS,EAAgD,OAAO,GAAG,IAAI;CACjF;CAEA,EAAoB,KAAK,SAAS,EAAE;CACpC,OAAO;AACT;AAEA,SAAgB,YAAyC;CACvD,MAAM,WAAW,WAAW;CAC5B,MAAM,UAAU,aAAa,QAAQ;CACrC,QAAA,GAAA,IAAA,SAAA,CAAgB;EACd,WAAW;GACT,QAAa;GACb,OAAO,SAAS;EAClB;EACA,MAAM,WAAmB,SAAS,UAAU,MAAM;CACpD,CAAC;AACH;AAEA,SAAS,aAAwC,UAA0C;CACzF,MAAM,WAAA,GAAA,IAAA,WAAA,CAAqB,SAAS,OAAO;CAC3C,CAAA,GAAA,IAAA,eAAA,CACE,SAAS,gBAAgB;EACvB,QAAQ,QAAQ,SAAS;CAC3B,CAAC,CACH;CACA,OAAO;AACT;AAKA,MAAa,SAAA,GAAA,IAAA,gBAAA,CAAwB;CACnC,MAAM;CACN,OAAO;EACL,IAAI;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnC,QAAQ;GAAE,MAAM;GAA4B,SAAS,KAAA;EAAU;EAC/D,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,YAAY;GAAE,MAAM;GAAqC,gBAAgB,CAAC;EAAG;EAC7E,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,OAAO;GAAE,MAAM;GAA8C,gBAAgB,CAAC;EAAG;CACnF;CACA,MAAM,OAAO;EACX,MAAM,WAAW,MAAM,YAAY,WAAW;EAC9C,MAAM,UAAU,aAAa,QAAQ;EACrC,aAAa;GACX,QAAa;GAKb,QAAA,GAAA,IAAA,EAAA,CACEA,IAAAA,UACA,SAAA,GAAA,QAAA,UAAA,CANY,SAAS,EACrB,MAAM,IACN,MAAM,MAKS,CAAC,GACd,MAAM,YACN,MAAM,OACN,IAAI,IAAI,MAAM,YAAYC,QAAAA,SAAS,CACrC,CACF;EACF;CACF;AACF,CAAC;AAED,SAAS,QACP,OACA,YACA,OACA,UACc;CACd,OAAO,MAAM,KAAK,SAAS;EACzB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,WAAW,QAAQ,KAAK,UAAU,YAAY,OAAO,QAAQ;EACnE,MAAM,KAAK,WAAW,KAAK;EAC3B,IAAI,IAAI,OAAO,GAAG,QAAQ;EAC1B,MAAM,OAAO,MAAM,KAAK;EACxB,IAAI,SAAS,KAAA,GACX,QAAA,GAAA,IAAA,EAAA,CAAS,MAAA,GAAA,QAAA,cAAA,CAAmB,IAAI,GAAG,QAAQ;EAE7C,IAAI,SAAS,IAAI,KAAK,IAAI,GACxB,QAAA,GAAA,IAAA,EAAA,CAAS,KAAK,MAAM,MAAM,QAAQ;EAEpC,OAAO;CACT,CAAC;AACH"}
package/dist/index.d.cts CHANGED
@@ -18,10 +18,18 @@ declare const Trans: import("vue").DefineComponent<import("vue").ExtractPropType
18
18
  type: PropType<Params>;
19
19
  default: undefined;
20
20
  };
21
+ instance: {
22
+ type: PropType<Verbaly>;
23
+ default: undefined;
24
+ };
21
25
  components: {
22
26
  type: PropType<TransComponents>;
23
27
  default: () => {};
24
28
  };
29
+ richTags: {
30
+ type: PropType<string[]>;
31
+ default: undefined;
32
+ };
25
33
  links: {
26
34
  type: PropType<Record<string, RichLink>>;
27
35
  default: () => {};
@@ -37,17 +45,27 @@ declare const Trans: import("vue").DefineComponent<import("vue").ExtractPropType
37
45
  type: PropType<Params>;
38
46
  default: undefined;
39
47
  };
48
+ instance: {
49
+ type: PropType<Verbaly>;
50
+ default: undefined;
51
+ };
40
52
  components: {
41
53
  type: PropType<TransComponents>;
42
54
  default: () => {};
43
55
  };
56
+ richTags: {
57
+ type: PropType<string[]>;
58
+ default: undefined;
59
+ };
44
60
  links: {
45
61
  type: PropType<Record<string, RichLink>>;
46
62
  default: () => {};
47
63
  };
48
64
  }>> & Readonly<{}>, {
49
65
  values: Params;
66
+ instance: Verbaly<DictionaryInput>;
50
67
  components: TransComponents;
68
+ richTags: string[];
51
69
  links: Record<string, RichLink>;
52
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
53
71
  //#endregion
package/dist/index.d.ts CHANGED
@@ -18,10 +18,18 @@ declare const Trans: import("vue").DefineComponent<import("vue").ExtractPropType
18
18
  type: PropType<Params>;
19
19
  default: undefined;
20
20
  };
21
+ instance: {
22
+ type: PropType<Verbaly>;
23
+ default: undefined;
24
+ };
21
25
  components: {
22
26
  type: PropType<TransComponents>;
23
27
  default: () => {};
24
28
  };
29
+ richTags: {
30
+ type: PropType<string[]>;
31
+ default: undefined;
32
+ };
25
33
  links: {
26
34
  type: PropType<Record<string, RichLink>>;
27
35
  default: () => {};
@@ -37,17 +45,27 @@ declare const Trans: import("vue").DefineComponent<import("vue").ExtractPropType
37
45
  type: PropType<Params>;
38
46
  default: undefined;
39
47
  };
48
+ instance: {
49
+ type: PropType<Verbaly>;
50
+ default: undefined;
51
+ };
40
52
  components: {
41
53
  type: PropType<TransComponents>;
42
54
  default: () => {};
43
55
  };
56
+ richTags: {
57
+ type: PropType<string[]>;
58
+ default: undefined;
59
+ };
44
60
  links: {
45
61
  type: PropType<Record<string, RichLink>>;
46
62
  default: () => {};
47
63
  };
48
64
  }>> & Readonly<{}>, {
49
65
  values: Params;
66
+ instance: Verbaly<DictionaryInput>;
50
67
  components: TransComponents;
68
+ richTags: string[];
51
69
  links: Record<string, RichLink>;
52
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
53
71
  //#endregion
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Fragment, computed, defineComponent, h, inject, onScopeDispose, shallowRef } from "vue";
2
- import { normalizeLink, parseTags } from "verbaly";
2
+ import { RICH_TAGS, normalizeLink, parseTags } from "verbaly";
3
3
  //#region src/index.ts
4
4
  const KEY = Symbol("verbaly");
5
5
  function verbalyPlugin(instance) {
@@ -51,32 +51,41 @@ const Trans = defineComponent({
51
51
  type: Object,
52
52
  default: void 0
53
53
  },
54
+ instance: {
55
+ type: Object,
56
+ default: void 0
57
+ },
54
58
  components: {
55
59
  type: Object,
56
60
  default: () => ({})
57
61
  },
62
+ richTags: {
63
+ type: Array,
64
+ default: void 0
65
+ },
58
66
  links: {
59
67
  type: Object,
60
68
  default: () => ({})
61
69
  }
62
70
  },
63
71
  setup(props) {
64
- const instance = useVerbaly();
72
+ const instance = props.instance ?? useVerbaly();
65
73
  const version = trackVersion(instance);
66
74
  return () => {
67
75
  version.value;
68
- return h(Fragment, toNodes(parseTags(instance.t(props.id, props.values)), props.components, props.links));
76
+ return h(Fragment, toNodes(parseTags(instance.t(props.id, props.values)), props.components, props.links, new Set(props.richTags ?? RICH_TAGS)));
69
77
  };
70
78
  }
71
79
  });
72
- function toNodes(nodes, components, links) {
80
+ function toNodes(nodes, components, links, richTags) {
73
81
  return nodes.map((node) => {
74
82
  if (typeof node === "string") return node;
75
- const children = toNodes(node.children, components, links);
83
+ const children = toNodes(node.children, components, links, richTags);
76
84
  const fn = components[node.name];
77
85
  if (fn) return fn(children);
78
86
  const link = links[node.name];
79
87
  if (link !== void 0) return h("a", normalizeLink(link), children);
88
+ if (richTags.has(node.name)) return h(node.name, null, children);
80
89
  return children;
81
90
  });
82
91
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\nexport function useT<D extends DictionaryInput = DictionaryInput>(): TFunction<D> {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as TFunction<D>).id = instance.t.id;\n return t as TFunction<D>;\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(Fragment, toNodes(parseTags(text), props.components, props.links));\n };\n },\n});\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links);\n const fn = components[node.name];\n if (fn) return fn(children);\n const link = links[node.name];\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;AA0BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;AAEA,SAAgB,aAAsE;CACpF,MAAM,WAAW,OAAO,KAAK,IAAI;CACjC,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,2DAA2D;CAE7E,OAAO;AACT;AAEA,SAAgB,OAAkE;CAChF,MAAM,WAAW,WAAc;CAC/B,MAAM,UAAU,aAAa,QAAQ;CACrC,MAAM,KAAK,OAAgB,GAAG,SAA4B;EACxD,QAAa;EACb,OAAQ,SAAS,EAAgD,OAAO,GAAG,IAAI;CACjF;CAEA,EAAoB,KAAK,SAAS,EAAE;CACpC,OAAO;AACT;AAEA,SAAgB,YAAyC;CACvD,MAAM,WAAW,WAAW;CAC5B,MAAM,UAAU,aAAa,QAAQ;CACrC,OAAO,SAAS;EACd,WAAW;GACT,QAAa;GACb,OAAO,SAAS;EAClB;EACA,MAAM,WAAmB,SAAS,UAAU,MAAM;CACpD,CAAC;AACH;AAEA,SAAS,aAAwC,UAA0C;CACzF,MAAM,UAAU,WAAW,SAAS,OAAO;CAC3C,eACE,SAAS,gBAAgB;EACvB,QAAQ,QAAQ,SAAS;CAC3B,CAAC,CACH;CACA,OAAO;AACT;AAKA,MAAa,QAAQ,gBAAgB;CACnC,MAAM;CACN,OAAO;EACL,IAAI;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnC,QAAQ;GAAE,MAAM;GAA4B,SAAS,KAAA;EAAU;EAC/D,YAAY;GAAE,MAAM;GAAqC,gBAAgB,CAAC;EAAG;EAC7E,OAAO;GAAE,MAAM;GAA8C,gBAAgB,CAAC;EAAG;CACnF;CACA,MAAM,OAAO;EACX,MAAM,WAAW,WAAW;EAC5B,MAAM,UAAU,aAAa,QAAQ;EACrC,aAAa;GACX,QAAa;GAKb,OAAO,EAAE,UAAU,QAAQ,UAJb,SAAS,EACrB,MAAM,IACN,MAAM,MAEgC,CAAC,GAAG,MAAM,YAAY,MAAM,KAAK,CAAC;EAC5E;CACF;AACF,CAAC;AAED,SAAS,QACP,OACA,YACA,OACc;CACd,OAAO,MAAM,KAAK,SAAS;EACzB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,WAAW,QAAQ,KAAK,UAAU,YAAY,KAAK;EACzD,MAAM,KAAK,WAAW,KAAK;EAC3B,IAAI,IAAI,OAAO,GAAG,QAAQ;EAC1B,MAAM,OAAO,MAAM,KAAK;EACxB,IAAI,SAAS,KAAA,GACX,OAAO,EAAE,KAAK,cAAc,IAAI,GAAG,QAAQ;EAE7C,OAAO;CACT,CAAC;AACH"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n Fragment,\n h,\n inject,\n onScopeDispose,\n shallowRef,\n type App,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n type VNodeChild,\n type WritableComputedRef,\n} from 'vue';\nimport {\n normalizeLink,\n parseTags,\n RICH_TAGS,\n type DictionaryInput,\n type Params,\n type RichLink,\n type TagNode,\n type TFunction,\n type Verbaly,\n} from 'verbaly';\n\nconst KEY: InjectionKey<Verbaly> = Symbol('verbaly');\n\nexport interface VerbalyPlugin {\n install(app: App): void;\n}\n\nexport function verbalyPlugin<D extends DictionaryInput>(instance: Verbaly<D>): VerbalyPlugin {\n return {\n install(app) {\n app.provide(KEY, instance as unknown as Verbaly);\n },\n };\n}\n\nexport function useVerbaly<D extends DictionaryInput = DictionaryInput>(): Verbaly<D> {\n const instance = inject(KEY, null);\n if (!instance) {\n throw new Error('[verbaly] useVerbaly requires app.use(verbalyPlugin(...))');\n }\n return instance as unknown as Verbaly<D>;\n}\n\nexport function useT<D extends DictionaryInput = DictionaryInput>(): TFunction<D> {\n const instance = useVerbaly<D>();\n const version = trackVersion(instance);\n const t = (first: unknown, ...rest: unknown[]): string => {\n void version.value;\n return (instance.t as unknown as (...args: unknown[]) => string)(first, ...rest);\n };\n // the reactive wrapper must keep t's full surface (react/svelte hand out instance.t directly)\n (t as TFunction<D>).id = instance.t.id;\n return t as TFunction<D>;\n}\n\nexport function useLocale(): WritableComputedRef<string> {\n const instance = useVerbaly();\n const version = trackVersion(instance);\n return computed({\n get: () => {\n void version.value;\n return instance.locale;\n },\n set: (locale: string) => instance.setLocale(locale),\n });\n}\n\nfunction trackVersion<D extends DictionaryInput>(instance: Verbaly<D>): ShallowRef<number> {\n const version = shallowRef(instance.version);\n onScopeDispose(\n instance.subscribe(() => {\n version.value = instance.version;\n }),\n );\n return version;\n}\n\nexport type TransComponents = Record<string, (children: VNodeChild[]) => VNodeChild>;\n\n// translated message + element interpolation\nexport const Trans = defineComponent({\n name: 'Trans',\n props: {\n id: { type: String, required: true },\n values: { type: Object as PropType<Params>, default: undefined },\n instance: { type: Object as PropType<Verbaly>, default: undefined },\n components: { type: Object as PropType<TransComponents>, default: () => ({}) },\n richTags: { type: Array as PropType<string[]>, default: undefined },\n links: { type: Object as PropType<Record<string, RichLink>>, default: () => ({}) },\n },\n setup(props) {\n const instance = props.instance ?? useVerbaly();\n const version = trackVersion(instance);\n return () => {\n void version.value;\n const text = (instance.t as unknown as (id: string, values?: Params) => string)(\n props.id,\n props.values,\n );\n return h(\n Fragment,\n toNodes(\n parseTags(text),\n props.components,\n props.links,\n new Set(props.richTags ?? RICH_TAGS),\n ),\n );\n };\n },\n});\n\nfunction toNodes(\n nodes: TagNode[],\n components: TransComponents,\n links: Record<string, RichLink>,\n richTags: Set<string>,\n): VNodeChild[] {\n return nodes.map((node) => {\n if (typeof node === 'string') return node;\n const children = toNodes(node.children, components, links, richTags);\n const fn = components[node.name];\n if (fn) return fn(children);\n const link = links[node.name];\n if (link !== undefined) {\n return h('a', normalizeLink(link), children);\n }\n if (richTags.has(node.name)) {\n return h(node.name, null, children);\n }\n return children;\n });\n}\n\nexport type { Params, TFunction, Verbaly };\n"],"mappings":";;;AA2BA,MAAM,MAA6B,OAAO,SAAS;AAMnD,SAAgB,cAAyC,UAAqC;CAC5F,OAAO,EACL,QAAQ,KAAK;EACX,IAAI,QAAQ,KAAK,QAA8B;CACjD,EACF;AACF;AAEA,SAAgB,aAAsE;CACpF,MAAM,WAAW,OAAO,KAAK,IAAI;CACjC,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,2DAA2D;CAE7E,OAAO;AACT;AAEA,SAAgB,OAAkE;CAChF,MAAM,WAAW,WAAc;CAC/B,MAAM,UAAU,aAAa,QAAQ;CACrC,MAAM,KAAK,OAAgB,GAAG,SAA4B;EACxD,QAAa;EACb,OAAQ,SAAS,EAAgD,OAAO,GAAG,IAAI;CACjF;CAEA,EAAoB,KAAK,SAAS,EAAE;CACpC,OAAO;AACT;AAEA,SAAgB,YAAyC;CACvD,MAAM,WAAW,WAAW;CAC5B,MAAM,UAAU,aAAa,QAAQ;CACrC,OAAO,SAAS;EACd,WAAW;GACT,QAAa;GACb,OAAO,SAAS;EAClB;EACA,MAAM,WAAmB,SAAS,UAAU,MAAM;CACpD,CAAC;AACH;AAEA,SAAS,aAAwC,UAA0C;CACzF,MAAM,UAAU,WAAW,SAAS,OAAO;CAC3C,eACE,SAAS,gBAAgB;EACvB,QAAQ,QAAQ,SAAS;CAC3B,CAAC,CACH;CACA,OAAO;AACT;AAKA,MAAa,QAAQ,gBAAgB;CACnC,MAAM;CACN,OAAO;EACL,IAAI;GAAE,MAAM;GAAQ,UAAU;EAAK;EACnC,QAAQ;GAAE,MAAM;GAA4B,SAAS,KAAA;EAAU;EAC/D,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,YAAY;GAAE,MAAM;GAAqC,gBAAgB,CAAC;EAAG;EAC7E,UAAU;GAAE,MAAM;GAA6B,SAAS,KAAA;EAAU;EAClE,OAAO;GAAE,MAAM;GAA8C,gBAAgB,CAAC;EAAG;CACnF;CACA,MAAM,OAAO;EACX,MAAM,WAAW,MAAM,YAAY,WAAW;EAC9C,MAAM,UAAU,aAAa,QAAQ;EACrC,aAAa;GACX,QAAa;GAKb,OAAO,EACL,UACA,QACE,UAPU,SAAS,EACrB,MAAM,IACN,MAAM,MAKS,CAAC,GACd,MAAM,YACN,MAAM,OACN,IAAI,IAAI,MAAM,YAAY,SAAS,CACrC,CACF;EACF;CACF;AACF,CAAC;AAED,SAAS,QACP,OACA,YACA,OACA,UACc;CACd,OAAO,MAAM,KAAK,SAAS;EACzB,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,MAAM,WAAW,QAAQ,KAAK,UAAU,YAAY,OAAO,QAAQ;EACnE,MAAM,KAAK,WAAW,KAAK;EAC3B,IAAI,IAAI,OAAO,GAAG,QAAQ;EAC1B,MAAM,OAAO,MAAM,KAAK;EACxB,IAAI,SAAS,KAAA,GACX,OAAO,EAAE,KAAK,cAAc,IAAI,GAAG,QAAQ;EAE7C,IAAI,SAAS,IAAI,KAAK,IAAI,GACxB,OAAO,EAAE,KAAK,MAAM,MAAM,QAAQ;EAEpC,OAAO;CACT,CAAC;AACH"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@verbaly/vue",
3
- "version": "0.22.0",
4
- "description": "Vue 3 bindings for Verbaly composables over the reactive core.",
3
+ "version": "0.23.0",
4
+ "description": "Vue 3 bindings for Verbaly: composables over the reactive core.",
5
5
  "keywords": [
6
6
  "i18n",
7
7
  "vue",
@@ -48,12 +48,12 @@
48
48
  },
49
49
  "peerDependencies": {
50
50
  "vue": "^3.4.0",
51
- "verbaly": "^0.22.0"
51
+ "verbaly": "^0.23.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "happy-dom": "^20.10.6",
55
55
  "vue": "^3.5.39",
56
- "verbaly": "0.22.0"
56
+ "verbaly": "0.23.0"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "tsdown",