react-cheminfo 0.52.0 → 0.54.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 +65 -31
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/i18n/core/index.d.ts +2 -0
- package/lib/i18n/core/index.d.ts.map +1 -1
- package/lib/i18n/core/index.js +1 -0
- package/lib/i18n/core/index.js.map +1 -1
- package/lib/i18n/core/messageCatalog.d.ts +10 -0
- package/lib/i18n/core/messageCatalog.d.ts.map +1 -1
- package/lib/i18n/core/messageCatalog.js +12 -0
- package/lib/i18n/core/messageCatalog.js.map +1 -1
- package/lib/i18n/core/translate.d.ts +35 -0
- package/lib/i18n/core/translate.d.ts.map +1 -0
- package/lib/i18n/core/translate.js +27 -0
- package/lib/i18n/core/translate.js.map +1 -0
- package/lib/i18n/ui/useT.d.ts +2 -12
- package/lib/i18n/ui/useT.d.ts.map +1 -1
- package/lib/i18n/ui/useT.js +2 -8
- package/lib/i18n/ui/useT.js.map +1 -1
- package/lib/i18n/vite/index.d.ts +3 -0
- package/lib/i18n/vite/index.d.ts.map +1 -0
- package/lib/i18n/vite/index.js +2 -0
- package/lib/i18n/vite/index.js.map +1 -0
- package/lib/i18n/vite/localeCatalog.d.ts +70 -0
- package/lib/i18n/vite/localeCatalog.d.ts.map +1 -0
- package/lib/i18n/vite/localeCatalog.js +80 -0
- package/lib/i18n/vite/localeCatalog.js.map +1 -0
- package/lib/language/ui/siteLanguageContext.d.ts.map +1 -1
- package/lib/language/ui/siteLanguageContext.js +2 -1
- package/lib/language/ui/siteLanguageContext.js.map +1 -1
- package/lib/locales/de.json +5 -0
- package/lib/locales/en.json +5 -0
- package/lib/locales/es.json +5 -0
- package/lib/locales/fr.json +5 -0
- package/lib/locales/it.json +5 -0
- package/lib/router/core/history.d.ts +4 -3
- package/lib/router/core/history.d.ts.map +1 -1
- package/lib/router/core/history.js +9 -13
- package/lib/router/core/history.js.map +1 -1
- package/lib/router/core/index.d.ts +2 -0
- package/lib/router/core/index.d.ts.map +1 -1
- package/lib/router/core/index.js +1 -0
- package/lib/router/core/index.js.map +1 -1
- package/lib/router/core/pageAddress.d.ts +61 -0
- package/lib/router/core/pageAddress.d.ts.map +1 -0
- package/lib/router/core/pageAddress.js +69 -0
- package/lib/router/core/pageAddress.js.map +1 -0
- package/lib/share/core/index.d.ts +4 -0
- package/lib/share/core/index.d.ts.map +1 -1
- package/lib/share/core/index.js +2 -0
- package/lib/share/core/index.js.map +1 -1
- package/lib/share/core/preferences.d.ts +2 -2
- package/lib/share/core/preferences.d.ts.map +1 -1
- package/lib/share/core/preferences.js +8 -3
- package/lib/share/core/preferences.js.map +1 -1
- package/lib/share/core/seal.d.ts +42 -0
- package/lib/share/core/seal.d.ts.map +1 -0
- package/lib/share/core/seal.js +185 -0
- package/lib/share/core/seal.js.map +1 -0
- package/lib/share/core/sealedAddress.d.ts +31 -0
- package/lib/share/core/sealedAddress.d.ts.map +1 -0
- package/lib/share/core/sealedAddress.js +38 -0
- package/lib/share/core/sealedAddress.js.map +1 -0
- package/lib/share/ui/SealedLinkRefused.d.ts +17 -0
- package/lib/share/ui/SealedLinkRefused.d.ts.map +1 -0
- package/lib/share/ui/SealedLinkRefused.js +23 -0
- package/lib/share/ui/SealedLinkRefused.js.map +1 -0
- package/lib/share/ui/ShareConfigOptions.d.ts +12 -1
- package/lib/share/ui/ShareConfigOptions.d.ts.map +1 -1
- package/lib/share/ui/ShareConfigOptions.js +4 -3
- package/lib/share/ui/ShareConfigOptions.js.map +1 -1
- package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
- package/lib/share/ui/ShareDialogContent.js +20 -6
- package/lib/share/ui/ShareDialogContent.js.map +1 -1
- package/lib/share/ui/ShareLinkBar.d.ts +5 -0
- package/lib/share/ui/ShareLinkBar.d.ts.map +1 -1
- package/lib/share/ui/ShareLinkBar.js +4 -4
- package/lib/share/ui/ShareLinkBar.js.map +1 -1
- package/lib/share/ui/index.d.ts +2 -0
- package/lib/share/ui/index.d.ts.map +1 -1
- package/lib/share/ui/index.js +1 -0
- package/lib/share/ui/index.js.map +1 -1
- package/lib/share/ui/useSealedUrl.d.ts +17 -0
- package/lib/share/ui/useSealedUrl.d.ts.map +1 -0
- package/lib/share/ui/useSealedUrl.js +31 -0
- package/lib/share/ui/useSealedUrl.js.map +1 -0
- package/lib/vite.d.ts +1 -0
- package/lib/vite.d.ts.map +1 -1
- package/lib/vite.js +1 -0
- package/lib/vite.js.map +1 -1
- package/package.json +1 -1
- package/src/i18n/core/index.ts +2 -0
- package/src/i18n/core/messageCatalog.ts +13 -0
- package/src/i18n/core/translate.ts +51 -0
- package/src/i18n/ui/useT.ts +6 -29
- package/src/i18n/vite/index.ts +5 -0
- package/src/i18n/vite/localeCatalog.ts +121 -0
- package/src/language/ui/siteLanguageContext.ts +2 -1
- package/src/locales/de.json +5 -0
- package/src/locales/en.json +5 -0
- package/src/locales/es.json +5 -0
- package/src/locales/fr.json +5 -0
- package/src/locales/it.json +5 -0
- package/src/router/core/history.ts +9 -15
- package/src/router/core/index.ts +8 -0
- package/src/router/core/pageAddress.ts +110 -0
- package/src/share/core/index.ts +10 -0
- package/src/share/core/preferences.ts +10 -10
- package/src/share/core/seal.ts +233 -0
- package/src/share/core/sealedAddress.ts +48 -0
- package/src/share/ui/SealedLinkRefused.tsx +43 -0
- package/src/share/ui/ShareConfigOptions.tsx +23 -1
- package/src/share/ui/ShareDialogContent.tsx +37 -6
- package/src/share/ui/ShareLinkBar.tsx +9 -1
- package/src/share/ui/index.ts +2 -0
- package/src/share/ui/useSealedUrl.ts +40 -0
- package/src/vite.ts +1 -0
|
@@ -17,17 +17,17 @@ import { useChromeT } from "../../i18n/ui/useT.js";
|
|
|
17
17
|
* @returns The bar.
|
|
18
18
|
*/
|
|
19
19
|
export function ShareLinkBar(props) {
|
|
20
|
-
const { url, frame, onCopied } = props;
|
|
20
|
+
const { url, frame, onCopied, disabled = false } = props;
|
|
21
21
|
const t = useChromeT();
|
|
22
22
|
return (_jsxs("div", { className: "share-linkbar", children: [_jsx(HelpTooltip, { content: {
|
|
23
23
|
title: t('share.copyLinkHelpTitle'),
|
|
24
24
|
body: t('share.copyLinkHelp'),
|
|
25
|
-
}, children: _jsx(CopyButton, { content: url, label: t('share.copyLink'), title: "", onCopied: onCopied }) }), _jsx(HelpTooltip, { content: {
|
|
25
|
+
}, children: _jsx(CopyButton, { content: url, label: t('share.copyLink'), title: "", disabled: disabled, onCopied: onCopied }) }), _jsx(HelpTooltip, { content: {
|
|
26
26
|
title: t('share.openInNewTabHelpTitle'),
|
|
27
27
|
body: t('share.openInNewTabHelp'),
|
|
28
|
-
}, children: _jsx(AnchorButton, { icon: "share", text: t('share.openInNewTab'), href: url, target: "_blank", rel: "noopener noreferrer" }) }), _jsx(HelpTooltip, { content: {
|
|
28
|
+
}, children: _jsx(AnchorButton, { icon: "share", text: t('share.openInNewTab'), href: url, disabled: disabled, target: "_blank", rel: "noopener noreferrer" }) }), _jsx(HelpTooltip, { content: {
|
|
29
29
|
title: t('share.copyIframeHelpTitle'),
|
|
30
30
|
body: t('share.copyIframeHelp'),
|
|
31
|
-
}, children: _jsx(CopyButton, { content: frame, icon: "code", label: t('share.copyIframe'), title: "", onCopied: onCopied }) })] }));
|
|
31
|
+
}, children: _jsx(CopyButton, { content: frame, icon: "code", label: t('share.copyIframe'), title: "", disabled: disabled, onCopied: onCopied }) })] }));
|
|
32
32
|
}
|
|
33
33
|
//# sourceMappingURL=ShareLinkBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareLinkBar.js","sourceRoot":"","sources":["../../../src/share/ui/ShareLinkBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ShareLinkBar.js","sourceRoot":"","sources":["../../../src/share/ui/ShareLinkBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAmBnD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IACzD,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;IAEvB,OAAO,CACL,eAAK,SAAS,EAAC,eAAe,aAC5B,KAAC,WAAW,IACV,OAAO,EAAE;oBACP,KAAK,EAAE,CAAC,CAAC,yBAAyB,CAAC;oBACnC,IAAI,EAAE,CAAC,CAAC,oBAAoB,CAAC;iBAC9B,YAED,KAAC,UAAU,IACT,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAC1B,KAAK,EAAC,EAAE,EACR,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,GAClB,GACU,EACd,KAAC,WAAW,IACV,OAAO,EAAE;oBACP,KAAK,EAAE,CAAC,CAAC,6BAA6B,CAAC;oBACvC,IAAI,EAAE,CAAC,CAAC,wBAAwB,CAAC;iBAClC,YAED,KAAC,YAAY,IACX,IAAI,EAAC,OAAO,EACZ,IAAI,EAAE,CAAC,CAAC,oBAAoB,CAAC,EAC7B,IAAI,EAAE,GAAG,EACT,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,GACzB,GACU,EACd,KAAC,WAAW,IACV,OAAO,EAAE;oBACP,KAAK,EAAE,CAAC,CAAC,2BAA2B,CAAC;oBACrC,IAAI,EAAE,CAAC,CAAC,sBAAsB,CAAC;iBAChC,YAED,KAAC,UAAU,IACT,OAAO,EAAE,KAAK,EACd,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAC5B,KAAK,EAAC,EAAE,EACR,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,GAClB,GACU,IACV,CACP,CAAC;AACJ,CAAC"}
|
package/lib/share/ui/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export { HiddenPartsProvider } from './HiddenPartsProvider.tsx';
|
|
|
3
3
|
export { useIsHidden } from './hiddenParts.ts';
|
|
4
4
|
export type { PagePartProps } from './PagePart.tsx';
|
|
5
5
|
export { PagePart } from './PagePart.tsx';
|
|
6
|
+
export type { SealedLinkRefusedProps } from './SealedLinkRefused.tsx';
|
|
7
|
+
export { SealedLinkRefused } from './SealedLinkRefused.tsx';
|
|
6
8
|
export type { ShareButtonProps, ShareButtonVariant } from './ShareButton.tsx';
|
|
7
9
|
export { ShareButton } from './ShareButton.tsx';
|
|
8
10
|
export type { ShareDialogProps } from './ShareDialog.tsx';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/share/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/share/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/lib/share/ui/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { HiddenPartsProvider } from "./HiddenPartsProvider.js";
|
|
2
2
|
export { useIsHidden } from "./hiddenParts.js";
|
|
3
3
|
export { PagePart } from "./PagePart.js";
|
|
4
|
+
export { SealedLinkRefused } from "./SealedLinkRefused.js";
|
|
4
5
|
export { ShareButton } from "./ShareButton.js";
|
|
5
6
|
export { ShareDialog } from "./ShareDialog.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/share/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAgB,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAmB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/share/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAgB,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAyB,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAmB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAmB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The link the dialog hands out, and whether it may be handed out yet. */
|
|
2
|
+
export interface SealedUrl {
|
|
3
|
+
/** The link: sealed when asked and ready, else the share link itself. */
|
|
4
|
+
link: string;
|
|
5
|
+
/** False while the link is being sealed, when only the plain one exists. */
|
|
6
|
+
ready: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The link the dialog hands out: the share link itself, or its sealed form.
|
|
10
|
+
* Sealing is asynchronous, so a sealed link is not ready at once, and a link
|
|
11
|
+
* sealed for an older draft is never answered for the current one.
|
|
12
|
+
* @param url - The share link.
|
|
13
|
+
* @param sealed - Whether to hand out its sealed form.
|
|
14
|
+
* @returns The link, and whether it is ready.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useSealedUrl(url: string, sealed: boolean): SealedUrl;
|
|
17
|
+
//# sourceMappingURL=useSealedUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSealedUrl.d.ts","sourceRoot":"","sources":["../../../src/share/ui/useSealedUrl.ts"],"names":[],"mappings":"AAIA,2EAA2E;AAC3E,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CAmBpE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { sealShareUrl } from "../core/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* The link the dialog hands out: the share link itself, or its sealed form.
|
|
5
|
+
* Sealing is asynchronous, so a sealed link is not ready at once, and a link
|
|
6
|
+
* sealed for an older draft is never answered for the current one.
|
|
7
|
+
* @param url - The share link.
|
|
8
|
+
* @param sealed - Whether to hand out its sealed form.
|
|
9
|
+
* @returns The link, and whether it is ready.
|
|
10
|
+
*/
|
|
11
|
+
export function useSealedUrl(url, sealed) {
|
|
12
|
+
const [result, setResult] = useState(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!sealed)
|
|
15
|
+
return;
|
|
16
|
+
let current = true;
|
|
17
|
+
void sealShareUrl(url).then((to) => {
|
|
18
|
+
if (current)
|
|
19
|
+
setResult({ from: url, to });
|
|
20
|
+
});
|
|
21
|
+
return () => {
|
|
22
|
+
current = false;
|
|
23
|
+
};
|
|
24
|
+
}, [url, sealed]);
|
|
25
|
+
if (!sealed)
|
|
26
|
+
return { link: url, ready: true };
|
|
27
|
+
if (result?.from === url)
|
|
28
|
+
return { link: result.to, ready: true };
|
|
29
|
+
return { link: url, ready: false };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=useSealedUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSealedUrl.js","sourceRoot":"","sources":["../../../src/share/ui/useSealedUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAUhD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,MAAe;IACvD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAClC,IAAI,CACL,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE;YACjC,IAAI,OAAO;gBAAE,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAElB,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/C,IAAI,MAAM,EAAE,IAAI,KAAK,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAClE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC"}
|
package/lib/vite.d.ts
CHANGED
package/lib/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/lib/vite.js
CHANGED
package/lib/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-cheminfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React components, hooks and framework-free helpers shared by the cheminfo sites: site chrome, citations, sharing, routing, pedagogy, charts, and the structure, orbital and 3D molecule viewers",
|
|
6
6
|
"author": "Luc Patiny",
|
package/src/i18n/core/index.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type {
|
|
|
15
15
|
} from './messageCatalog.ts';
|
|
16
16
|
export { MessageCatalog } from './messageCatalog.ts';
|
|
17
17
|
export type { MessageValues } from './messageValues.ts';
|
|
18
|
+
export type { Translate } from './translate.ts';
|
|
19
|
+
export { catalogTranslate } from './translate.ts';
|
|
18
20
|
export type { ProsePiece } from './prose.ts';
|
|
19
21
|
export { splitProse } from './prose.ts';
|
|
20
22
|
export type { MessageSession } from './session.ts';
|
|
@@ -141,6 +141,19 @@ export class MessageCatalog<TKey extends string = string> {
|
|
|
141
141
|
return fill(message, values);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Whether the catalog declares a key at all.
|
|
146
|
+
*
|
|
147
|
+
* English is the list of keys, so this is what a loop walking a numbered
|
|
148
|
+
* family of messages — `how.limits.p1`, `p2`, … — stops on, and what tells a
|
|
149
|
+
* page a section was never written from one left untranslated.
|
|
150
|
+
* @param key - Key to look for.
|
|
151
|
+
* @returns True when English carries it.
|
|
152
|
+
*/
|
|
153
|
+
public declares(key: string): boolean {
|
|
154
|
+
return ownMessage(this.source.messages, key) !== undefined;
|
|
155
|
+
}
|
|
156
|
+
|
|
144
157
|
/**
|
|
145
158
|
* The messages of a language, once they are in memory.
|
|
146
159
|
* @param language - Language asked for.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The formatter a catalog's text is read through, outside React.
|
|
3
|
+
*
|
|
4
|
+
* `useT` is this function with the page's language and a redraw wired to it;
|
|
5
|
+
* the build and a site's own tests need the same shape without either, so it
|
|
6
|
+
* lives here rather than in the hook. A site never writes its own: four of
|
|
7
|
+
* them had, each with a slightly different fallback.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Language } from './languages.ts';
|
|
11
|
+
import type { LooseKey, MessageCatalog } from './messageCatalog.ts';
|
|
12
|
+
import type { MessageValues } from './messageValues.ts';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* What text is read with.
|
|
16
|
+
*
|
|
17
|
+
* `t(key)` is a key the catalog declares, checked at compile time.
|
|
18
|
+
* `t.or(key, fallback)` is a key built from the data — a site's id, an
|
|
19
|
+
* element's symbol — which the catalog may not have caught up with yet; it
|
|
20
|
+
* reads as the fallback rather than as a raw key.
|
|
21
|
+
*/
|
|
22
|
+
export type Translate<TKey extends string> = ((
|
|
23
|
+
key: LooseKey<TKey>,
|
|
24
|
+
values?: MessageValues,
|
|
25
|
+
) => string) & {
|
|
26
|
+
or: (key: string, fallback: string, values?: MessageValues) => string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A catalog's formatter, in one language.
|
|
31
|
+
*
|
|
32
|
+
* In a component this is `useT`, which also redraws when the language or a
|
|
33
|
+
* translator's edit changes it. Here it is for the places a hook cannot go:
|
|
34
|
+
* the build writing a head per address per language, a test asserting on the
|
|
35
|
+
* text a page shows, a label computed in a module helper.
|
|
36
|
+
* @param catalog - The catalog to read, typed by its English keys.
|
|
37
|
+
* @param language - The language to read it in.
|
|
38
|
+
* @returns See {@link Translate}.
|
|
39
|
+
*/
|
|
40
|
+
export function catalogTranslate<TKey extends string>(
|
|
41
|
+
catalog: MessageCatalog<TKey>,
|
|
42
|
+
language: Language,
|
|
43
|
+
): Translate<TKey> {
|
|
44
|
+
// `or` is a property of the function itself, so the two are built together
|
|
45
|
+
// rather than assigned onto a value a render may already have read.
|
|
46
|
+
const translate = (key: LooseKey<TKey>, values?: MessageValues) =>
|
|
47
|
+
catalog.translate(key, language, { values });
|
|
48
|
+
translate.or = (key: string, fallback: string, values?: MessageValues) =>
|
|
49
|
+
catalog.translate(key, language, { fallback, values });
|
|
50
|
+
return translate;
|
|
51
|
+
}
|
package/src/i18n/ui/useT.ts
CHANGED
|
@@ -3,27 +3,17 @@ import { CHROME_CATALOG } from '../core/chromeCatalog.ts';
|
|
|
3
3
|
import type {
|
|
4
4
|
Language,
|
|
5
5
|
LooseKey,
|
|
6
|
-
|
|
6
|
+
Translate,
|
|
7
7
|
TranslateOptions,
|
|
8
8
|
} from '../core/index.ts';
|
|
9
|
+
import { catalogTranslate } from '../core/index.ts';
|
|
9
10
|
import type { MessageCatalog } from '../core/messageCatalog.ts';
|
|
10
11
|
|
|
11
12
|
import { useLanguage, useMessagesVersion } from './useLanguage.ts';
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* `t(key)` is a key the catalog declares, checked at compile time.
|
|
17
|
-
* `t.or(key, fallback)` is a key built from the data — a site's id, an
|
|
18
|
-
* element's symbol — which the catalog may not have caught up with yet; it
|
|
19
|
-
* reads as the fallback rather than as a raw key.
|
|
20
|
-
*/
|
|
21
|
-
export type Translate<TKey extends string> = ((
|
|
22
|
-
key: LooseKey<TKey>,
|
|
23
|
-
values?: MessageValues,
|
|
24
|
-
) => string) & {
|
|
25
|
-
or: (key: string, fallback: string, values?: MessageValues) => string;
|
|
26
|
-
};
|
|
14
|
+
// The formatter's own shape belongs to the catalog, not to the hook, and a site
|
|
15
|
+
// reads it from either entry point.
|
|
16
|
+
export type { Translate } from '../core/index.ts';
|
|
27
17
|
|
|
28
18
|
/**
|
|
29
19
|
* The formatter of a catalog's text, in the language the page is written in.
|
|
@@ -40,20 +30,7 @@ export function useT<TKey extends string>(
|
|
|
40
30
|
const language = useLanguage();
|
|
41
31
|
useMessagesVersion();
|
|
42
32
|
catalog.prefetch(language);
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Built outside the hook, because the `or` form is a property of the function
|
|
47
|
-
// itself and a render may not write to a value it has just read.
|
|
48
|
-
function translator<TKey extends string>(
|
|
49
|
-
catalog: MessageCatalog<TKey>,
|
|
50
|
-
language: Language,
|
|
51
|
-
): Translate<TKey> {
|
|
52
|
-
const translate = (key: LooseKey<TKey>, values?: MessageValues) =>
|
|
53
|
-
catalog.translate(key, language, { values });
|
|
54
|
-
translate.or = (key: string, fallback: string, values?: MessageValues) =>
|
|
55
|
-
catalog.translate(key, language, { fallback, values });
|
|
56
|
-
return translate;
|
|
33
|
+
return catalogTranslate(catalog, language);
|
|
57
34
|
}
|
|
58
35
|
|
|
59
36
|
/**
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A site's catalogs as the build reads them: all of them, off disk, at once.
|
|
3
|
+
*
|
|
4
|
+
* The page and the build want opposite things from the same files. A browser
|
|
5
|
+
* fetches one language — the one being read — so `en.json` is part of the
|
|
6
|
+
* bundle and the others are `import()`ed when a visitor asks, which is what
|
|
7
|
+
* keeps a site nobody reads in German from downloading the German. The build
|
|
8
|
+
* writes a head per address per language in one pass, so it wants every
|
|
9
|
+
* language, synchronously, before the first route table is asked for.
|
|
10
|
+
*
|
|
11
|
+
* Reading them rather than fetching them is what makes that possible. The
|
|
12
|
+
* page's loaders are written bare — `import('../locales/fr.json')` with no
|
|
13
|
+
* `with { type: 'json' }` — because the dev server serves a JSON file as a
|
|
14
|
+
* JavaScript module and a browser refuses a chunk it was promised JSON for.
|
|
15
|
+
* Node demands the attribute, so it cannot run those loaders: a build that
|
|
16
|
+
* awaited them had to be async and still only worked by keeping a second,
|
|
17
|
+
* eagerly imported copy of every catalog beside the first. `readFileSync` has
|
|
18
|
+
* no attribute, so there is nothing to work around.
|
|
19
|
+
*
|
|
20
|
+
* The identity comes from the page's own catalog, never re-typed here: pass
|
|
21
|
+
* `SITE_CATALOG.source` and the two provably name the same files.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { readFileSync } from 'node:fs';
|
|
25
|
+
import { join, resolve } from 'node:path';
|
|
26
|
+
|
|
27
|
+
import type { Language } from '../core/index.ts';
|
|
28
|
+
import { DEFAULT_LANGUAGE, LANGUAGES, MessageCatalog } from '../core/index.ts';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Which catalog to read, which is the page catalog's own `source`.
|
|
32
|
+
*
|
|
33
|
+
* `MessageCatalog` publishes it for the translate overlay, and it already
|
|
34
|
+
* carries the three things a reader needs. Hand it over rather than writing
|
|
35
|
+
* them twice: a build that names its own directory is a build that can come to
|
|
36
|
+
* disagree with the page about which files the site is translated in.
|
|
37
|
+
*/
|
|
38
|
+
export interface LocaleCatalogSource {
|
|
39
|
+
/**
|
|
40
|
+
* The name the page knows the catalog by, which is the site's host, e.g.
|
|
41
|
+
* `surge.cheminfo.org`. A translator's edit is routed back to the right
|
|
42
|
+
* repository with it, so the build and the page must agree on it.
|
|
43
|
+
*/
|
|
44
|
+
id: string;
|
|
45
|
+
/** The GitHub repository the files live in, written `owner/repo`. */
|
|
46
|
+
repository: string;
|
|
47
|
+
/** The directory holding the locale files, relative to the repository root. */
|
|
48
|
+
directory: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Where the directory is looked for. */
|
|
52
|
+
export interface LocaleCatalogOptions {
|
|
53
|
+
/**
|
|
54
|
+
* What the source's relative `directory` is resolved against. The default is
|
|
55
|
+
* the working directory, which is the repository root for both callers: a
|
|
56
|
+
* Vite config and a vitest run.
|
|
57
|
+
* @default process.cwd()
|
|
58
|
+
*/
|
|
59
|
+
root?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Every language a site is written in, read off disk into one catalog.
|
|
64
|
+
*
|
|
65
|
+
* For the build and for a site's own tests, never for the page: it reads the
|
|
66
|
+
* filesystem, and the translations it holds are tens of kilobytes a first
|
|
67
|
+
* visit must not pay for. Read one language out of it with `catalogTranslate`.
|
|
68
|
+
*
|
|
69
|
+
* A language whose file is absent is left out, which the catalog already reads
|
|
70
|
+
* as English — a half-translated site serves the pages it has rather than
|
|
71
|
+
* failing the build. A missing English file is a misconfiguration and throws:
|
|
72
|
+
* every key and every fallback is declared there.
|
|
73
|
+
* @param source - The page catalog's own `source`. See {@link LocaleCatalogSource}.
|
|
74
|
+
* @param options - See {@link LocaleCatalogOptions}.
|
|
75
|
+
* @returns The catalog, every language it carries already in memory.
|
|
76
|
+
*/
|
|
77
|
+
export function readLocaleCatalog<TKey extends string = string>(
|
|
78
|
+
source: LocaleCatalogSource,
|
|
79
|
+
options: LocaleCatalogOptions = {},
|
|
80
|
+
): MessageCatalog<TKey> {
|
|
81
|
+
const { id, repository, directory } = source;
|
|
82
|
+
const folder = resolve(options.root ?? process.cwd(), directory);
|
|
83
|
+
const english = readMessages(folder, DEFAULT_LANGUAGE);
|
|
84
|
+
if (english === undefined) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`no ${DEFAULT_LANGUAGE}.json in ${folder}: a catalog declares its keys and its fallbacks there`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
const translations: Partial<Record<Language, Record<string, string>>> = {};
|
|
90
|
+
for (const language of LANGUAGES) {
|
|
91
|
+
if (language === DEFAULT_LANGUAGE) continue;
|
|
92
|
+
const messages = readMessages(folder, language);
|
|
93
|
+
if (messages !== undefined) translations[language] = messages;
|
|
94
|
+
}
|
|
95
|
+
return new MessageCatalog<TKey>({
|
|
96
|
+
id,
|
|
97
|
+
repository,
|
|
98
|
+
directory,
|
|
99
|
+
source: english,
|
|
100
|
+
translations,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* One language's messages, read off disk.
|
|
106
|
+
* @param folder - The resolved directory holding the locale files.
|
|
107
|
+
* @param language - The language whose file to read.
|
|
108
|
+
* @returns Its messages, or `undefined` when the site does not carry it.
|
|
109
|
+
*/
|
|
110
|
+
function readMessages(
|
|
111
|
+
folder: string,
|
|
112
|
+
language: Language,
|
|
113
|
+
): Record<string, string> | undefined {
|
|
114
|
+
let text: string;
|
|
115
|
+
try {
|
|
116
|
+
text = readFileSync(join(folder, `${language}.json`), 'utf8');
|
|
117
|
+
} catch {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
return JSON.parse(text) as Record<string, string>;
|
|
121
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createContext, use } from 'react';
|
|
2
2
|
|
|
3
|
+
import { pageLocation } from '../../router/core/pageAddress.ts';
|
|
3
4
|
import { readLanguageParam } from '../core/languageParam.ts';
|
|
4
5
|
|
|
5
6
|
/** What a site declares the page is being read in. */
|
|
@@ -16,5 +17,5 @@ export const SiteLanguageContext = createContext<string | undefined>(undefined);
|
|
|
16
17
|
export function useSiteLanguage(): string | undefined {
|
|
17
18
|
const declared = use(SiteLanguageContext);
|
|
18
19
|
if (declared !== undefined) return declared;
|
|
19
|
-
return readLanguageParam(
|
|
20
|
+
return readLanguageParam(pageLocation()?.search ?? '');
|
|
20
21
|
}
|
package/src/locales/de.json
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"share.layout": "Darstellung",
|
|
55
55
|
"share.embed": "In eine andere Seite einbetten",
|
|
56
56
|
"share.embedHint": "Lässt Kopfzeile und Navigation der Website weg, damit die Seite in einer Seite von Ihnen sitzt.",
|
|
57
|
+
"share.protect": "Diesen Link schützen",
|
|
58
|
+
"share.protectHint": "Die Klasse kann weder lesen noch ändern, was der Link einstellt, und die Adresse der Seite bleibt fest. Die Seite wird eingebettet.",
|
|
57
59
|
"share.on": "Ein",
|
|
58
60
|
"share.off": "Aus",
|
|
59
61
|
"share.showOnPage": "Auf der Seite zeigen",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"share.copyIframe": "Iframe kopieren",
|
|
77
79
|
"share.copyIframeHelpTitle": "Die Seite in Ihre einbauen",
|
|
78
80
|
"share.copyIframeHelp": "Ein HTML-Schnipsel, das dort eingefügt wird, wo das HTML Ihrer Seite bearbeitet wird: das Werkzeug läuft dann darin.",
|
|
81
|
+
"seal.refusedTitle": "Dieser Link lässt sich nicht öffnen",
|
|
82
|
+
"seal.refusedBody": "Er wurde nach dem Erstellen verändert oder ist unvollständig, daher wurde nichts geöffnet. Bitten Sie erneut um den Link.",
|
|
83
|
+
"seal.openWithout": "Das Werkzeug ohne den Link öffnen",
|
|
79
84
|
"cite.button": "Zitieren",
|
|
80
85
|
"cite.copyReferenceAs": "Literaturangabe kopieren als",
|
|
81
86
|
"cite.pleaseCiteBoth": "Bitte zitieren Sie beide Arbeiten",
|
package/src/locales/en.json
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"share.layout": "Layout",
|
|
55
55
|
"share.embed": "Embed in another page",
|
|
56
56
|
"share.embedHint": "Drops the site header and its navigation, so the page sits inside a page of your own.",
|
|
57
|
+
"share.protect": "Protect this link",
|
|
58
|
+
"share.protectHint": "The class can neither read nor change what the link sets up, and the page's address stays fixed. The page is embedded.",
|
|
57
59
|
"share.on": "On",
|
|
58
60
|
"share.off": "Off",
|
|
59
61
|
"share.showOnPage": "Show on the page",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"share.copyIframe": "Copy the iframe",
|
|
77
79
|
"share.copyIframeHelpTitle": "Put the page inside yours",
|
|
78
80
|
"share.copyIframeHelp": "A snippet of HTML to paste where your own page's HTML is edited: the tool then runs inside it.",
|
|
81
|
+
"seal.refusedTitle": "This link cannot be opened",
|
|
82
|
+
"seal.refusedBody": "It was changed after it was made, or it is incomplete, so nothing was opened. Ask for the link again.",
|
|
83
|
+
"seal.openWithout": "Open the tool without it",
|
|
79
84
|
"cite.button": "Cite",
|
|
80
85
|
"cite.copyReferenceAs": "Copy the reference as",
|
|
81
86
|
"cite.pleaseCiteBoth": "Please cite both works",
|
package/src/locales/es.json
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"share.layout": "Disposición",
|
|
55
55
|
"share.embed": "Incrustar en otra página",
|
|
56
56
|
"share.embedHint": "Quita la cabecera del sitio y su navegación, para que la página quede dentro de una página suya.",
|
|
57
|
+
"share.protect": "Proteger este enlace",
|
|
58
|
+
"share.protectHint": "La clase no puede leer ni cambiar lo que configura el enlace, y la dirección de la página queda fija. La página se integra.",
|
|
57
59
|
"share.on": "Sí",
|
|
58
60
|
"share.off": "No",
|
|
59
61
|
"share.showOnPage": "Mostrar en la página",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"share.copyIframe": "Copiar el iframe",
|
|
77
79
|
"share.copyIframeHelpTitle": "Poner la página dentro de la tuya",
|
|
78
80
|
"share.copyIframeHelp": "Un fragmento de HTML para pegar donde se edita el HTML de tu página: la herramienta funciona dentro de él.",
|
|
81
|
+
"seal.refusedTitle": "Este enlace no se puede abrir",
|
|
82
|
+
"seal.refusedBody": "Se modificó después de crearse, o está incompleto, así que no se abrió nada. Pide el enlace de nuevo.",
|
|
83
|
+
"seal.openWithout": "Abrir la herramienta sin el enlace",
|
|
79
84
|
"cite.button": "Citar",
|
|
80
85
|
"cite.copyReferenceAs": "Copiar la referencia como",
|
|
81
86
|
"cite.pleaseCiteBoth": "Por favor, cite ambos trabajos",
|
package/src/locales/fr.json
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"share.layout": "Disposition",
|
|
55
55
|
"share.embed": "Intégrer dans une autre page",
|
|
56
56
|
"share.embedHint": "Retire l'en-tête du site et sa navigation, pour que la page prenne place dans une page à vous.",
|
|
57
|
+
"share.protect": "Protéger ce lien",
|
|
58
|
+
"share.protectHint": "La classe ne peut ni lire ni modifier ce que le lien règle, et l'adresse de la page reste fixe. La page est intégrée.",
|
|
57
59
|
"share.on": "Oui",
|
|
58
60
|
"share.off": "Non",
|
|
59
61
|
"share.showOnPage": "Afficher sur la page",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"share.copyIframe": "Copier l'iframe",
|
|
77
79
|
"share.copyIframeHelpTitle": "Mettre la page dans la vôtre",
|
|
78
80
|
"share.copyIframeHelp": "Un extrait de HTML à coller là où le HTML de votre page s'édite : l'outil s'exécute alors à l'intérieur.",
|
|
81
|
+
"seal.refusedTitle": "Ce lien ne peut pas être ouvert",
|
|
82
|
+
"seal.refusedBody": "Il a été modifié après sa création, ou il est incomplet : rien n'a été ouvert. Demandez à nouveau le lien.",
|
|
83
|
+
"seal.openWithout": "Ouvrir l'outil sans ce lien",
|
|
79
84
|
"cite.button": "Citer",
|
|
80
85
|
"cite.copyReferenceAs": "Copier la référence en",
|
|
81
86
|
"cite.pleaseCiteBoth": "Merci de citer les deux travaux",
|
package/src/locales/it.json
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"share.layout": "Disposizione",
|
|
55
55
|
"share.embed": "Incorporare in un'altra pagina",
|
|
56
56
|
"share.embedHint": "Toglie l'intestazione del sito e la sua navigazione, così la pagina sta dentro una pagina propria.",
|
|
57
|
+
"share.protect": "Proteggi questo link",
|
|
58
|
+
"share.protectHint": "La classe non può né leggere né modificare ciò che il link imposta, e l'indirizzo della pagina resta fisso. La pagina viene incorporata.",
|
|
57
59
|
"share.on": "Sì",
|
|
58
60
|
"share.off": "No",
|
|
59
61
|
"share.showOnPage": "Mostra nella pagina",
|
|
@@ -76,6 +78,9 @@
|
|
|
76
78
|
"share.copyIframe": "Copia l'iframe",
|
|
77
79
|
"share.copyIframeHelpTitle": "Mettere la pagina dentro la tua",
|
|
78
80
|
"share.copyIframeHelp": "Un frammento di HTML da incollare dove si modifica l'HTML della tua pagina: lo strumento funziona al suo interno.",
|
|
81
|
+
"seal.refusedTitle": "Questo link non può essere aperto",
|
|
82
|
+
"seal.refusedBody": "È stato modificato dopo la creazione, o è incompleto, quindi non si è aperto nulla. Chiedi di nuovo il link.",
|
|
83
|
+
"seal.openWithout": "Apri lo strumento senza il link",
|
|
79
84
|
"cite.button": "Cita",
|
|
80
85
|
"cite.copyReferenceAs": "Copia il riferimento come",
|
|
81
86
|
"cite.pleaseCiteBoth": "Si prega di citare entrambi i lavori",
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* The tab router bound to the browser: read the address on screen, write a new
|
|
3
3
|
* one through the History API, and hear every move.
|
|
4
4
|
*
|
|
5
|
-
* The router itself stays pure. Everything here reads
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The router itself stays pure. Everything here reads and writes the address
|
|
6
|
+
* through `pageLocation` and `pageHistory` — the browser's, or the one a sealed
|
|
7
|
+
* link holds in memory — and does nothing where neither exists, so a prerender
|
|
8
|
+
* script can import a module that uses it.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import { EMBED_PARAM, HIDE_PARAM } from '../../share/core/config.ts';
|
|
11
12
|
|
|
13
|
+
import { pageHistory, pageLocation } from './pageAddress.ts';
|
|
12
14
|
import type { QueryEntry } from './query.ts';
|
|
13
15
|
import { formatQueryEntries } from './query.ts';
|
|
14
16
|
import type { TabRoute, TabRouteInput, TabRouter } from './tabRouter.ts';
|
|
@@ -34,7 +36,7 @@ export function readRoute<Tab extends string>(
|
|
|
34
36
|
const address = currentAddress();
|
|
35
37
|
const adopted = router.legacyAddress(address);
|
|
36
38
|
if (adopted === null) return router.parse(address);
|
|
37
|
-
const history =
|
|
39
|
+
const history = pageHistory();
|
|
38
40
|
history?.replaceState(history.state, '', adopted);
|
|
39
41
|
globalThis.dispatchEvent?.(new Event(ROUTE_CHANGE_EVENT));
|
|
40
42
|
return router.parse(adopted);
|
|
@@ -78,8 +80,8 @@ export function writeRoute<Tab extends string>(
|
|
|
78
80
|
): string {
|
|
79
81
|
const current = currentAddress();
|
|
80
82
|
const address = withKeptParams(router, route, current, options.keep ?? []);
|
|
81
|
-
const location =
|
|
82
|
-
const history =
|
|
83
|
+
const location = pageLocation();
|
|
84
|
+
const history = pageHistory();
|
|
83
85
|
if (location === undefined || history === undefined) return address;
|
|
84
86
|
|
|
85
87
|
const shown =
|
|
@@ -126,7 +128,7 @@ export function subscribeToRoute<Tab extends string>(
|
|
|
126
128
|
* @returns It, or `/` where there is no browser.
|
|
127
129
|
*/
|
|
128
130
|
export function currentAddress(): string {
|
|
129
|
-
const location =
|
|
131
|
+
const location = pageLocation();
|
|
130
132
|
if (location === undefined) return '/';
|
|
131
133
|
return `${location.pathname}${location.search}${location.hash}`;
|
|
132
134
|
}
|
|
@@ -150,11 +152,3 @@ function withKeptParams<Tab extends string>(
|
|
|
150
152
|
const separator = target.includes('?') ? '&' : '?';
|
|
151
153
|
return `${target}${separator}${formatQueryEntries(kept)}`;
|
|
152
154
|
}
|
|
153
|
-
|
|
154
|
-
function browserLocation(): Location | undefined {
|
|
155
|
-
return globalThis.location;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function browserHistory(): History | undefined {
|
|
159
|
-
return globalThis.history;
|
|
160
|
-
}
|
package/src/router/core/index.ts
CHANGED
|
@@ -18,6 +18,14 @@ export type {
|
|
|
18
18
|
LegacyHashOptions,
|
|
19
19
|
} from './legacyHash.ts';
|
|
20
20
|
export { adoptLegacyHashAddress, pathFromLegacyHash } from './legacyHash.ts';
|
|
21
|
+
export type { PageHistory, PageLocation } from './pageAddress.ts';
|
|
22
|
+
export {
|
|
23
|
+
holdPageAddress,
|
|
24
|
+
isPageAddressHeld,
|
|
25
|
+
pageHistory,
|
|
26
|
+
pageLocation,
|
|
27
|
+
releasePageAddress,
|
|
28
|
+
} from './pageAddress.ts';
|
|
21
29
|
export type { QueryEntry, QueryStringOptions } from './query.ts';
|
|
22
30
|
export {
|
|
23
31
|
firstQueryValues,
|