react-cheminfo 0.64.1 → 0.65.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 +282 -0
- package/lib/card/core/cardAddress.d.ts +70 -0
- package/lib/card/core/cardAddress.d.ts.map +1 -0
- package/lib/card/core/cardAddress.js +59 -0
- package/lib/card/core/cardAddress.js.map +1 -0
- package/lib/card/core/cardPageUrl.d.ts +49 -0
- package/lib/card/core/cardPageUrl.d.ts.map +1 -0
- package/lib/card/core/cardPageUrl.js +59 -0
- package/lib/card/core/cardPageUrl.js.map +1 -0
- package/lib/card/core/index.d.ts +7 -0
- package/lib/card/core/index.d.ts.map +1 -0
- package/lib/card/core/index.js +4 -0
- package/lib/card/core/index.js.map +1 -0
- package/lib/card/core/panelRoom.d.ts +40 -0
- package/lib/card/core/panelRoom.d.ts.map +1 -0
- package/lib/card/core/panelRoom.js +40 -0
- package/lib/card/core/panelRoom.js.map +1 -0
- package/lib/card/ui/CardDetailsButton.d.ts +38 -0
- package/lib/card/ui/CardDetailsButton.d.ts.map +1 -0
- package/lib/card/ui/CardDetailsButton.js +50 -0
- package/lib/card/ui/CardDetailsButton.js.map +1 -0
- package/lib/card/ui/CardFigure.d.ts +51 -0
- package/lib/card/ui/CardFigure.d.ts.map +1 -0
- package/lib/card/ui/CardFigure.js +27 -0
- package/lib/card/ui/CardFigure.js.map +1 -0
- package/lib/card/ui/CardFrame.d.ts +30 -0
- package/lib/card/ui/CardFrame.d.ts.map +1 -0
- package/lib/card/ui/CardFrame.js +20 -0
- package/lib/card/ui/CardFrame.js.map +1 -0
- package/lib/card/ui/CopyTableButton.d.ts +37 -0
- package/lib/card/ui/CopyTableButton.d.ts.map +1 -0
- package/lib/card/ui/CopyTableButton.js +19 -0
- package/lib/card/ui/CopyTableButton.js.map +1 -0
- package/lib/card/ui/cardTooltip.d.ts +14 -0
- package/lib/card/ui/cardTooltip.d.ts.map +1 -0
- package/lib/card/ui/cardTooltip.js +15 -0
- package/lib/card/ui/cardTooltip.js.map +1 -0
- package/lib/card/ui/embed.d.ts +15 -0
- package/lib/card/ui/embed.d.ts.map +1 -0
- package/lib/card/ui/embed.js +24 -0
- package/lib/card/ui/embed.js.map +1 -0
- package/lib/card/ui/fitCardToFrame.d.ts +31 -0
- package/lib/card/ui/fitCardToFrame.d.ts.map +1 -0
- package/lib/card/ui/fitCardToFrame.js +66 -0
- package/lib/card/ui/fitCardToFrame.js.map +1 -0
- package/lib/card/ui/holdRoomForPanels.d.ts +16 -0
- package/lib/card/ui/holdRoomForPanels.d.ts.map +1 -0
- package/lib/card/ui/holdRoomForPanels.js +76 -0
- package/lib/card/ui/holdRoomForPanels.js.map +1 -0
- package/lib/card/ui/index.d.ts +11 -0
- package/lib/card/ui/index.d.ts.map +1 -0
- package/lib/card/ui/index.js +7 -0
- package/lib/card/ui/index.js.map +1 -0
- package/lib/card/ui/openPanels.d.ts +25 -0
- package/lib/card/ui/openPanels.d.ts.map +1 -0
- package/lib/card/ui/openPanels.js +85 -0
- package/lib/card/ui/openPanels.js.map +1 -0
- package/lib/card.d.ts +13 -0
- package/lib/card.d.ts.map +1 -0
- package/lib/card.js +13 -0
- package/lib/card.js.map +1 -0
- package/lib/conformers.d.ts +1 -0
- package/lib/conformers.d.ts.map +1 -1
- package/lib/conformers.js +1 -0
- package/lib/conformers.js.map +1 -1
- package/lib/core.d.ts +4 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +5 -0
- package/lib/core.js.map +1 -1
- package/lib/fetch/core/apiError.d.ts +56 -0
- package/lib/fetch/core/apiError.d.ts.map +1 -0
- package/lib/fetch/core/apiError.js +43 -0
- package/lib/fetch/core/apiError.js.map +1 -0
- package/lib/fetch/core/fetchJson.d.ts +47 -0
- package/lib/fetch/core/fetchJson.d.ts.map +1 -0
- package/lib/fetch/core/fetchJson.js +109 -0
- package/lib/fetch/core/fetchJson.js.map +1 -0
- package/lib/fetch/core/index.d.ts +5 -0
- package/lib/fetch/core/index.d.ts.map +1 -0
- package/lib/fetch/core/index.js +3 -0
- package/lib/fetch/core/index.js.map +1 -0
- package/lib/formula/core/formulaText.d.ts +46 -0
- package/lib/formula/core/formulaText.d.ts.map +1 -0
- package/lib/formula/core/formulaText.js +74 -0
- package/lib/formula/core/formulaText.js.map +1 -0
- package/lib/formula/core/index.d.ts +6 -0
- package/lib/formula/core/index.d.ts.map +1 -0
- package/lib/formula/core/index.js +4 -0
- package/lib/formula/core/index.js.map +1 -0
- package/lib/formula/core/normalizeFormula.d.ts +22 -0
- package/lib/formula/core/normalizeFormula.d.ts.map +1 -0
- package/lib/formula/core/normalizeFormula.js +46 -0
- package/lib/formula/core/normalizeFormula.js.map +1 -0
- package/lib/formula/core/readFormula.d.ts +73 -0
- package/lib/formula/core/readFormula.d.ts.map +1 -0
- package/lib/formula/core/readFormula.js +132 -0
- package/lib/formula/core/readFormula.js.map +1 -0
- package/lib/formula/ui/CopyableFormula.d.ts +31 -0
- package/lib/formula/ui/CopyableFormula.d.ts.map +1 -0
- package/lib/formula/ui/CopyableFormula.js +19 -0
- package/lib/formula/ui/CopyableFormula.js.map +1 -0
- package/lib/formula/ui/FormulaInput.d.ts +29 -0
- package/lib/formula/ui/FormulaInput.d.ts.map +1 -0
- package/lib/formula/ui/FormulaInput.js +16 -0
- package/lib/formula/ui/FormulaInput.js.map +1 -0
- package/lib/formula/ui/QuestionFormula.d.ts +14 -0
- package/lib/formula/ui/QuestionFormula.d.ts.map +1 -0
- package/lib/formula/ui/QuestionFormula.js +13 -0
- package/lib/formula/ui/QuestionFormula.js.map +1 -0
- package/lib/formula/ui/index.d.ts +7 -0
- package/lib/formula/ui/index.d.ts.map +1 -0
- package/lib/formula/ui/index.js +4 -0
- package/lib/formula/ui/index.js.map +1 -0
- package/lib/formula.d.ts +11 -0
- package/lib/formula.d.ts.map +1 -0
- package/lib/formula.js +11 -0
- package/lib/formula.js.map +1 -0
- package/lib/hooks/ui/index.d.ts +1 -0
- package/lib/hooks/ui/index.d.ts.map +1 -1
- package/lib/hooks/ui/index.js.map +1 -1
- package/lib/hooks/ui/keyTargets.d.ts +4 -2
- package/lib/hooks/ui/keyTargets.d.ts.map +1 -1
- package/lib/hooks/ui/keyTargets.js +5 -3
- package/lib/hooks/ui/keyTargets.js.map +1 -1
- package/lib/hooks/ui/useAsync.d.ts +20 -5
- package/lib/hooks/ui/useAsync.d.ts.map +1 -1
- package/lib/hooks/ui/useAsync.js +29 -14
- package/lib/hooks/ui/useAsync.js.map +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/locales/de.json +37 -0
- package/lib/locales/en.json +37 -0
- package/lib/locales/es.json +37 -0
- package/lib/locales/fr.json +37 -0
- package/lib/locales/it.json +37 -0
- package/lib/moleculesClient/core/index.d.ts +5 -0
- package/lib/moleculesClient/core/index.d.ts.map +1 -0
- package/lib/moleculesClient/core/index.js +3 -0
- package/lib/moleculesClient/core/index.js.map +1 -0
- package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
- package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesClient.js +105 -0
- package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
- package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
- package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
- package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
- package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
- package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesTypes.js +2 -0
- package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
- package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
- package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
- package/lib/moleculesClient/core/requestRetry.js +108 -0
- package/lib/moleculesClient/core/requestRetry.js.map +1 -0
- package/lib/molstar/core/camera.d.ts +2 -1
- package/lib/molstar/core/camera.d.ts.map +1 -1
- package/lib/molstar/core/camera.js +3 -2
- package/lib/molstar/core/camera.js.map +1 -1
- package/lib/molstar/core/framing.d.ts +102 -0
- package/lib/molstar/core/framing.d.ts.map +1 -0
- package/lib/molstar/core/framing.js +120 -0
- package/lib/molstar/core/framing.js.map +1 -0
- package/lib/molstar/core/hover.d.ts +16 -0
- package/lib/molstar/core/hover.d.ts.map +1 -1
- package/lib/molstar/core/hover.js +14 -0
- package/lib/molstar/core/hover.js.map +1 -1
- package/lib/molstar/core/index.d.ts +4 -1
- package/lib/molstar/core/index.d.ts.map +1 -1
- package/lib/molstar/core/index.js +2 -1
- package/lib/molstar/core/index.js.map +1 -1
- package/lib/pedagogy/core/answers.d.ts +46 -0
- package/lib/pedagogy/core/answers.d.ts.map +1 -0
- package/lib/pedagogy/core/answers.js +77 -0
- package/lib/pedagogy/core/answers.js.map +1 -0
- package/lib/pedagogy/core/attempts.d.ts +86 -0
- package/lib/pedagogy/core/attempts.d.ts.map +1 -0
- package/lib/pedagogy/core/attempts.js +117 -0
- package/lib/pedagogy/core/attempts.js.map +1 -0
- package/lib/pedagogy/core/index.d.ts +8 -0
- package/lib/pedagogy/core/index.d.ts.map +1 -1
- package/lib/pedagogy/core/index.js +4 -0
- package/lib/pedagogy/core/index.js.map +1 -1
- package/lib/pedagogy/core/progressController.d.ts +64 -0
- package/lib/pedagogy/core/progressController.d.ts.map +1 -0
- package/lib/pedagogy/core/progressController.js +56 -0
- package/lib/pedagogy/core/progressController.js.map +1 -0
- package/lib/pedagogy/core/seed.d.ts +96 -0
- package/lib/pedagogy/core/seed.d.ts.map +1 -0
- package/lib/pedagogy/core/seed.js +128 -0
- package/lib/pedagogy/core/seed.js.map +1 -0
- package/lib/pedagogy/core/series.d.ts +77 -0
- package/lib/pedagogy/core/series.d.ts.map +1 -0
- package/lib/pedagogy/core/series.js +10 -0
- package/lib/pedagogy/core/series.js.map +1 -0
- package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
- package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
- package/lib/pedagogy/ui/AnswerFields.js +24 -0
- package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
- package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
- package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
- package/lib/pedagogy/ui/ExerciseList.js +53 -0
- package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
- package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
- package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
- package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
- package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
- package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
- package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
- package/lib/pedagogy/ui/QuestionCard.js +73 -0
- package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
- package/lib/pedagogy/ui/index.d.ts +10 -0
- package/lib/pedagogy/ui/index.d.ts.map +1 -1
- package/lib/pedagogy/ui/index.js +6 -0
- package/lib/pedagogy/ui/index.js.map +1 -1
- package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
- package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
- package/lib/pedagogy/ui/seriesCounts.js +27 -0
- package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
- package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
- package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
- package/lib/pedagogy/ui/seriesParts.js +38 -0
- package/lib/pedagogy/ui/seriesParts.js.map +1 -0
- package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
- package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
- package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
- package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +6 -3
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/property/core/copyableText.d.ts +14 -0
- package/lib/property/core/copyableText.d.ts.map +1 -0
- package/lib/property/core/copyableText.js +21 -0
- package/lib/property/core/copyableText.js.map +1 -0
- package/lib/property/core/index.d.ts +2 -0
- package/lib/property/core/index.d.ts.map +1 -0
- package/lib/property/core/index.js +2 -0
- package/lib/property/core/index.js.map +1 -0
- package/lib/property/ui/PropertyTable.d.ts +43 -0
- package/lib/property/ui/PropertyTable.d.ts.map +1 -0
- package/lib/property/ui/PropertyTable.js +19 -0
- package/lib/property/ui/PropertyTable.js.map +1 -0
- package/lib/property/ui/index.d.ts +3 -0
- package/lib/property/ui/index.d.ts.map +1 -0
- package/lib/property/ui/index.js +2 -0
- package/lib/property/ui/index.js.map +1 -0
- package/lib/router/core/history.d.ts +24 -3
- package/lib/router/core/history.d.ts.map +1 -1
- package/lib/router/core/history.js +55 -7
- package/lib/router/core/history.js.map +1 -1
- package/lib/router/core/index.d.ts +3 -3
- package/lib/router/core/index.d.ts.map +1 -1
- package/lib/router/core/index.js +2 -2
- package/lib/router/core/index.js.map +1 -1
- package/lib/router/core/languageRoute.d.ts +61 -0
- package/lib/router/core/languageRoute.d.ts.map +1 -0
- package/lib/router/core/languageRoute.js +96 -0
- package/lib/router/core/languageRoute.js.map +1 -0
- package/lib/router/core/siteAddresses.d.ts +23 -0
- package/lib/router/core/siteAddresses.d.ts.map +1 -1
- package/lib/router/core/siteAddresses.js +26 -0
- package/lib/router/core/siteAddresses.js.map +1 -1
- package/lib/router/core/tabRouter.d.ts +2 -108
- package/lib/router/core/tabRouter.d.ts.map +1 -1
- package/lib/router/core/tabRouter.js +38 -5
- package/lib/router/core/tabRouter.js.map +1 -1
- package/lib/router/core/tabRouterTypes.d.ts +154 -0
- package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
- package/lib/router/core/tabRouterTypes.js +2 -0
- package/lib/router/core/tabRouterTypes.js.map +1 -0
- package/lib/seo/core/fitDescription.d.ts +40 -0
- package/lib/seo/core/fitDescription.d.ts.map +1 -0
- package/lib/seo/core/fitDescription.js +45 -0
- package/lib/seo/core/fitDescription.js.map +1 -0
- package/lib/seo/core/index.d.ts +7 -0
- package/lib/seo/core/index.d.ts.map +1 -1
- package/lib/seo/core/index.js +4 -0
- package/lib/seo/core/index.js.map +1 -1
- package/lib/seo/core/limits.d.ts +24 -0
- package/lib/seo/core/limits.d.ts.map +1 -0
- package/lib/seo/core/limits.js +24 -0
- package/lib/seo/core/limits.js.map +1 -0
- package/lib/seo/core/pageContent.d.ts +25 -0
- package/lib/seo/core/pageContent.d.ts.map +1 -0
- package/lib/seo/core/pageContent.js +25 -0
- package/lib/seo/core/pageContent.js.map +1 -0
- package/lib/seo/core/plainDescription.d.ts.map +1 -1
- package/lib/seo/core/plainDescription.js +3 -2
- package/lib/seo/core/plainDescription.js.map +1 -1
- package/lib/seo/core/routeProblems.d.ts.map +1 -1
- package/lib/seo/core/routeProblems.js +1 -6
- package/lib/seo/core/routeProblems.js.map +1 -1
- package/lib/seo/core/routeTable.d.ts +31 -0
- package/lib/seo/core/routeTable.d.ts.map +1 -0
- package/lib/seo/core/routeTable.js +96 -0
- package/lib/seo/core/routeTable.js.map +1 -0
- package/lib/seo/vite/index.d.ts +2 -0
- package/lib/seo/vite/index.d.ts.map +1 -1
- package/lib/seo/vite/index.js +1 -0
- package/lib/seo/vite/index.js.map +1 -1
- package/lib/seo/vite/prerender.d.ts +10 -0
- package/lib/seo/vite/prerender.d.ts.map +1 -1
- package/lib/seo/vite/prerender.js +12 -1
- package/lib/seo/vite/prerender.js.map +1 -1
- package/lib/seo/vite/routeTable.d.ts +40 -0
- package/lib/seo/vite/routeTable.d.ts.map +1 -0
- package/lib/seo/vite/routeTable.js +44 -0
- package/lib/seo/vite/routeTable.js.map +1 -0
- package/lib/server/answerAddresses.d.ts +51 -0
- package/lib/server/answerAddresses.d.ts.map +1 -0
- package/lib/server/answerAddresses.js +72 -0
- package/lib/server/answerAddresses.js.map +1 -0
- package/lib/server/cardMeta.d.ts +57 -0
- package/lib/server/cardMeta.d.ts.map +1 -0
- package/lib/server/cardMeta.js +52 -0
- package/lib/server/cardMeta.js.map +1 -0
- package/lib/server/config.d.ts +72 -0
- package/lib/server/config.d.ts.map +1 -0
- package/lib/server/config.js +67 -0
- package/lib/server/config.js.map +1 -0
- package/lib/server/envNumber.d.ts +35 -0
- package/lib/server/envNumber.d.ts.map +1 -0
- package/lib/server/envNumber.js +42 -0
- package/lib/server/envNumber.js.map +1 -0
- package/lib/server/healthRoute.d.ts +26 -0
- package/lib/server/healthRoute.d.ts.map +1 -0
- package/lib/server/healthRoute.js +22 -0
- package/lib/server/healthRoute.js.map +1 -0
- package/lib/server/listenSite.d.ts +38 -0
- package/lib/server/listenSite.d.ts.map +1 -0
- package/lib/server/listenSite.js +60 -0
- package/lib/server/listenSite.js.map +1 -0
- package/lib/server/mcpServer.d.ts +8 -0
- package/lib/server/mcpServer.d.ts.map +1 -0
- package/lib/server/mcpServer.js +11 -0
- package/lib/server/mcpServer.js.map +1 -0
- package/lib/server/repositoryVersion.d.ts +16 -0
- package/lib/server/repositoryVersion.d.ts.map +1 -0
- package/lib/server/repositoryVersion.js +33 -0
- package/lib/server/repositoryVersion.js.map +1 -0
- package/lib/server/routeOptions.d.ts +23 -0
- package/lib/server/routeOptions.d.ts.map +1 -0
- package/lib/server/routeOptions.js +20 -0
- package/lib/server/routeOptions.js.map +1 -0
- package/lib/server/routeTable.d.ts +14 -0
- package/lib/server/routeTable.d.ts.map +1 -0
- package/lib/server/routeTable.js +32 -0
- package/lib/server/routeTable.js.map +1 -0
- package/lib/server/siteView.d.ts +29 -0
- package/lib/server/siteView.d.ts.map +1 -0
- package/lib/server/siteView.js +21 -0
- package/lib/server/siteView.js.map +1 -0
- package/lib/server/spaPages.d.ts +32 -0
- package/lib/server/spaPages.d.ts.map +1 -0
- package/lib/server/spaPages.js +126 -0
- package/lib/server/spaPages.js.map +1 -0
- package/lib/server/spaSite.d.ts +30 -0
- package/lib/server/spaSite.d.ts.map +1 -0
- package/lib/server/spaSite.js +170 -0
- package/lib/server/spaSite.js.map +1 -0
- package/lib/server/spaSiteOptions.d.ts +126 -0
- package/lib/server/spaSiteOptions.d.ts.map +1 -0
- package/lib/server/spaSiteOptions.js +2 -0
- package/lib/server/spaSiteOptions.js.map +1 -0
- package/lib/server/staticSite.d.ts +9 -0
- package/lib/server/staticSite.d.ts.map +1 -1
- package/lib/server/staticSite.js +41 -19
- package/lib/server/staticSite.js.map +1 -1
- package/lib/server/toolSiteServer.d.ts +77 -0
- package/lib/server/toolSiteServer.d.ts.map +1 -0
- package/lib/server/toolSiteServer.js +58 -0
- package/lib/server/toolSiteServer.js.map +1 -0
- package/lib/server/trustProxy.d.ts +20 -0
- package/lib/server/trustProxy.d.ts.map +1 -0
- package/lib/server/trustProxy.js +32 -0
- package/lib/server/trustProxy.js.map +1 -0
- package/lib/server/types.d.ts +13 -0
- package/lib/server/types.d.ts.map +1 -0
- package/lib/server/types.js +2 -0
- package/lib/server/types.js.map +1 -0
- package/lib/server.d.ts +22 -0
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +12 -0
- package/lib/server.js.map +1 -1
- package/lib/share/core/config.d.ts +18 -0
- package/lib/share/core/config.d.ts.map +1 -1
- package/lib/share/core/config.js +33 -2
- package/lib/share/core/config.js.map +1 -1
- package/lib/share/core/index.d.ts +3 -1
- package/lib/share/core/index.d.ts.map +1 -1
- package/lib/share/core/index.js +2 -1
- package/lib/share/core/index.js.map +1 -1
- package/lib/share/core/keySetParam.d.ts +40 -0
- package/lib/share/core/keySetParam.d.ts.map +1 -0
- package/lib/share/core/keySetParam.js +60 -0
- package/lib/share/core/keySetParam.js.map +1 -0
- package/lib/share/core/vocabulary.d.ts +8 -0
- package/lib/share/core/vocabulary.d.ts.map +1 -1
- package/lib/shell/ui/ShareControl.d.ts +75 -0
- package/lib/shell/ui/ShareControl.d.ts.map +1 -0
- package/lib/shell/ui/ShareControl.js +40 -0
- package/lib/shell/ui/ShareControl.js.map +1 -0
- package/lib/shell/ui/ShellFrame.d.ts +14 -0
- package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
- package/lib/shell/ui/ShellFrame.js +45 -0
- package/lib/shell/ui/ShellFrame.js.map +1 -0
- package/lib/shell/ui/SiteShell.d.ts +251 -0
- package/lib/shell/ui/SiteShell.d.ts.map +1 -0
- package/lib/shell/ui/SiteShell.js +39 -0
- package/lib/shell/ui/SiteShell.js.map +1 -0
- package/lib/shell/ui/index.d.ts +5 -0
- package/lib/shell/ui/index.d.ts.map +1 -0
- package/lib/shell/ui/index.js +3 -0
- package/lib/shell/ui/index.js.map +1 -0
- package/lib/state/core/index.d.ts +1 -0
- package/lib/state/core/index.d.ts.map +1 -1
- package/lib/state/core/index.js.map +1 -1
- package/lib/state/core/legacyEntries.d.ts +30 -0
- package/lib/state/core/legacyEntries.d.ts.map +1 -0
- package/lib/state/core/legacyEntries.js +51 -0
- package/lib/state/core/legacyEntries.js.map +1 -0
- package/lib/state/core/persistBucket.d.ts +26 -2
- package/lib/state/core/persistBucket.d.ts.map +1 -1
- package/lib/state/core/persistBucket.js +26 -9
- package/lib/state/core/persistBucket.js.map +1 -1
- package/lib/state/core/persistSignalBucket.d.ts +26 -0
- package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
- package/lib/state/core/persistSignalBucket.js +31 -0
- package/lib/state/core/persistSignalBucket.js.map +1 -1
- package/lib/state/core/storageEntry.d.ts +15 -0
- package/lib/state/core/storageEntry.d.ts.map +1 -1
- package/lib/state/core/storageEntry.js +33 -0
- package/lib/state/core/storageEntry.js.map +1 -1
- package/lib/structure/ui/StructureExportButton.d.ts +27 -0
- package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
- package/lib/structure/ui/StructureExportButton.js +21 -0
- package/lib/structure/ui/StructureExportButton.js.map +1 -0
- package/lib/structure/ui/index.d.ts +4 -0
- package/lib/structure/ui/index.d.ts.map +1 -1
- package/lib/structure/ui/index.js +2 -0
- package/lib/structure/ui/index.js.map +1 -1
- package/lib/structure/ui/useStructureDraft.d.ts +32 -0
- package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
- package/lib/structure/ui/useStructureDraft.js +20 -0
- package/lib/structure/ui/useStructureDraft.js.map +1 -0
- package/lib/ui.d.ts +2 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +2 -0
- package/lib/ui.js.map +1 -1
- package/lib/worker/core/index.d.ts +1 -1
- package/lib/worker/core/index.d.ts.map +1 -1
- package/lib/worker/core/messages.d.ts +4 -2
- package/lib/worker/core/messages.d.ts.map +1 -1
- package/lib/worker/core/messages.js.map +1 -1
- package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
- package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
- package/lib/worker/core/oclResourcesUrl.js +19 -0
- package/lib/worker/core/oclResourcesUrl.js.map +1 -0
- package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
- package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
- package/lib/worker/core/serveWorkerRequests.js +15 -2
- package/lib/worker/core/serveWorkerRequests.js.map +1 -1
- package/lib/worker/core/workerChannel.d.ts +3 -4
- package/lib/worker/core/workerChannel.d.ts.map +1 -1
- package/lib/worker/core/workerChannel.js +72 -67
- package/lib/worker/core/workerChannel.js.map +1 -1
- package/lib/worker/core/workerChannelParts.d.ts +17 -6
- package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
- package/lib/worker/core/workerChannelParts.js +20 -4
- package/lib/worker/core/workerChannelParts.js.map +1 -1
- package/lib/worker/core/workerChannelTypes.d.ts +46 -2
- package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
- package/lib/worker/core/workerSlot.d.ts +66 -0
- package/lib/worker/core/workerSlot.d.ts.map +1 -0
- package/lib/worker/core/workerSlot.js +107 -0
- package/lib/worker/core/workerSlot.js.map +1 -0
- package/package.json +16 -1
- package/src/card/core/cardAddress.ts +100 -0
- package/src/card/core/cardPageUrl.ts +97 -0
- package/src/card/core/index.ts +6 -0
- package/src/card/core/panelRoom.ts +66 -0
- package/src/card/ui/CardDetailsButton.tsx +104 -0
- package/src/card/ui/CardFigure.tsx +86 -0
- package/src/card/ui/CardFrame.tsx +46 -0
- package/src/card/ui/CopyTableButton.tsx +81 -0
- package/src/card/ui/cardTooltip.ts +18 -0
- package/src/card/ui/embed.ts +27 -0
- package/src/card/ui/fitCardToFrame.ts +76 -0
- package/src/card/ui/holdRoomForPanels.ts +83 -0
- package/src/card/ui/index.ts +14 -0
- package/src/card/ui/openPanels.ts +106 -0
- package/src/card.ts +13 -0
- package/src/conformers.ts +4 -0
- package/src/core.ts +5 -0
- package/src/fetch/core/apiError.ts +65 -0
- package/src/fetch/core/fetchJson.ts +129 -0
- package/src/fetch/core/index.ts +4 -0
- package/src/formula/core/formulaText.ts +96 -0
- package/src/formula/core/index.ts +20 -0
- package/src/formula/core/normalizeFormula.ts +50 -0
- package/src/formula/core/readFormula.ts +211 -0
- package/src/formula/ui/CopyableFormula.tsx +51 -0
- package/src/formula/ui/FormulaInput.tsx +50 -0
- package/src/formula/ui/QuestionFormula.tsx +20 -0
- package/src/formula/ui/index.ts +6 -0
- package/src/formula.ts +11 -0
- package/src/hooks/ui/index.ts +1 -0
- package/src/hooks/ui/keyTargets.ts +5 -3
- package/src/hooks/ui/useAsync.ts +50 -14
- package/src/locales/de.json +37 -0
- package/src/locales/en.json +37 -0
- package/src/locales/es.json +37 -0
- package/src/locales/fr.json +37 -0
- package/src/locales/it.json +37 -0
- package/src/moleculesClient/core/index.ts +19 -0
- package/src/moleculesClient/core/moleculesClient.ts +175 -0
- package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
- package/src/moleculesClient/core/moleculesTypes.ts +163 -0
- package/src/moleculesClient/core/requestRetry.ts +118 -0
- package/src/molstar/core/camera.ts +3 -2
- package/src/molstar/core/framing.ts +200 -0
- package/src/molstar/core/hover.ts +26 -0
- package/src/molstar/core/index.ts +21 -1
- package/src/pedagogy/core/answers.ts +94 -0
- package/src/pedagogy/core/attempts.ts +205 -0
- package/src/pedagogy/core/index.ts +36 -0
- package/src/pedagogy/core/progressController.ts +116 -0
- package/src/pedagogy/core/seed.ts +177 -0
- package/src/pedagogy/core/series.ts +82 -0
- package/src/pedagogy/ui/AnswerFields.tsx +63 -0
- package/src/pedagogy/ui/ExerciseList.tsx +202 -0
- package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
- package/src/pedagogy/ui/QuestionCard.tsx +231 -0
- package/src/pedagogy/ui/index.ts +18 -0
- package/src/pedagogy/ui/seriesCounts.ts +34 -0
- package/src/pedagogy/ui/seriesParts.tsx +127 -0
- package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
- package/src/periodic/ui/PeriodicTable.tsx +6 -3
- package/src/property/core/copyableText.ts +20 -0
- package/src/property/core/index.ts +1 -0
- package/src/property/ui/PropertyTable.tsx +83 -0
- package/src/property/ui/index.ts +2 -0
- package/src/router/core/history.ts +61 -7
- package/src/router/core/index.ts +3 -2
- package/src/router/core/languageRoute.ts +136 -0
- package/src/router/core/siteAddresses.ts +38 -0
- package/src/router/core/tabRouter.ts +59 -117
- package/src/router/core/tabRouterTypes.ts +158 -0
- package/src/seo/core/fitDescription.ts +74 -0
- package/src/seo/core/index.ts +17 -0
- package/src/seo/core/limits.ts +27 -0
- package/src/seo/core/pageContent.ts +42 -0
- package/src/seo/core/plainDescription.ts +4 -2
- package/src/seo/core/routeProblems.ts +1 -7
- package/src/seo/core/routeTable.ts +103 -0
- package/src/seo/vite/index.ts +2 -0
- package/src/seo/vite/prerender.ts +26 -1
- package/src/seo/vite/routeTable.ts +79 -0
- package/src/server/answerAddresses.ts +92 -0
- package/src/server/cardMeta.ts +88 -0
- package/src/server/config.ts +125 -0
- package/src/server/envNumber.ts +65 -0
- package/src/server/healthRoute.ts +42 -0
- package/src/server/listenSite.ts +90 -0
- package/src/server/mcpServer.ts +14 -0
- package/src/server/repositoryVersion.ts +33 -0
- package/src/server/routeOptions.ts +26 -0
- package/src/server/routeTable.ts +35 -0
- package/src/server/siteView.ts +42 -0
- package/src/server/spaPages.ts +179 -0
- package/src/server/spaSite.ts +216 -0
- package/src/server/spaSiteOptions.ts +133 -0
- package/src/server/staticSite.ts +65 -35
- package/src/server/toolSiteServer.ts +127 -0
- package/src/server/trustProxy.ts +32 -0
- package/src/server/types.ts +25 -0
- package/src/server.ts +40 -0
- package/src/share/core/config.ts +45 -2
- package/src/share/core/index.ts +4 -0
- package/src/share/core/keySetParam.ts +92 -0
- package/src/share/core/vocabulary.ts +8 -0
- package/src/shell/ui/ShareControl.tsx +150 -0
- package/src/shell/ui/ShellFrame.tsx +180 -0
- package/src/shell/ui/SiteShell.tsx +297 -0
- package/src/shell/ui/index.ts +9 -0
- package/src/state/core/index.ts +1 -0
- package/src/state/core/legacyEntries.ts +76 -0
- package/src/state/core/persistBucket.ts +50 -10
- package/src/state/core/persistSignalBucket.ts +52 -0
- package/src/state/core/storageEntry.ts +32 -0
- package/src/structure/ui/StructureExportButton.tsx +57 -0
- package/src/structure/ui/index.ts +4 -0
- package/src/structure/ui/useStructureDraft.ts +47 -0
- package/src/ui.ts +2 -0
- package/src/worker/core/index.ts +1 -0
- package/src/worker/core/messages.ts +4 -3
- package/src/worker/core/oclResourcesUrl.ts +21 -0
- package/src/worker/core/serveWorkerRequests.ts +30 -2
- package/src/worker/core/workerChannel.ts +74 -74
- package/src/worker/core/workerChannelParts.ts +33 -13
- package/src/worker/core/workerChannelTypes.ts +47 -2
- package/src/worker/core/workerSlot.ts +181 -0
- package/styles/card.css +145 -0
- package/styles/chrome.css +248 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a click on a value of a property table copies.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** What a cell shows when there is no value for it. */
|
|
6
|
+
export const NOT_AVAILABLE = '—';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The text a reader pastes for a value the page shows, or `null` when there is
|
|
10
|
+
* nothing to take: a value the data does not hold, or one drawn from elements
|
|
11
|
+
* rather than written as text, which names its own copy text instead.
|
|
12
|
+
* @param value - What is on screen.
|
|
13
|
+
* @returns The clipboard text, or null.
|
|
14
|
+
*/
|
|
15
|
+
export function copyableText(value: unknown): string | null {
|
|
16
|
+
if (typeof value === 'number') return String(value);
|
|
17
|
+
if (typeof value !== 'string') return null;
|
|
18
|
+
const text = value.trim();
|
|
19
|
+
return text === '' || text === NOT_AVAILABLE ? null : text;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NOT_AVAILABLE, copyableText } from './copyableText.ts';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { ClickToCopy } from '../../clipboard/ui/ClickToCopy.tsx';
|
|
4
|
+
import { joinClassNames } from '../../shared/ui/joinClassNames.ts';
|
|
5
|
+
import { copyableText } from '../core/copyableText.ts';
|
|
6
|
+
|
|
7
|
+
/** One row of a {@link PropertyTable}. */
|
|
8
|
+
export interface PropertyRow {
|
|
9
|
+
/** What the row is called. */
|
|
10
|
+
label: string;
|
|
11
|
+
/** The value, already formatted: text, a number, or a drawn element. */
|
|
12
|
+
value: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* What the number means, when the name alone does not say.
|
|
15
|
+
* @default undefined
|
|
16
|
+
*/
|
|
17
|
+
note?: string;
|
|
18
|
+
/**
|
|
19
|
+
* What a click on the value copies, when the value is drawn rather than
|
|
20
|
+
* written: a formula drawn by `<MF>` copies its plain string.
|
|
21
|
+
* @default the value itself when it is text or a number, nothing otherwise
|
|
22
|
+
*/
|
|
23
|
+
copy?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** What {@link PropertyTable} needs. */
|
|
27
|
+
export interface PropertyTableProps {
|
|
28
|
+
/**
|
|
29
|
+
* The heading over the group.
|
|
30
|
+
* @default undefined — no heading
|
|
31
|
+
*/
|
|
32
|
+
title?: string;
|
|
33
|
+
/** The rows, in the order they are read. */
|
|
34
|
+
rows: readonly PropertyRow[];
|
|
35
|
+
/**
|
|
36
|
+
* Class the group carries, in addition to `properties`.
|
|
37
|
+
* @default undefined
|
|
38
|
+
*/
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* One group of properties as a two-column table, each value its own copy
|
|
44
|
+
* target: a mass, a formula or an identifier is taken away with one click, and
|
|
45
|
+
* a row with no value is drawn as a plain cell.
|
|
46
|
+
* @param props - The heading and the rows.
|
|
47
|
+
* @returns The group.
|
|
48
|
+
*/
|
|
49
|
+
export function PropertyTable(props: PropertyTableProps): ReactElement {
|
|
50
|
+
const { title, rows, className } = props;
|
|
51
|
+
return (
|
|
52
|
+
<section className={joinClassNames('properties', className)}>
|
|
53
|
+
{title === undefined ? null : (
|
|
54
|
+
<h3 className="properties__title">{title}</h3>
|
|
55
|
+
)}
|
|
56
|
+
<table className="properties__table">
|
|
57
|
+
<tbody>
|
|
58
|
+
{rows.map((row) => {
|
|
59
|
+
const copy = row.copy ?? copyableText(row.value);
|
|
60
|
+
return (
|
|
61
|
+
<tr key={row.label}>
|
|
62
|
+
<th scope="row">
|
|
63
|
+
{row.label}
|
|
64
|
+
{row.note === undefined ? null : (
|
|
65
|
+
<span className="properties__note">{row.note}</span>
|
|
66
|
+
)}
|
|
67
|
+
</th>
|
|
68
|
+
<ClickToCopy
|
|
69
|
+
as="td"
|
|
70
|
+
value={copy ?? ''}
|
|
71
|
+
label={row.label}
|
|
72
|
+
disabled={copy === null}
|
|
73
|
+
>
|
|
74
|
+
{row.value}
|
|
75
|
+
</ClickToCopy>
|
|
76
|
+
</tr>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</tbody>
|
|
80
|
+
</table>
|
|
81
|
+
</section>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
* script can import a module that uses it.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { Language } from '../../i18n/core/languages.ts';
|
|
11
12
|
import { EMBED_PARAM, HIDE_PARAM } from '../../share/core/config.ts';
|
|
12
13
|
|
|
14
|
+
import { stripBasePath } from './basePath.ts';
|
|
13
15
|
import { pageHistory, pageLocation } from './pageAddress.ts';
|
|
14
16
|
import type { QueryEntry } from './query.ts';
|
|
15
17
|
import { formatQueryEntries } from './query.ts';
|
|
@@ -26,7 +28,10 @@ export const ROUTE_CHANGE_EVENT = 'cheminfo:routechange';
|
|
|
26
28
|
*
|
|
27
29
|
* A link written before the site routed by path — `/#/tutorial/3` — is replaced
|
|
28
30
|
* in place, once, by the address the router writes for it, when the router
|
|
29
|
-
* adopts such links.
|
|
31
|
+
* adopts such links. So is a `?lang=` a sibling site handed the language over
|
|
32
|
+
* in, on a router given `languages`: the language moves into the path, so one
|
|
33
|
+
* reader's bookmark and the next one's are the same address. The language of a
|
|
34
|
+
* prefixed address never changes: `/fr/tutorial?lang=de` stays French.
|
|
30
35
|
* @param router - The site's router.
|
|
31
36
|
* @returns The route of the address on screen, or of `/` where there is no browser.
|
|
32
37
|
*/
|
|
@@ -34,7 +39,8 @@ export function readRoute<Tab extends string>(
|
|
|
34
39
|
router: TabRouter<Tab>,
|
|
35
40
|
): TabRoute<Tab> {
|
|
36
41
|
const address = currentAddress();
|
|
37
|
-
const
|
|
42
|
+
const legacy = router.legacyAddress(address);
|
|
43
|
+
const adopted = router.languageAddress?.(legacy ?? address) ?? legacy;
|
|
38
44
|
if (adopted === null) return router.parse(address);
|
|
39
45
|
const history = pageHistory();
|
|
40
46
|
history?.replaceState(history.state, '', adopted);
|
|
@@ -42,6 +48,39 @@ export function readRoute<Tab extends string>(
|
|
|
42
48
|
return router.parse(adopted);
|
|
43
49
|
}
|
|
44
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Read the route the site opens on, the reader's own language applied to a
|
|
53
|
+
* bare root.
|
|
54
|
+
*
|
|
55
|
+
* A bare `/` — no page, no query, no fragment — names no language, so the one
|
|
56
|
+
* the reader last chose may decide which front page opens, and the address is
|
|
57
|
+
* rewritten in place to say it. Nothing else is steered: a deep link opens what
|
|
58
|
+
* it names for everybody, so `/tutorial` handed out in a course is English and
|
|
59
|
+
* `/fr/tutorial` French, whatever either reader last read.
|
|
60
|
+
* @param router - The site's router, given `languages`.
|
|
61
|
+
* @param preferred - The language the reader last chose; `undefined`, or one
|
|
62
|
+
* the router does not write, steers nothing.
|
|
63
|
+
* @returns The route to open on.
|
|
64
|
+
*/
|
|
65
|
+
export function openingRoute<Tab extends string>(
|
|
66
|
+
router: TabRouter<Tab>,
|
|
67
|
+
preferred: Language | undefined,
|
|
68
|
+
): TabRoute<Tab> {
|
|
69
|
+
const bare = isBareRoot(router);
|
|
70
|
+
const route = readRoute(router);
|
|
71
|
+
const steered =
|
|
72
|
+
bare &&
|
|
73
|
+
preferred !== undefined &&
|
|
74
|
+
preferred !== route.language &&
|
|
75
|
+
router.languages?.includes(preferred) === true;
|
|
76
|
+
if (!steered) return route;
|
|
77
|
+
const address = router.format({ ...route, language: preferred });
|
|
78
|
+
const history = pageHistory();
|
|
79
|
+
history?.replaceState(history.state, '', address);
|
|
80
|
+
globalThis.dispatchEvent?.(new Event(ROUTE_CHANGE_EVENT));
|
|
81
|
+
return router.parse(address);
|
|
82
|
+
}
|
|
83
|
+
|
|
45
84
|
/** How {@link writeRoute} records a move. */
|
|
46
85
|
export interface WriteRouteOptions {
|
|
47
86
|
/**
|
|
@@ -66,8 +105,10 @@ export interface WriteRouteOptions {
|
|
|
66
105
|
* The share parameters of the address on screen, and the preference names in
|
|
67
106
|
* `keep`, survive the move, so an embedded page stays embedded after its first
|
|
68
107
|
* click. A parameter the route names itself — even as `null` or `undefined`, to
|
|
69
|
-
* remove it — is the route's.
|
|
70
|
-
*
|
|
108
|
+
* remove it — is the route's. On a router given `languages`, a route naming no
|
|
109
|
+
* language keeps the one on screen, and changing language counts as changing
|
|
110
|
+
* tab. Writing the address already on screen does nothing, so echoing state
|
|
111
|
+
* back into the address cannot loop.
|
|
71
112
|
* @param router - The site's router.
|
|
72
113
|
* @param route - Where to go.
|
|
73
114
|
* @param options - How the move is recorded and which parameters survive it.
|
|
@@ -91,7 +132,9 @@ export function writeRoute<Tab extends string>(
|
|
|
91
132
|
if (shown === address) return address;
|
|
92
133
|
|
|
93
134
|
const mode = options.history ?? 'auto';
|
|
94
|
-
const
|
|
135
|
+
const from = router.parse(current);
|
|
136
|
+
const to = router.parse(address);
|
|
137
|
+
const sameTab = from.tab === to.tab && from.language === to.language;
|
|
95
138
|
if (mode === 'replace' || (mode === 'auto' && sameTab)) {
|
|
96
139
|
history.replaceState(history.state, '', address);
|
|
97
140
|
} else {
|
|
@@ -139,9 +182,13 @@ function withKeptParams<Tab extends string>(
|
|
|
139
182
|
current: string,
|
|
140
183
|
keep: readonly string[],
|
|
141
184
|
): string {
|
|
142
|
-
const
|
|
185
|
+
const onScreen = router.parse(current);
|
|
186
|
+
const language = route.language ?? onScreen.language;
|
|
187
|
+
const target = router.format(
|
|
188
|
+
language === undefined ? route : { ...route, language },
|
|
189
|
+
);
|
|
143
190
|
const named = route.params ?? {};
|
|
144
|
-
const shown =
|
|
191
|
+
const shown = onScreen.params;
|
|
145
192
|
const kept: QueryEntry[] = [];
|
|
146
193
|
for (const key of new Set([EMBED_PARAM, HIDE_PARAM, ...keep])) {
|
|
147
194
|
if (Object.hasOwn(named, key)) continue;
|
|
@@ -152,3 +199,10 @@ function withKeptParams<Tab extends string>(
|
|
|
152
199
|
const separator = target.includes('?') ? '&' : '?';
|
|
153
200
|
return `${target}${separator}${formatQueryEntries(kept)}`;
|
|
154
201
|
}
|
|
202
|
+
|
|
203
|
+
function isBareRoot<Tab extends string>(router: TabRouter<Tab>): boolean {
|
|
204
|
+
const location = pageLocation();
|
|
205
|
+
if (location === undefined) return false;
|
|
206
|
+
if (location.search !== '' || location.hash !== '') return false;
|
|
207
|
+
return stripBasePath(router.basePath ?? '', location.pathname) === '/';
|
|
208
|
+
}
|
package/src/router/core/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
export type { WriteRouteOptions } from './history.ts';
|
|
10
10
|
export {
|
|
11
11
|
ROUTE_CHANGE_EVENT,
|
|
12
|
+
openingRoute,
|
|
12
13
|
readRoute,
|
|
13
14
|
subscribeToRoute,
|
|
14
15
|
writeRoute,
|
|
@@ -35,12 +36,12 @@ export {
|
|
|
35
36
|
parseQueryString,
|
|
36
37
|
} from './query.ts';
|
|
37
38
|
export type { SiteAddresses, SiteAddressesOptions } from './siteAddresses.ts';
|
|
38
|
-
export { createSiteAddresses } from './siteAddresses.ts';
|
|
39
|
+
export { anchorHref, createSiteAddresses } from './siteAddresses.ts';
|
|
39
40
|
export type {
|
|
40
41
|
TabDefinition,
|
|
41
42
|
TabRoute,
|
|
42
43
|
TabRouteInput,
|
|
43
44
|
TabRouter,
|
|
44
45
|
TabRouterOptions,
|
|
45
|
-
} from './
|
|
46
|
+
} from './tabRouterTypes.ts';
|
|
46
47
|
export { createTabRouter } from './tabRouter.ts';
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The language half of a translated site's routes: the prefix a page is
|
|
3
|
+
* written under, and the `?lang=` a sibling site hands the language over in.
|
|
4
|
+
*
|
|
5
|
+
* Inside a translated site the language is the path — `/fr/tutorial` — so each
|
|
6
|
+
* language is an address of its own a crawler indexes and a course hands out.
|
|
7
|
+
* Between sites it travels as a parameter, because the site being linked to
|
|
8
|
+
* may not speak it, and a parameter it does not know is ignored where a prefix
|
|
9
|
+
* it does not have is a 404. So a route reads the parameter only where the
|
|
10
|
+
* prefix says nothing, and the prefix always wins: `/fr/tutorial?lang=de` is
|
|
11
|
+
* the French tutorial for everybody.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Language } from '../../i18n/core/languages.ts';
|
|
15
|
+
import { DEFAULT_LANGUAGE } from '../../i18n/core/languages.ts';
|
|
16
|
+
import { LANGUAGE_PARAM } from '../../language/core/languageParam.ts';
|
|
17
|
+
import {
|
|
18
|
+
readLanguagePath,
|
|
19
|
+
withLanguagePath,
|
|
20
|
+
} from '../../language/core/languagePath.ts';
|
|
21
|
+
|
|
22
|
+
import { splitAddress } from './address.ts';
|
|
23
|
+
import { joinBasePath, stripBasePath } from './basePath.ts';
|
|
24
|
+
import type { QueryEntry, QueryStringOptions } from './query.ts';
|
|
25
|
+
import { formatQueryEntries, parseQueryEntries } from './query.ts';
|
|
26
|
+
|
|
27
|
+
/** The language a route is read in, and what is left of its address. */
|
|
28
|
+
export interface RouteLanguage {
|
|
29
|
+
/** The language the page is read in. */
|
|
30
|
+
language: Language;
|
|
31
|
+
/** The path from the site's own root, the prefix taken off. */
|
|
32
|
+
path: string;
|
|
33
|
+
/** The parameters, without a `lang` that names a language of the site. */
|
|
34
|
+
params: Record<string, string>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Read the language of a route off its path and its parameters.
|
|
39
|
+
* @param path - The path from the site's own root, the mount already off.
|
|
40
|
+
* @param params - The decoded query parameters.
|
|
41
|
+
* @param languages - The languages the site is written in.
|
|
42
|
+
* @returns The language, the path without its prefix, and the parameters.
|
|
43
|
+
*/
|
|
44
|
+
export function readRouteLanguage(
|
|
45
|
+
path: string,
|
|
46
|
+
params: Record<string, string>,
|
|
47
|
+
languages: readonly Language[],
|
|
48
|
+
): RouteLanguage {
|
|
49
|
+
const read = readLanguagePath(path, languages);
|
|
50
|
+
const named = siteLanguage(params[LANGUAGE_PARAM], languages);
|
|
51
|
+
if (named === undefined) return { ...read, params };
|
|
52
|
+
const kept: Record<string, string> = {};
|
|
53
|
+
for (const [key, value] of Object.entries(params)) {
|
|
54
|
+
if (key !== LANGUAGE_PARAM) kept[key] = value;
|
|
55
|
+
}
|
|
56
|
+
const language = read.language === DEFAULT_LANGUAGE ? named : read.language;
|
|
57
|
+
return { language, path: read.path, params: kept };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Write a path from the site's own root under a language's prefix.
|
|
62
|
+
* @param language - The language asked for, if any.
|
|
63
|
+
* @param path - The path from the site's own root.
|
|
64
|
+
* @param languages - The languages the site is written in.
|
|
65
|
+
* @returns The path under the prefix; a language the site does not speak is
|
|
66
|
+
* written as the default one, with no prefix.
|
|
67
|
+
*/
|
|
68
|
+
export function writeRouteLanguage(
|
|
69
|
+
language: Language | undefined,
|
|
70
|
+
path: string,
|
|
71
|
+
languages: readonly Language[],
|
|
72
|
+
): string {
|
|
73
|
+
const written =
|
|
74
|
+
language !== undefined && languages.includes(language)
|
|
75
|
+
? language
|
|
76
|
+
: DEFAULT_LANGUAGE;
|
|
77
|
+
return withLanguagePath(written, path);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** How {@link adoptLanguageParam} reads an address. */
|
|
81
|
+
export interface AdoptLanguageOptions {
|
|
82
|
+
/** The mount path, normalised. */
|
|
83
|
+
basePath: string;
|
|
84
|
+
/** The languages the site is written in. */
|
|
85
|
+
languages: readonly Language[];
|
|
86
|
+
/** How the query string is read and written back. */
|
|
87
|
+
queryOptions: QueryStringOptions;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The address to put in place of one carrying a `?lang=` the site speaks.
|
|
92
|
+
*
|
|
93
|
+
* Only the language moves: the page named stays the page written, whether the
|
|
94
|
+
* router knows it or not, and every other parameter and the fragment are kept.
|
|
95
|
+
* @param address - A browser address: mount, prefix, page, query and fragment.
|
|
96
|
+
* @param options - The mount, the languages and how the query is read.
|
|
97
|
+
* @returns The address with the language in its path, or `null` when the
|
|
98
|
+
* address names no language of the site in its query.
|
|
99
|
+
*/
|
|
100
|
+
export function adoptLanguageParam(
|
|
101
|
+
address: string,
|
|
102
|
+
options: AdoptLanguageOptions,
|
|
103
|
+
): string | null {
|
|
104
|
+
const { basePath, languages, queryOptions } = options;
|
|
105
|
+
const { path, search, fragment } = splitAddress(address);
|
|
106
|
+
const entries = parseQueryEntries(search, queryOptions);
|
|
107
|
+
let named: Language | undefined;
|
|
108
|
+
const kept: QueryEntry[] = [];
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
const language =
|
|
111
|
+
entry[0] === LANGUAGE_PARAM
|
|
112
|
+
? siteLanguage(entry[1], languages)
|
|
113
|
+
: undefined;
|
|
114
|
+
if (language === undefined) kept.push(entry);
|
|
115
|
+
else named ??= language;
|
|
116
|
+
}
|
|
117
|
+
if (named === undefined) return null;
|
|
118
|
+
|
|
119
|
+
const read = readLanguagePath(stripBasePath(basePath, path), languages);
|
|
120
|
+
const language = read.language === DEFAULT_LANGUAGE ? named : read.language;
|
|
121
|
+
const opened = joinBasePath(basePath, withLanguagePath(language, read.path));
|
|
122
|
+
const query = formatQueryEntries(kept);
|
|
123
|
+
const withQuery = query === '' ? opened : `${opened}?${query}`;
|
|
124
|
+
return fragment === '' ? withQuery : `${withQuery}#${fragment}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function siteLanguage(
|
|
128
|
+
value: string | undefined,
|
|
129
|
+
languages: readonly Language[],
|
|
130
|
+
): Language | undefined {
|
|
131
|
+
if (value === undefined) return undefined;
|
|
132
|
+
for (const language of languages) {
|
|
133
|
+
if (language === value) return language;
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
@@ -52,6 +52,11 @@ export function createSiteAddresses(
|
|
|
52
52
|
return environment || ownUrl;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function storedAssetSrc(url: string): string {
|
|
56
|
+
if (OWN_ORIGIN.test(url) || url.startsWith('//')) return url;
|
|
57
|
+
return url.startsWith('/') ? withBase(url) : url;
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
return {
|
|
56
61
|
basePath,
|
|
57
62
|
siteName: siteDisplayName(site),
|
|
@@ -60,9 +65,31 @@ export function createSiteAddresses(
|
|
|
60
65
|
pathWithoutBase,
|
|
61
66
|
absoluteUrl,
|
|
62
67
|
configuredSiteUrl,
|
|
68
|
+
anchorHref,
|
|
69
|
+
storedAssetSrc,
|
|
63
70
|
};
|
|
64
71
|
}
|
|
65
72
|
|
|
73
|
+
/**
|
|
74
|
+
* A link to an anchor on the page being read.
|
|
75
|
+
*
|
|
76
|
+
* Every page of ours carries a `<base>`, so a bare `#id` resolves against the
|
|
77
|
+
* mount rather than against the address open, and clicking it leaves the page
|
|
78
|
+
* instead of scrolling down it. The link names the page's own address and its
|
|
79
|
+
* query instead — the browser's, since that is the document a click scrolls.
|
|
80
|
+
* @param id - The `id` of the element to jump to.
|
|
81
|
+
* @returns The address of that anchor on the page on screen, or `#id` where
|
|
82
|
+
* there is no page.
|
|
83
|
+
*/
|
|
84
|
+
export function anchorHref(id: string): string {
|
|
85
|
+
const location = globalThis.location as Location | undefined;
|
|
86
|
+
if (location === undefined) return `#${id}`;
|
|
87
|
+
return `${location.pathname}${location.search}#${id}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// A scheme names its own origin: `https:`, `data:`, `blob:`.
|
|
91
|
+
const OWN_ORIGIN = /^[a-z][\w+.-]*:/i;
|
|
92
|
+
|
|
66
93
|
/** How {@link createSiteAddresses} reads the mount. */
|
|
67
94
|
export interface SiteAddressesOptions {
|
|
68
95
|
/**
|
|
@@ -95,4 +122,15 @@ export interface SiteAddresses {
|
|
|
95
122
|
* it says something, the site's own address otherwise.
|
|
96
123
|
*/
|
|
97
124
|
configuredSiteUrl: () => string;
|
|
125
|
+
/** A link to an anchor on the page on screen; see {@link anchorHref}. */
|
|
126
|
+
anchorHref: (id: string) => string;
|
|
127
|
+
/**
|
|
128
|
+
* The address of something a backend stored and the page shows — an
|
|
129
|
+
* uploaded picture — as this deployment serves it. A backend names those
|
|
130
|
+
* from its own root, `/uploads/<name>`, because a proxy mounting the site
|
|
131
|
+
* under a path strips the path before the request reaches it; so a
|
|
132
|
+
* root-relative address is put under the mount, and one carrying its own
|
|
133
|
+
* scheme or origin, or relative already, is handed back untouched.
|
|
134
|
+
*/
|
|
135
|
+
storedAssetSrc: (url: string) => string;
|
|
98
136
|
}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import { splitAddress, splitPath, trimTrailingSlash } from './address.ts';
|
|
2
2
|
import { joinBasePath, normalizeBasePath, stripBasePath } from './basePath.ts';
|
|
3
|
+
import {
|
|
4
|
+
adoptLanguageParam,
|
|
5
|
+
readRouteLanguage,
|
|
6
|
+
writeRouteLanguage,
|
|
7
|
+
} from './languageRoute.ts';
|
|
3
8
|
import { adoptLegacyHashAddress, pathFromLegacyHash } from './legacyHash.ts';
|
|
4
9
|
import type { QueryStringOptions } from './query.ts';
|
|
5
10
|
import { formatQueryString, parseQueryString } from './query.ts';
|
|
11
|
+
import type {
|
|
12
|
+
TabRoute,
|
|
13
|
+
TabRouteInput,
|
|
14
|
+
TabRouter,
|
|
15
|
+
TabRouterOptions,
|
|
16
|
+
} from './tabRouterTypes.ts';
|
|
17
|
+
|
|
18
|
+
export type {
|
|
19
|
+
TabDefinition,
|
|
20
|
+
TabRoute,
|
|
21
|
+
TabRouteInput,
|
|
22
|
+
TabRouter,
|
|
23
|
+
TabRouterOptions,
|
|
24
|
+
} from './tabRouterTypes.ts';
|
|
6
25
|
|
|
7
26
|
/**
|
|
8
27
|
* The two directions between an address and the page it names.
|
|
@@ -20,6 +39,7 @@ export function createTabRouter<Tab extends string>(
|
|
|
20
39
|
const mode = options.mode ?? 'path';
|
|
21
40
|
const basePath = normalizeBasePath(options.basePath ?? '');
|
|
22
41
|
const adoptLegacyHash = options.adoptLegacyHash ?? false;
|
|
42
|
+
const siteLanguages = options.languages;
|
|
23
43
|
const queryOptions: QueryStringOptions = {
|
|
24
44
|
literalPlus: options.literalPlus ?? true,
|
|
25
45
|
keepEmptyValues: options.keepEmptyValues ?? false,
|
|
@@ -50,8 +70,17 @@ export function createTabRouter<Tab extends string>(
|
|
|
50
70
|
|
|
51
71
|
function parse(address: string): TabRoute<Tab> {
|
|
52
72
|
const parts = readAddress(address, mode, basePath, adoptLegacyHash);
|
|
53
|
-
const
|
|
54
|
-
|
|
73
|
+
const query = parseQueryString(parts.search, queryOptions);
|
|
74
|
+
if (siteLanguages === undefined) return routeOf(parts.path, query);
|
|
75
|
+
const read = readRouteLanguage(parts.path, query, siteLanguages);
|
|
76
|
+
return { ...routeOf(read.path, read.params), language: read.language };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function routeOf(
|
|
80
|
+
path: string,
|
|
81
|
+
params: Record<string, string>,
|
|
82
|
+
): TabRoute<Tab> {
|
|
83
|
+
const segments = splitPath(path);
|
|
55
84
|
const first = segments[0];
|
|
56
85
|
const tab = first === undefined ? undefined : tabBySegment.get(first);
|
|
57
86
|
if (tab === undefined) return { tab: options.home, id: null, params };
|
|
@@ -65,8 +94,12 @@ export function createTabRouter<Tab extends string>(
|
|
|
65
94
|
const definition = definitions.get(tab);
|
|
66
95
|
const base = tab === options.home ? '/' : (definition?.path ?? '/');
|
|
67
96
|
const id = definition?.takesId === true ? (route.id ?? null) : null;
|
|
68
|
-
const
|
|
97
|
+
const page =
|
|
69
98
|
id === null || base === '/' ? base : `${base}/${encodeURIComponent(id)}`;
|
|
99
|
+
const path =
|
|
100
|
+
siteLanguages === undefined
|
|
101
|
+
? page
|
|
102
|
+
: writeRouteLanguage(route.language, page, siteLanguages);
|
|
70
103
|
const search = formatQueryString(route.params ?? {}, queryOptions);
|
|
71
104
|
const address = mode === 'hash' ? `#${path}` : joinBasePath(basePath, path);
|
|
72
105
|
return search === '' ? address : `${address}?${search}`;
|
|
@@ -77,125 +110,34 @@ export function createTabRouter<Tab extends string>(
|
|
|
77
110
|
const adopted = adoptLegacyHashAddress(address, { basePath });
|
|
78
111
|
if (adopted === null) return null;
|
|
79
112
|
const route = parse(adopted);
|
|
80
|
-
const path = format({
|
|
113
|
+
const path = format({
|
|
114
|
+
tab: route.tab,
|
|
115
|
+
id: route.id,
|
|
116
|
+
language: route.language,
|
|
117
|
+
});
|
|
81
118
|
const { search } = splitAddress(adopted);
|
|
82
119
|
return search === '' ? path : `${path}?${search}`;
|
|
83
120
|
}
|
|
84
121
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* The address of the tab, from the site's own root. The home tab is always
|
|
94
|
-
* written as `/`, whatever it declares here, so the site has one address for
|
|
95
|
-
* it instead of two holding the same thing.
|
|
96
|
-
* @default `/${id}`
|
|
97
|
-
*/
|
|
98
|
-
path?: string;
|
|
99
|
-
/**
|
|
100
|
-
* Whether the tab addresses one of its items in a second path segment — a
|
|
101
|
-
* tutorial step, an exercise, an element — so a lecturer can hand out a deep
|
|
102
|
-
* link and a crawler indexes each item as a page of its own.
|
|
103
|
-
* @default false
|
|
104
|
-
*/
|
|
105
|
-
takesId?: boolean;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** How the addresses of a site's tabs are read and written. */
|
|
109
|
-
export interface TabRouterOptions<Tab extends string> {
|
|
110
|
-
/** Every tab of the site, named on its own or described in full. */
|
|
111
|
-
tabs: ReadonlyArray<Tab | TabDefinition<Tab>>;
|
|
112
|
-
/**
|
|
113
|
-
* The tab living at the root, and the one an address the site does not know
|
|
114
|
-
* opens — a link written before a rename still lands somewhere.
|
|
115
|
-
*/
|
|
116
|
-
home: Tab;
|
|
117
|
-
/**
|
|
118
|
-
* Whether the address is the path or the fragment. A public tool must use
|
|
119
|
-
* `'path'`: a `#` is dropped by half the tools that pass links around, the
|
|
120
|
-
* server never sees it, and a crawler indexes the whole site as one page.
|
|
121
|
-
* `'hash'` exists only so a site already routing that way can adopt this
|
|
122
|
-
* router before it moves.
|
|
123
|
-
* @default 'path'
|
|
124
|
-
*/
|
|
125
|
-
mode?: 'path' | 'hash';
|
|
126
|
-
/**
|
|
127
|
-
* The path the site is served under: nothing on a host of its own, `/surge`
|
|
128
|
-
* as one tool among several on a shared one.
|
|
129
|
-
* @default ''
|
|
130
|
-
*/
|
|
131
|
-
basePath?: string;
|
|
132
|
-
/**
|
|
133
|
-
* Read a `+` in a value as the character it is rather than as a space.
|
|
134
|
-
* Without it a shared SMILES breaks.
|
|
135
|
-
* @default true
|
|
136
|
-
*/
|
|
137
|
-
literalPlus?: boolean;
|
|
138
|
-
/**
|
|
139
|
-
* Write a parameter carrying nothing back as the bare key, so a hand-typed
|
|
140
|
-
* `?embed` survives the round trip.
|
|
141
|
-
* @default false
|
|
142
|
-
*/
|
|
143
|
-
keepEmptyValues?: boolean;
|
|
144
|
-
/**
|
|
145
|
-
* Also read an address whose page is named by an old `#/tab/item` fragment,
|
|
146
|
-
* so links handed out before the site routed by path keep working.
|
|
147
|
-
* @default false
|
|
148
|
-
*/
|
|
149
|
-
adoptLegacyHash?: boolean;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Where the app is: which tab, what it has open, and how it is set up. */
|
|
153
|
-
export interface TabRoute<Tab extends string = string> {
|
|
154
|
-
/** The tab the address opens. */
|
|
155
|
-
tab: Tab;
|
|
156
|
-
/** The item its second segment names, `null` on a tab that takes none. */
|
|
157
|
-
id: string | null;
|
|
158
|
-
/** Decoded query parameters, the tool's own and the share configuration's. */
|
|
159
|
-
params: Record<string, string>;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** A route as a caller writes it, the parts it does not carry left out. */
|
|
163
|
-
export interface TabRouteInput<Tab extends string = string> {
|
|
164
|
-
/** The tab to open; one the router does not know falls back to the home tab. */
|
|
165
|
-
tab: Tab;
|
|
166
|
-
/**
|
|
167
|
-
* The item the tab has open, ignored by a tab that addresses none.
|
|
168
|
-
* @default null
|
|
169
|
-
*/
|
|
170
|
-
id?: string | null;
|
|
171
|
-
/**
|
|
172
|
-
* Query parameters to carry; an empty, `undefined` or `null` value is left out.
|
|
173
|
-
* @default {}
|
|
174
|
-
*/
|
|
175
|
-
params?: Record<string, string | undefined | null>;
|
|
176
|
-
}
|
|
122
|
+
function languageAddress(address: string): string | null {
|
|
123
|
+
if (mode !== 'path' || siteLanguages === undefined) return null;
|
|
124
|
+
return adoptLanguageParam(address, {
|
|
125
|
+
basePath,
|
|
126
|
+
languages: siteLanguages,
|
|
127
|
+
queryOptions,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
177
130
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
/** The address a route is reachable at, mount path and query included. */
|
|
189
|
-
format: (route: TabRouteInput<Tab>) => string;
|
|
190
|
-
/** Whether a string read out of an address names one of the site's tabs. */
|
|
191
|
-
isTab: (value: string) => value is Tab;
|
|
192
|
-
/**
|
|
193
|
-
* The address to put in the bar in place of a link written before the site
|
|
194
|
-
* routed by path: the page it names as this router writes it, with the query
|
|
195
|
-
* string kept as it was. `null` when the address is no such link, or when the
|
|
196
|
-
* router does not adopt them.
|
|
197
|
-
*/
|
|
198
|
-
legacyAddress: (address: string) => string | null;
|
|
131
|
+
return {
|
|
132
|
+
mode,
|
|
133
|
+
parse,
|
|
134
|
+
format,
|
|
135
|
+
isTab,
|
|
136
|
+
legacyAddress,
|
|
137
|
+
languageAddress,
|
|
138
|
+
basePath,
|
|
139
|
+
languages: siteLanguages,
|
|
140
|
+
};
|
|
199
141
|
}
|
|
200
142
|
|
|
201
143
|
interface NormalizedTab {
|