prosebook 0.0.1 → 0.2.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/LICENSE +21 -0
- package/README.md +604 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +508 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-D--RITk2.js +1208 -0
- package/dist/config-D--RITk2.js.map +1 -0
- package/dist/config-_4HfnJQu.d.ts +517 -0
- package/dist/config-_4HfnJQu.d.ts.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -0
- package/dist/copy-DXnzXsJa.d.ts +162 -0
- package/dist/copy-DXnzXsJa.d.ts.map +1 -0
- package/dist/helpers-BPuPGjQP.js +61 -0
- package/dist/helpers-BPuPGjQP.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector.d.ts +37 -0
- package/dist/inspector.d.ts.map +1 -0
- package/dist/inspector.js +572 -0
- package/dist/inspector.js.map +1 -0
- package/dist/react/index.d.ts +37 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +86 -0
- package/dist/react/index.js.map +1 -0
- package/dist/sarif-CI8HOokm.js +1033 -0
- package/dist/sarif-CI8HOokm.js.map +1 -0
- package/dist/scan-Ch2BfIUD.js +2561 -0
- package/dist/scan-Ch2BfIUD.js.map +1 -0
- package/dist/tools.d.ts +377 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +4 -0
- package/dist/vite.d.ts +24 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +264 -0
- package/dist/vite.js.map +1 -0
- package/package.json +148 -15
- package/src/cli.ts +528 -0
- package/src/index.ts +31 -0
- package/src/inspector-dialog.ts +450 -0
- package/src/inspector.ts +228 -0
- package/src/react/index.tsx +112 -0
- package/src/runtime/copy.ts +221 -0
- package/src/runtime/helpers.ts +66 -0
- package/src/runtime/locale.ts +49 -0
- package/src/runtime/types.ts +106 -0
- package/src/tools/catalog.ts +449 -0
- package/src/tools/compile.ts +121 -0
- package/src/tools/config.ts +211 -0
- package/src/tools/diff.ts +84 -0
- package/src/tools/entry.ts +325 -0
- package/src/tools/extract.ts +694 -0
- package/src/tools/generate.ts +257 -0
- package/src/tools/icu.ts +211 -0
- package/src/tools/index.ts +91 -0
- package/src/tools/lint.ts +865 -0
- package/src/tools/lock.ts +95 -0
- package/src/tools/mf1.ts +246 -0
- package/src/tools/mf2.ts +752 -0
- package/src/tools/migrate.ts +138 -0
- package/src/tools/presets.ts +159 -0
- package/src/tools/pseudo.ts +40 -0
- package/src/tools/sarif.ts +80 -0
- package/src/tools/scan.ts +303 -0
- package/src/tools/syntax.ts +24 -0
- package/src/tools/types.ts +137 -0
- package/src/vite.ts +296 -0
- package/index.js +0 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { S as RichParam, b as RegisteredMessages, h as MessageShape, n as Copy, w as TagFn, x as RichKey, y as RegisteredLocale } from "../copy-DXnzXsJa.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
type M = RegisteredMessages;
|
|
4
|
+
type L = RegisteredLocale;
|
|
5
|
+
/** `Copy`, with `rich` returning a `ReactNode`. */
|
|
6
|
+
export interface ReactCopy extends Omit<Copy<M, L>, 'rich'> {
|
|
7
|
+
rich<K extends RichKey<M>>(this: void, key: K, ...values: RichParam<M[K], ReactNode>): ReactNode;
|
|
8
|
+
}
|
|
9
|
+
type Tags = {
|
|
10
|
+
readonly [tag: string]: TagFn<ReactNode>;
|
|
11
|
+
};
|
|
12
|
+
export interface CopyProviderProps {
|
|
13
|
+
copy: Copy<M, L> | Copy;
|
|
14
|
+
/** Tag renderers every rich read under this provider gets, beside the copy's own. */
|
|
15
|
+
tags?: Tags;
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare function CopyProvider({ copy, tags, children }: CopyProviderProps): import("react").JSX.Element;
|
|
19
|
+
/** The catalog, in the current locale. Re-renders the component when the locale changes, or in dev the catalog. */
|
|
20
|
+
export declare function useCopy(): ReactCopy;
|
|
21
|
+
/** The current locale alone, for components that only format or switch. */
|
|
22
|
+
export declare function useLocale(): L;
|
|
23
|
+
type ValuesProp<S extends MessageShape> = {} extends S['args'] & { [T in S['tags']]: unknown; } ? {
|
|
24
|
+
values?: S['args'] & { [T in S['tags']]?: TagFn<ReactNode>; };
|
|
25
|
+
} : {
|
|
26
|
+
values: RichParam<S, ReactNode>[0];
|
|
27
|
+
};
|
|
28
|
+
export type TextProps<K extends Extract<keyof M, string>> = {
|
|
29
|
+
id: K;
|
|
30
|
+
} & ValuesProp<M[K]>;
|
|
31
|
+
/**
|
|
32
|
+
* A message as an element: `<Text id="cart.items" values={{ count }} />`. Rich messages render their
|
|
33
|
+
* tags through the provider's renderers and any given in `values`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function Text<K extends Extract<keyof M, string>>(props: TextProps<K>): import("react").JSX.Element;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/react/index.tsx"],"mappings":";;KAYK,IAAI;KACJ,IAAI;;iBAGQ,kBAAkB,KAAK,KAAK,GAAG;EAC9C,KAAK,UAAU,QAAQ,IAAI,YAAY,KAAK,MAAM,QAAQ,UAAU,EAAE,IAAI,aAAa;;KAKpF;YAAmB,cAAc,MAAM;;iBAE3B;EACf,MAAM,KAAK,GAAG,KAAK;;EAEnB,OAAO;EACP,WAAW;;wBAGG,eAAe,MAAM,MAAM,YAAY,oCAAiB,IAAA;;wBAMxD,WAAW;;wBAaX,aAAa;KA+CxB,WAAW,UAAU,2BAA2B,eAAe,KAAK;EACnE,SAAS,eAAe,KAAK,aAAa,MAAM;;EAChD,QAAQ,UAAU,GAAG;;YAEf,UAAU,UAAU,cAAc;EAAgB,IAAI;IAAM,WAAW,EAAE;;;;;wBAMrE,KAAK,UAAU,cAAc,YAAY,OAAO,UAAU,qBAAE,IAAA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Fragment, createContext, isValidElement, use, useMemo, useSyncExternalStore } from "react";
|
|
2
|
+
import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
|
|
3
|
+
// src/react/index.tsx
|
|
4
|
+
/**
|
|
5
|
+
* `prosebook/react`: the catalog in components.
|
|
6
|
+
*
|
|
7
|
+
* `useCopy()` re-renders its component when the locale changes, and its `rich` returns a ready
|
|
8
|
+
* `ReactNode`: elements are keyed and tag functions receive keyed children, so a sentence with a
|
|
9
|
+
* link inside it is one catalog entry and one call, with no wrapper to remember.
|
|
10
|
+
*/
|
|
11
|
+
const CopyContext = createContext(null);
|
|
12
|
+
function CopyProvider({ copy, tags, children }) {
|
|
13
|
+
const value = useMemo(() => ({
|
|
14
|
+
copy,
|
|
15
|
+
tags: {
|
|
16
|
+
...copy.tags,
|
|
17
|
+
...tags
|
|
18
|
+
}
|
|
19
|
+
}), [copy, tags]);
|
|
20
|
+
return /* @__PURE__ */ jsx(CopyContext, {
|
|
21
|
+
value,
|
|
22
|
+
children
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** The catalog, in the current locale. Re-renders the component when the locale changes, or in dev the catalog. */
|
|
26
|
+
function useCopy() {
|
|
27
|
+
const context = use(CopyContext);
|
|
28
|
+
if (context === null) throw new Error("prosebook: useCopy() needs a <CopyProvider> above it");
|
|
29
|
+
const { copy, tags } = context;
|
|
30
|
+
const version = useSyncExternalStore(copy.subscribe, () => copy.version, () => copy.version);
|
|
31
|
+
return useMemo(() => readerFor(copy, tags, version), [
|
|
32
|
+
copy,
|
|
33
|
+
tags,
|
|
34
|
+
version
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
/** The current locale alone, for components that only format or switch. */
|
|
38
|
+
function useLocale() {
|
|
39
|
+
const context = use(CopyContext);
|
|
40
|
+
if (context === null) throw new Error("prosebook: useLocale() needs a <CopyProvider> above it");
|
|
41
|
+
return useSyncExternalStore(context.copy.subscribe, () => context.copy.locale, () => context.copy.locale);
|
|
42
|
+
}
|
|
43
|
+
function readerFor(copy, tags, version) {
|
|
44
|
+
return {
|
|
45
|
+
locale: copy.locale,
|
|
46
|
+
version,
|
|
47
|
+
locales: copy.locales,
|
|
48
|
+
source: copy.source,
|
|
49
|
+
tags: copy.tags,
|
|
50
|
+
ready: copy.ready,
|
|
51
|
+
t: copy.t,
|
|
52
|
+
has: copy.has,
|
|
53
|
+
setLocale: copy.setLocale,
|
|
54
|
+
subscribe: copy.subscribe,
|
|
55
|
+
number: copy.number,
|
|
56
|
+
date: copy.date,
|
|
57
|
+
list: copy.list,
|
|
58
|
+
relative: copy.relative,
|
|
59
|
+
rich(key, ...values) {
|
|
60
|
+
const given = values[0] ?? {};
|
|
61
|
+
const merged = {
|
|
62
|
+
...tags,
|
|
63
|
+
...given
|
|
64
|
+
};
|
|
65
|
+
for (const [name, value] of Object.entries(merged)) if (typeof value === "function") merged[name] = (chunks) => value(keyed(chunks));
|
|
66
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: keyed(copy.rich(key, merged)) });
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Text joined where it can be, and each element under its own key, so React never warns about a list. */
|
|
71
|
+
function keyed(parts) {
|
|
72
|
+
if (parts.every((p) => typeof p === "string")) return [parts.join("")];
|
|
73
|
+
return parts.map((p, i) => isValidElement(p) || typeof p === "object" ? /* @__PURE__ */ jsx(Fragment, { children: p }, i) : p);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A message as an element: `<Text id="cart.items" values={{ count }} />`. Rich messages render their
|
|
77
|
+
* tags through the provider's renderers and any given in `values`.
|
|
78
|
+
*/
|
|
79
|
+
function Text(props) {
|
|
80
|
+
const copy = useCopy();
|
|
81
|
+
const values = props.values;
|
|
82
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: copy.rich(props.id, values) });
|
|
83
|
+
}
|
|
84
|
+
export { CopyProvider, Text, useCopy, useLocale };
|
|
85
|
+
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/react/index.tsx"],"sourcesContent":["/**\n * `prosebook/react`: the catalog in components.\n *\n * `useCopy()` re-renders its component when the locale changes, and its `rich` returns a ready\n * `ReactNode`: elements are keyed and tag functions receive keyed children, so a sentence with a\n * link inside it is one catalog entry and one call, with no wrapper to remember.\n */\nimport { createContext, Fragment, isValidElement, use, useMemo, useSyncExternalStore, type ReactNode } from 'react';\n\nimport type { Copy } from '#src/runtime/copy.ts';\nimport type { MessageShape, RegisteredLocale, RegisteredMessages, RichKey, RichParam, TagFn } from '#src/runtime/types.ts';\n\ntype M = RegisteredMessages;\ntype L = RegisteredLocale;\n\n/** `Copy`, with `rich` returning a `ReactNode`. */\nexport interface ReactCopy extends Omit<Copy<M, L>, 'rich'> {\n rich<K extends RichKey<M>>(this: void, key: K, ...values: RichParam<M[K], ReactNode>): ReactNode;\n}\n\nconst CopyContext = createContext<{ copy: Copy<M, L>; tags: Tags } | null>(null);\n\ntype Tags = { readonly [tag: string]: TagFn<ReactNode> };\n\nexport interface CopyProviderProps {\n copy: Copy<M, L> | Copy;\n /** Tag renderers every rich read under this provider gets, beside the copy's own. */\n tags?: Tags;\n children?: ReactNode;\n}\n\nexport function CopyProvider({ copy, tags, children }: CopyProviderProps) {\n const value = useMemo(() => ({ copy: copy as Copy<M, L>, tags: { ...(copy.tags as unknown as Tags), ...tags } }), [copy, tags]);\n return <CopyContext value={value}>{children}</CopyContext>;\n}\n\n/** The catalog, in the current locale. Re-renders the component when the locale changes, or in dev the catalog. */\nexport function useCopy(): ReactCopy {\n const context = use(CopyContext);\n if (context === null) throw new Error('prosebook: useCopy() needs a <CopyProvider> above it');\n const { copy, tags } = context;\n const version = useSyncExternalStore(\n copy.subscribe,\n () => copy.version,\n () => copy.version,\n );\n return useMemo(() => readerFor(copy, tags, version), [copy, tags, version]);\n}\n\n/** The current locale alone, for components that only format or switch. */\nexport function useLocale(): L {\n const context = use(CopyContext);\n if (context === null) throw new Error('prosebook: useLocale() needs a <CopyProvider> above it');\n return useSyncExternalStore(\n context.copy.subscribe,\n () => context.copy.locale,\n () => context.copy.locale,\n );\n}\n\n// Takes the version only so the reader is rebuilt, and its identity changes, when what it reads does.\nfunction readerFor(copy: Copy<M, L>, tags: Tags, version: number): ReactCopy {\n return {\n locale: copy.locale,\n version,\n locales: copy.locales,\n source: copy.source,\n tags: copy.tags,\n ready: copy.ready,\n t: copy.t,\n has: copy.has,\n setLocale: copy.setLocale,\n subscribe: copy.subscribe,\n number: copy.number,\n date: copy.date,\n list: copy.list,\n relative: copy.relative,\n rich(key, ...values) {\n const given = (values[0] ?? {}) as Record<string, unknown>;\n const merged: Record<string, unknown> = { ...tags, ...given };\n for (const [name, value] of Object.entries(merged))\n if (typeof value === 'function') merged[name] = (chunks: unknown[]) => (value as TagFn<ReactNode>)(keyed(chunks));\n\n return <>{keyed(copy.rich(key as never, merged as never))}</>;\n },\n };\n}\n\n/** Text joined where it can be, and each element under its own key, so React never warns about a list. */\nfunction keyed(parts: unknown[]): (string | ReactNode)[] {\n if (parts.every((p) => typeof p === 'string')) return [parts.join('')];\n return parts.map((p, i) =>\n // oxlint-disable-next-line react/no-array-index-key -- the parts of one message never reorder, so positions are stable keys\n isValidElement(p) || typeof p === 'object' ? <Fragment key={i}>{p as ReactNode}</Fragment> : (p as ReactNode),\n );\n}\n\ntype ValuesProp<S extends MessageShape> = {} extends S['args'] & { [T in S['tags']]: unknown }\n ? { values?: S['args'] & { [T in S['tags']]?: TagFn<ReactNode> } }\n : { values: RichParam<S, ReactNode>[0] };\n\nexport type TextProps<K extends Extract<keyof M, string>> = { id: K } & ValuesProp<M[K]>;\n\n/**\n * A message as an element: `<Text id=\"cart.items\" values={{ count }} />`. Rich messages render their\n * tags through the provider's renderers and any given in `values`.\n */\nexport function Text<K extends Extract<keyof M, string>>(props: TextProps<K>) {\n const copy = useCopy();\n const values = (props as { values?: object }).values;\n return <>{copy.rich(props.id as RichKey<M>, values)}</>;\n}\n"],"mappings":";;;;;;;;;;AAoBA,MAAM,cAAc,cAAuD,IAAI;AAW/E,SAAgB,aAAa,EAAE,MAAM,MAAM,YAA+B;CACxE,MAAM,QAAQ,eAAe;EAAQ;EAAoB,MAAM;GAAE,GAAI,KAAK;GAA0B,GAAG;EAAK;CAAE,IAAI,CAAC,MAAM,IAAI,CAAC;CAC9H,OAAO,oBAAC,aAAD;EAAoB;EAAQ;CAAsB,CAAA;AAC3D;;AAGA,SAAgB,UAAqB;CACnC,MAAM,UAAU,IAAI,WAAW;CAC/B,IAAI,YAAY,MAAM,MAAM,IAAI,MAAM,sDAAsD;CAC5F,MAAM,EAAE,MAAM,SAAS;CACvB,MAAM,UAAU,qBACd,KAAK,iBACC,KAAK,eACL,KAAK,OACb;CACA,OAAO,cAAc,UAAU,MAAM,MAAM,OAAO,GAAG;EAAC;EAAM;EAAM;CAAO,CAAC;AAC5E;;AAGA,SAAgB,YAAe;CAC7B,MAAM,UAAU,IAAI,WAAW;CAC/B,IAAI,YAAY,MAAM,MAAM,IAAI,MAAM,wDAAwD;CAC9F,OAAO,qBACL,QAAQ,KAAK,iBACP,QAAQ,KAAK,cACb,QAAQ,KAAK,MACrB;AACF;AAGA,SAAS,UAAU,MAAkB,MAAY,SAA4B;CAC3E,OAAO;EACL,QAAQ,KAAK;EACb;EACA,SAAS,KAAK;EACd,QAAQ,KAAK;EACb,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,GAAG,KAAK;EACR,KAAK,KAAK;EACV,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,QAAQ,KAAK;EACb,MAAM,KAAK;EACX,MAAM,KAAK;EACX,UAAU,KAAK;EACf,KAAK,KAAK,GAAG,QAAQ;GACnB,MAAM,QAAS,OAAO,MAAM,CAAC;GAC7B,MAAM,SAAkC;IAAE,GAAG;IAAM,GAAG;GAAM;GAC5D,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,GAC/C,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,WAAuB,MAA2B,MAAM,MAAM,CAAC;GAElH,OAAO,oBAAA,YAAA,EAAA,UAAG,MAAM,KAAK,KAAK,KAAc,MAAe,CAAC,EAAI,CAAA;EAC9D;CACF;AACF;;AAGA,SAAS,MAAM,OAA0C;CACvD,IAAI,MAAM,OAAO,MAAM,OAAO,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,KAAK,EAAE,CAAC;CACrE,OAAO,MAAM,KAAK,GAAG,MAEnB,eAAe,CAAC,KAAK,OAAO,MAAM,WAAW,oBAAC,UAAD,EAAA,UAAmB,EAAyB,GAA7B,CAA6B,IAAK,CAChG;AACF;;;;;AAYA,SAAgB,KAAyC,OAAqB;CAC5E,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAU,MAA8B;CAC9C,OAAO,oBAAA,YAAA,EAAA,UAAG,KAAK,KAAK,MAAM,IAAkB,MAAM,EAAI,CAAA;AACxD"}
|