react-cheminfo 0.51.0 → 0.53.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 +135 -46
- package/lib/host/core/connectHost.d.ts +75 -0
- package/lib/host/core/connectHost.d.ts.map +1 -0
- package/lib/host/core/connectHost.js +171 -0
- package/lib/host/core/connectHost.js.map +1 -0
- package/lib/host/core/hostStructure.d.ts +52 -0
- package/lib/host/core/hostStructure.d.ts.map +1 -0
- package/lib/host/core/hostStructure.js +106 -0
- package/lib/host/core/hostStructure.js.map +1 -0
- package/lib/host/core/index.d.ts +9 -0
- package/lib/host/core/index.d.ts.map +1 -0
- package/lib/host/core/index.js +5 -0
- package/lib/host/core/index.js.map +1 -0
- package/lib/host/core/kinds.d.ts +73 -0
- package/lib/host/core/kinds.d.ts.map +1 -0
- package/lib/host/core/kinds.js +88 -0
- package/lib/host/core/kinds.js.map +1 -0
- package/lib/host/core/protocol.d.ts +134 -0
- package/lib/host/core/protocol.d.ts.map +1 -0
- package/lib/host/core/protocol.js +92 -0
- package/lib/host/core/protocol.js.map +1 -0
- package/lib/host/testing/sciPeaks.d.ts +21 -0
- package/lib/host/testing/sciPeaks.d.ts.map +1 -0
- package/lib/host/testing/sciPeaks.js +62 -0
- package/lib/host/testing/sciPeaks.js.map +1 -0
- package/lib/host/testing/standInHost.d.ts +47 -0
- package/lib/host/testing/standInHost.d.ts.map +1 -0
- package/lib/host/testing/standInHost.js +85 -0
- package/lib/host/testing/standInHost.js.map +1 -0
- package/lib/host/ui/index.d.ts +3 -0
- package/lib/host/ui/index.d.ts.map +1 -0
- package/lib/host/ui/index.js +2 -0
- package/lib/host/ui/index.js.map +1 -0
- package/lib/host/ui/useHostConnection.d.ts +36 -0
- package/lib/host/ui/useHostConnection.d.ts.map +1 -0
- package/lib/host/ui/useHostConnection.js +62 -0
- package/lib/host/ui/useHostConnection.js.map +1 -0
- package/lib/host-testing.d.ts +8 -0
- package/lib/host-testing.d.ts.map +1 -0
- package/lib/host-testing.js +7 -0
- package/lib/host-testing.js.map +1 -0
- package/lib/host.d.ts +11 -0
- package/lib/host.d.ts.map +1 -0
- package/lib/host.js +11 -0
- package/lib/host.js.map +1 -0
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- 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/package.json +4 -1
- package/src/host/core/connectHost.ts +240 -0
- package/src/host/core/hostStructure.ts +129 -0
- package/src/host/core/index.ts +46 -0
- package/src/host/core/kinds.ts +128 -0
- package/src/host/core/protocol.ts +197 -0
- package/src/host/testing/sciPeaks.ts +66 -0
- package/src/host/testing/standInHost.ts +116 -0
- package/src/host/ui/index.ts +2 -0
- package/src/host/ui/useHostConnection.ts +85 -0
- package/src/host-testing.ts +18 -0
- package/src/host.ts +11 -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/README.md
CHANGED
|
@@ -30,22 +30,24 @@ would mean two Blueprint style trees in one page.
|
|
|
30
30
|
Subpaths are **bundle boundaries, not taxonomy**: a feature gets its own door
|
|
31
31
|
only when it drags a heavy dependency behind it.
|
|
32
32
|
|
|
33
|
-
| Import | Holds
|
|
34
|
-
| ---------------------------------- |
|
|
35
|
-
| `react-cheminfo/core` | every framework-free helper — 140 value exports
|
|
36
|
-
| `react-cheminfo/ui` | every React component and hook — 60 value exports
|
|
37
|
-
| `react-cheminfo/vite` | the prerender plugin and the OG card
|
|
38
|
-
| `react-cheminfo/pages` | the Cloudflare Pages analytics middleware
|
|
39
|
-
| `react-cheminfo/orbital` | the 3D atomic-orbital viewer
|
|
40
|
-
| `react-cheminfo/molecule3d` | the 3D molecule viewer and its toolbar
|
|
41
|
-
| `react-cheminfo/structure` | the structure editor and renderer
|
|
42
|
-
| `react-cheminfo/conformers` | conformer generation, ranking and refinement
|
|
43
|
-
| `react-cheminfo/slides` | the deck format and the slideshow player
|
|
44
|
-
| `react-cheminfo/spectra` | the spectra processing settings editors
|
|
45
|
-
| `react-cheminfo/ir` | the infrared chart, band table and editor
|
|
46
|
-
| `react-cheminfo/xtb` | GFN2-xTB as a geometry relaxer
|
|
47
|
-
| `react-cheminfo/
|
|
48
|
-
| `react-cheminfo/
|
|
33
|
+
| Import | Holds | Costs |
|
|
34
|
+
| ---------------------------------- | ----------------------------------------------------- | ------------------------------------------------ |
|
|
35
|
+
| `react-cheminfo/core` | every framework-free helper — 140 value exports | nothing |
|
|
36
|
+
| `react-cheminfo/ui` | every React component and hook — 60 value exports | React |
|
|
37
|
+
| `react-cheminfo/vite` | the prerender plugin and the OG card | nothing; React on the card |
|
|
38
|
+
| `react-cheminfo/pages` | the Cloudflare Pages analytics middleware | nothing |
|
|
39
|
+
| `react-cheminfo/orbital` | the 3D atomic-orbital viewer | React, molstar |
|
|
40
|
+
| `react-cheminfo/molecule3d` | the 3D molecule viewer and its toolbar | React, molstar |
|
|
41
|
+
| `react-cheminfo/structure` | the structure editor and renderer | React, react-ocl, OCL |
|
|
42
|
+
| `react-cheminfo/conformers` | conformer generation, ranking and refinement | OCL |
|
|
43
|
+
| `react-cheminfo/slides` | the deck format and the slideshow player | React, react-markdown |
|
|
44
|
+
| `react-cheminfo/spectra` | the spectra processing settings editors | React; types only from spectra-processor, ml-pca |
|
|
45
|
+
| `react-cheminfo/ir` | the infrared chart, band table and editor | React, ir-spectrum, convert-to-jcamp |
|
|
46
|
+
| `react-cheminfo/xtb` | GFN2-xTB as a geometry relaxer | nothing on import; xtb-wasm on the first call |
|
|
47
|
+
| `react-cheminfo/host` | data handed over by a page that frames the tool | nothing on import; ajv once the page is framed |
|
|
48
|
+
| `react-cheminfo/host-testing` | a stand-in host and SciPeaks' messages, for e2e tests | nothing; Node only |
|
|
49
|
+
| `react-cheminfo/styles/chrome.css` | the shared tokens and site-header stylesheet | nothing |
|
|
50
|
+
| `react-cheminfo/styles/slides.css` | the deck stylesheet, themed on the site's colours | nothing |
|
|
49
51
|
|
|
50
52
|
A backend serving an RIS endpoint, a prerender script writing a sitemap, and
|
|
51
53
|
every unit test of that logic therefore load no React at all — and a worker
|
|
@@ -86,36 +88,37 @@ through a wildcard subpath exactly as `react-science` serves its own.
|
|
|
86
88
|
|
|
87
89
|
## What is in it
|
|
88
90
|
|
|
89
|
-
| Area | `…/core`
|
|
90
|
-
| -------------------------- |
|
|
91
|
-
| **Site identity** | `siteById`, `findSiteByHost`, `siteTokensCss`
|
|
92
|
-
| **Chrome** | —
|
|
93
|
-
| **Languages** | `LANGUAGES`, `DEFAULT_LANGUAGE`, `LANGUAGE_LABELS`, `isLanguage`, `MessageCatalog`, `CHROME_CATALOG`, `setMessageSession`, `loadCatalogs`, `LANGUAGE_PARAM`, `withLanguageParam`
|
|
94
|
-
| **Citation** | `formatCitation`, `formatCitations`, `citationSegments`, `downloadCitation`, `citedReferences`, `doiUrl`
|
|
95
|
-
| **Share & embed** | `parseShareConfig`, `applyShareConfig`, `buildShareUrl`, `buildEmbedCode`, `isHidden`, `visibleShareParts`, `applySharePreset`, `findSharePreset`, the param codecs, `syncPreferencesWithUrl`, `applyPreferencesFromSearch`, `writePreferencesToSearch`
|
|
96
|
-
| **Routing & head** | `createTabRouter`, `readRoute`, `writeRoute`, `subscribeToRoute`, `adoptLegacyHashAddress`, `writeDocumentMeta`
|
|
97
|
-
| **Indexing** | `injectPageMeta`, `pageHeadTags`, `pageDocumentMeta`, `fill`, `PAGE_HEAD_MARKER`, `PAGE_BODY_MARKER`, `robotsTxt`, `sitemapXml`, `noscriptIndex`, `structuredDataScript`, `assertRoutes`, `routeFor`, `homeRoute`
|
|
98
|
-
| **Pedagogy** | `parseGlossaryMarkers`, `localStorageProgressStore`, `progressSummary`, `finishValidation`
|
|
99
|
-
| **Clipboard & files** | `writeToClipboard`, `downloadBlob`, `downloadText`, `sanitizeFileName`, `toDelimited`, `readDelimited`, `downloadFigure`, `figureSvg`, `figurePng`, `figureSize`
|
|
100
|
-
| **Formatting & colour** | `formatInteger`, `formatDecimal`, `formatBytes`, `pluralize`, `readableInk`, `contrastRatio`, `COLOR_SCALES`, `resolveColorScale`, `formatColorScale`, `colorAt`, `swatchAt`, `sampleScale`, `colorScaleGradient`, `rgbToHsv`
|
|
101
|
-
| **Number entry** | `readNumber`, `numberText`, `isPartialNumber`, `stepNumber`, `snapToStep`
|
|
102
|
-
| **Range filter** | `isRangeBounded`, `isRangeDomain`, `rangeHandles`, `movedRange`, `settleHandles`, `sameRange`, `rangeHistogramPath`, `OPEN_RANGE`
|
|
103
|
-
| **Widgets** | `CREDITS`, `credits`
|
|
104
|
-
| **Hooks & state** | `createWorkerChannel`, `persistBucket`, `persistSignalBucket`
|
|
105
|
-
| **Chemistry** | `atomicOrbitalsOf`, `configurationOf`, `classifyMolfile`, `readStructure`, `toMolfileExport`
|
|
106
|
-
| **Conformers** | `generateConformers`, `continueConformers`, `refineConformers`, `conformerShape`, `isSameMinimum`, `rankByEnergy`, `minimiseConformer`, `DEFAULT_CONFORMER_OPTIONS`, `CONFORMER_STRATEGIES` (all `/conformers`); `GeometryRelaxer`, `readRelaxableGeometry`, `centredRmsd`
|
|
107
|
-
| **Spectrum charts** | `chartScale`, `chartAxisScale`, `plotRect`, `zoomDomain`, `zoomSelection`, `labelStackBaselines`, `layoutAnnotationBoxes`, `profilePath`, `stickPath`, `guidePlacement`, `readoutPlacement`, `stackCapacity`, `nextSpectrumColor`, `panelStyles`, `statusBar`
|
|
108
|
-
| **Infrared** | `loadIrSpectra`, `toIrSpectrum`, `pickBands`, `assignBands`, `BAND_ASSIGNMENTS`, `irSpectrumToJcamp`, `IR_MODE_RULES`, `nearestBandAt`, `planBandLabels`, `irReducer` (all `/ir`)
|
|
109
|
-
| **Spectra** | `FILTER_CATALOG`, `filterMenu`, `settingsProblems`, `normalizationFilters`, `addFilter`, `moveFilter`, `setFilterOption`, `principalComponentChoices`, `clampPrincipalComponents`, `EMPTY_SETTINGS` (all `/spectra`)
|
|
110
|
-
| **About** | `resolveAbout`, `aboutProblems`
|
|
111
|
-
| **Which build is running** | `formatBuiltAt`, `shortCommit`, `BuildInfo`
|
|
112
|
-
| **Slideshows** | `parseTalk`, `splitDemoLinks`, `slideActionForKey`, `parseTalkOrigin`, `buildTalkManifest` (all `/slides`)
|
|
113
|
-
| **Token guard** | `findTokenViolations`
|
|
114
|
-
| **Figures** | `chartScale`, `chartAxisScale`, `chartAxisTitle`, `chartShare`, `chartColumnExtent`, `chartBinCounts`, `chartSeriesColor`, `rowMatrix`, `stackedMatrix`, `emptiestCorner`, `placeOverlayCard`, `overlayMetrics`
|
|
115
|
-
| **Projections** | `pcaResult`, `embeddingResult`, `projectionTabs`, `loadingProfiles`, `explainedShares`, `confidenceEllipse`, `projectEllipse`, `pointsInPolygon`, `resolveProjectionGroups`, `resolveProjectionShapes`, `PROJECTION_COPY`
|
|
116
|
-
| **Parallel coordinates** | `parallelAxisOf`, `parallelAxisLayouts`, `parallelIncludedMask`, `parallelKeptCount`, `parallelNearestRow`, `parallelSegmentAt`, `parallelBandAt`, `parallelRangeOf`, `parallelPalette`, `parallelColorSteps`, `paintParallelLines`
|
|
117
|
-
| **Periodic table** | `PERIODIC_ELEMENTS`, `elementBySymbol`, `elementByAtomicNumber`, `cellOf`, `placedElements`, `elementByArrowKey`, `EMPTY_BLOCK`, `categorySwatch`, `CATEGORY_LABELS`
|
|
118
|
-
| **Taxonomy** | `TAXON_RANKS`, `PRINCIPAL_RANKS`, `rankOrder`, `isPrincipalRank`, `isGenusOrBelow`, `isAboveGenus`, `principalLineage`, `lineageFromNodes`, `lineageFromRanks`, `genusOrBelow`, `ncbiTaxonomyUrl`, `splitOrganismName`
|
|
91
|
+
| Area | `…/core` | `…/ui` |
|
|
92
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
93
|
+
| **Site identity** | `siteById`, `findSiteByHost`, `siteTokensCss` | `SiteMark`, `Wordmark`, `SiteTheme`, `SiteTile`, `EcosystemButton`, `EcosystemLinks` |
|
|
94
|
+
| **Chrome** | — | `SiteHeader`, `SiteFooter`, `NavLink`, `NavMenuButton`, `MenuButton`, `AccountButton`, `useCompactHeader` |
|
|
95
|
+
| **Languages** | `LANGUAGES`, `DEFAULT_LANGUAGE`, `LANGUAGE_LABELS`, `isLanguage`, `MessageCatalog`, `CHROME_CATALOG`, `setMessageSession`, `loadCatalogs`, `LANGUAGE_PARAM`, `withLanguageParam` | `useT`, `useChromeT`, `useLanguage`, `LanguageSelect`, `SiteLanguage` |
|
|
96
|
+
| **Citation** | `formatCitation`, `formatCitations`, `citationSegments`, `downloadCitation`, `citedReferences`, `doiUrl` | `CiteButton`, `CitationMenu`, `CitationPreview` |
|
|
97
|
+
| **Share & embed** | `parseShareConfig`, `applyShareConfig`, `buildShareUrl`, `buildEmbedCode`, `isHidden`, `visibleShareParts`, `applySharePreset`, `findSharePreset`, the param codecs, `syncPreferencesWithUrl`, `applyPreferencesFromSearch`, `writePreferencesToSearch`, sealed links: `openSealedAddress`, `sealShareUrl`, `sealQuery`, `unsealQuery` | `ShareDialog`, `ShareButton`, `HiddenPartsProvider`, `PagePart`, `useIsHidden`, `SealedLinkRefused` |
|
|
98
|
+
| **Routing & head** | `createTabRouter`, `readRoute`, `writeRoute`, `subscribeToRoute`, `adoptLegacyHashAddress`, `writeDocumentMeta`, `pageLocation`, `pageHistory` | `useTabRoute` |
|
|
99
|
+
| **Indexing** | `injectPageMeta`, `pageHeadTags`, `pageDocumentMeta`, `fill`, `PAGE_HEAD_MARKER`, `PAGE_BODY_MARKER`, `robotsTxt`, `sitemapXml`, `noscriptIndex`, `structuredDataScript`, `assertRoutes`, `routeFor`, `homeRoute` | `cheminfoPrerender`, `ogCardHtml`, `OG_WIDTH`, `OG_HEIGHT` (all `/vite`) |
|
|
100
|
+
| **Pedagogy** | `parseGlossaryMarkers`, `localStorageProgressStore`, `progressSummary`, `finishValidation` | `GlossaryText`, `SyntaxTooltip`, `HintLadder`, `ExerciseActions`, `ExerciseProgressHeader`, `TutorialStepStrip`, `ReferenceGrid`, `TestCaseList` |
|
|
101
|
+
| **Clipboard & files** | `writeToClipboard`, `downloadBlob`, `downloadText`, `sanitizeFileName`, `toDelimited`, `readDelimited`, `downloadFigure`, `figureSvg`, `figurePng`, `figureSize` | `ClickToCopy`, `CopyButton`, `CopyableValue`, `CodeBlock`, `DelimitedTextDialog`, `FigureDownload` |
|
|
102
|
+
| **Formatting & colour** | `formatInteger`, `formatDecimal`, `formatBytes`, `pluralize`, `readableInk`, `contrastRatio`, `COLOR_SCALES`, `resolveColorScale`, `formatColorScale`, `colorAt`, `swatchAt`, `sampleScale`, `colorScaleGradient`, `rgbToHsv` | `ColorScaleLegend`, `ColorScaleSelect`, `ColorScaleEditor`, `ColorScaleBar` |
|
|
103
|
+
| **Number entry** | `readNumber`, `numberText`, `isPartialNumber`, `stepNumber`, `snapToStep` | `NumberInput` |
|
|
104
|
+
| **Range filter** | `isRangeBounded`, `isRangeDomain`, `rangeHandles`, `movedRange`, `settleHandles`, `sameRange`, `rangeHistogramPath`, `OPEN_RANGE` | `RangeSlider` |
|
|
105
|
+
| **Widgets** | `CREDITS`, `credits` | `ErrorBoundary`, `CollapsibleSection`, `CapsuleFilter`, `HelpTooltip`, `CreditsList` |
|
|
106
|
+
| **Hooks & state** | `createWorkerChannel`, `persistBucket`, `persistSignalBucket` | `useDebouncedValue`, `useContainerSize`, `useListKeyboardNavigation`, `useDisclosure` |
|
|
107
|
+
| **Chemistry** | `atomicOrbitalsOf`, `configurationOf`, `classifyMolfile`, `readStructure`, `toMolfileExport` | `AtomicOrbitalViewer` (`/orbital`), `StructureEditor`, `Structure` (`/structure`) |
|
|
108
|
+
| **Conformers** | `generateConformers`, `continueConformers`, `refineConformers`, `conformerShape`, `isSameMinimum`, `rankByEnergy`, `minimiseConformer`, `DEFAULT_CONFORMER_OPTIONS`, `CONFORMER_STRATEGIES` (all `/conformers`); `GeometryRelaxer`, `readRelaxableGeometry`, `centredRmsd` | — |
|
|
109
|
+
| **Spectrum charts** | `chartScale`, `chartAxisScale`, `plotRect`, `zoomDomain`, `zoomSelection`, `labelStackBaselines`, `layoutAnnotationBoxes`, `profilePath`, `stickPath`, `guidePlacement`, `readoutPlacement`, `stackCapacity`, `nextSpectrumColor`, `panelStyles`, `statusBar` | `Axes`, `AxisGuide`, `ChartTracker`, `ChartStack`, `SelectionRect`, `TraceLegend`, `PlotCaption`, `useChartZoom`, `useChartPointer`, `useChartSize`, `SidePanelStack`, `PanelRail`, `Section`, `FilterInput`, `AboutDialogFrame`, `DocumentationDialogFrame`, `FigureDownload`, `useFigureDownload` |
|
|
110
|
+
| **Infrared** | `loadIrSpectra`, `toIrSpectrum`, `pickBands`, `assignBands`, `BAND_ASSIGNMENTS`, `irSpectrumToJcamp`, `IR_MODE_RULES`, `nearestBandAt`, `planBandLabels`, `irReducer` (all `/ir`) | `IrEditor`, `IrChart`, `BandsPanel`, `SpectraPanel`, `MetadataPanel`, `useIrEditor` (all `/ir`) |
|
|
111
|
+
| **Spectra** | `FILTER_CATALOG`, `filterMenu`, `settingsProblems`, `normalizationFilters`, `addFilter`, `moveFilter`, `setFilterOption`, `principalComponentChoices`, `clampPrincipalComponents`, `EMPTY_SETTINGS` (all `/spectra`) | `SpectraSettingsEditor`, `FilterChainEditor`, `PrincipalComponentSelect` (all `/spectra`) |
|
|
112
|
+
| **About** | `resolveAbout`, `aboutProblems` | `AboutPage` |
|
|
113
|
+
| **Which build is running** | `formatBuiltAt`, `shortCommit`, `BuildInfo` | `AboutBuild`, `cheminfoBuildInfo` (`/vite`) |
|
|
114
|
+
| **Slideshows** | `parseTalk`, `splitDemoLinks`, `slideActionForKey`, `parseTalkOrigin`, `buildTalkManifest` (all `/slides`) | `Slideshow`, `SlideView`, `TalkList`, `BackToSlides` (all `/slides`), `cheminfoTalks` (`/vite`) |
|
|
115
|
+
| **Token guard** | `findTokenViolations` | `cheminfo-check-tokens`, `cheminfo-check-messages`, `cheminfo-check-deploy` (the bins) |
|
|
116
|
+
| **Figures** | `chartScale`, `chartAxisScale`, `chartAxisTitle`, `chartShare`, `chartColumnExtent`, `chartBinCounts`, `chartSeriesColor`, `rowMatrix`, `stackedMatrix`, `emptiestCorner`, `placeOverlayCard`, `overlayMetrics` | `ChartFrame`, `ChartAxis`, `TrackedLineChart`, `OverlayBar`, `OverlaySelect`, `OverlaySegmented`, `OverlayToggle`, `OverlayNumber`, `OverlayLegend`, `OverlayCaption`, `OverlayReadout` |
|
|
117
|
+
| **Projections** | `pcaResult`, `embeddingResult`, `projectionTabs`, `loadingProfiles`, `explainedShares`, `confidenceEllipse`, `projectEllipse`, `pointsInPolygon`, `resolveProjectionGroups`, `resolveProjectionShapes`, `PROJECTION_COPY` | `PcaViewer`, `ProjectionViewer`, `ScatterPlot`, `ScatterMatrix` |
|
|
118
|
+
| **Parallel coordinates** | `parallelAxisOf`, `parallelAxisLayouts`, `parallelIncludedMask`, `parallelKeptCount`, `parallelNearestRow`, `parallelSegmentAt`, `parallelBandAt`, `parallelRangeOf`, `parallelPalette`, `parallelColorSteps`, `paintParallelLines` | `ParallelCoordinates` |
|
|
119
|
+
| **Periodic table** | `PERIODIC_ELEMENTS`, `elementBySymbol`, `elementByAtomicNumber`, `cellOf`, `placedElements`, `elementByArrowKey`, `EMPTY_BLOCK`, `categorySwatch`, `CATEGORY_LABELS` | `PeriodicTable`, `ElementCell`, `CategoryLegend` |
|
|
120
|
+
| **Taxonomy** | `TAXON_RANKS`, `PRINCIPAL_RANKS`, `rankOrder`, `isPrincipalRank`, `isGenusOrBelow`, `isAboveGenus`, `principalLineage`, `lineageFromNodes`, `lineageFromRanks`, `genusOrBelow`, `ncbiTaxonomyUrl`, `splitOrganismName` | `TaxonLineage`, `OrganismName`, `useRankLabel` |
|
|
121
|
+
| **Framed by a host** | `hostStructureLoader`, `readHostMolecule`, `STRUCTURE_KINDS`, `connectHost`, `selectInputs`, `checkValue`, `kindAccepts`, `parseRequest` (all `/host`); `startStandInHost`, `SCIPEAKS_ETHYLBENZENE_LOAD` (`/host-testing`) | `useHostConnection` (`/host`) |
|
|
119
122
|
|
|
120
123
|
Everything in that table is exported from `./core`, `./ui`, `./slides`,
|
|
121
124
|
`./vite` or `./structure` and nothing else is: the sub-components a component is built
|
|
@@ -836,6 +839,92 @@ const included = useMemo(
|
|
|
836
839
|
subject — a formula through `react-mf`, a structure, a name — and a readout of
|
|
837
840
|
strings cannot hold any of that.
|
|
838
841
|
|
|
842
|
+
## Framed by a notebook
|
|
843
|
+
|
|
844
|
+
A page that frames a tool — an electronic lab notebook such as SciPeaks, a
|
|
845
|
+
course — can hand it typed data instead of writing it into the link. The tool
|
|
846
|
+
says `cheminfo:hello` to its parent, the parent answers `cheminfo:connect` with
|
|
847
|
+
a private `MessageChannel` port, and the data arrives on that port as
|
|
848
|
+
`{ kind, value }` items, each checked against pipeline.cheminfo.org's JSON
|
|
849
|
+
Schema before the tool reads it. A tool taking a structure writes two things:
|
|
850
|
+
|
|
851
|
+
```ts
|
|
852
|
+
// src/tool.ts
|
|
853
|
+
import type { ToolInterface } from 'react-cheminfo/host';
|
|
854
|
+
import { STRUCTURE_KINDS, hostStructureLoader } from 'react-cheminfo/host';
|
|
855
|
+
|
|
856
|
+
export const TOOL: ToolInterface = {
|
|
857
|
+
name: '3d',
|
|
858
|
+
inputs: [{ key: 'structure', kinds: STRUCTURE_KINDS }],
|
|
859
|
+
outputs: [],
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
export const loadFromHost = hostStructureLoader((molecule, label) => {
|
|
863
|
+
loadSmiles(molecule.toIsomericSmiles(), label);
|
|
864
|
+
});
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
```tsx
|
|
868
|
+
// App.tsx, right after the hook that applies the address
|
|
869
|
+
useHostConnection(TOOL, { load: loadFromHost, build: BUILD_INFO });
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
- **Nothing is downloaded unless the page is framed**: the connection and ajv
|
|
873
|
+
are one lazy chunk, fetched once a parent or an opener exists.
|
|
874
|
+
- **A structure that does not read is answered, not shown**: the host gets
|
|
875
|
+
`unreadable` with one sentence it can display, and the screen does not change.
|
|
876
|
+
A molfile whose atoms all sit on one point — SciPeaks stores some that way —
|
|
877
|
+
is laid out again.
|
|
878
|
+
- **The same document twice is applied once**, so a host re-sending a sample
|
|
879
|
+
never overwrites what the visitor did with it.
|
|
880
|
+
|
|
881
|
+
`react-cheminfo/host-testing` serves a stand-in host for Playwright on
|
|
882
|
+
`127.0.0.1`, and exports `SCIPEAKS_ETHYLBENZENE_LOAD`: the message SciPeaks'
|
|
883
|
+
tool tab sends for a sample, byte for byte. visualizer-helper's tests pin the
|
|
884
|
+
same message, so a change on either side fails a test rather than a notebook.
|
|
885
|
+
|
|
886
|
+
```ts
|
|
887
|
+
const host = await startStandInHost();
|
|
888
|
+
await page.goto(
|
|
889
|
+
host.pageUrl(`${origin}/?embed=1`, [SCIPEAKS_ETHYLBENZENE_LOAD]),
|
|
890
|
+
);
|
|
891
|
+
const { results } = await page.evaluate(readStandInHostLog);
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
## Protecting a link
|
|
895
|
+
|
|
896
|
+
The share dialog can hand out a **sealed link**: the whole query string moved
|
|
897
|
+
into one `s` token, so a class can neither read nor edit what the link sets
|
|
898
|
+
up, and the page's address stays fixed while it is used.
|
|
899
|
+
|
|
900
|
+
```
|
|
901
|
+
https://surge.cheminfo.org/exercises?s=e1.x9dasYuwqR9SZzw…
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
A site offers it by opening its address before anything reads it. Everything
|
|
905
|
+
that reads the address at load moves to a second module:
|
|
906
|
+
|
|
907
|
+
```ts
|
|
908
|
+
// src/main.tsx
|
|
909
|
+
import { openSealedAddress } from 'react-cheminfo/core';
|
|
910
|
+
|
|
911
|
+
const opened = await openSealedAddress();
|
|
912
|
+
const { start } = await import('./start.tsx');
|
|
913
|
+
start(opened); // renders <SealedLinkRefused /> when opened.status is 'refused'
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
Calling `openSealedAddress` is what makes `ShareDialog` offer _Protect this
|
|
917
|
+
link_; a site that never calls it never hands out a link it cannot open. A
|
|
918
|
+
sealed page is always embedded. Its address is held in memory, so site code
|
|
919
|
+
reads the address through `pageLocation()` and writes it through
|
|
920
|
+
`pageHistory()`, never through `location` and `history` directly.
|
|
921
|
+
|
|
922
|
+
The token is deflated, then encrypted under an 8-byte HMAC tag that is also
|
|
923
|
+
the AES-CTR counter, so the same query always gives the same link, and an
|
|
924
|
+
edited one is refused. **The key ships in every bundle**: this stops a class,
|
|
925
|
+
not someone who digs the key out of the code. A token, once handed out, must
|
|
926
|
+
open for ever: a new key or format ships under a new version prefix (`e2`).
|
|
927
|
+
|
|
839
928
|
## Speaking four languages
|
|
840
929
|
|
|
841
930
|
Every word this library puts on a page — the header, the Tools menu, the Cite
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool's side of the host protocol: introduce itself to the page that
|
|
3
|
+
* frames it, take the private port that page answers with, and serve what
|
|
4
|
+
* arrives through it.
|
|
5
|
+
*
|
|
6
|
+
* Free of React and of the DOM — the window is handed in — so a test drives the
|
|
7
|
+
* whole exchange with a fake host and a real `MessageChannel`.
|
|
8
|
+
*/
|
|
9
|
+
import type { CheckedValue } from './kinds.ts';
|
|
10
|
+
import type { HostError, HostItem, ToolInterface } from './protocol.ts';
|
|
11
|
+
/** The item an input took, and its value as the input's kind reads it. */
|
|
12
|
+
export interface LoadedInput {
|
|
13
|
+
key: string;
|
|
14
|
+
item: HostItem;
|
|
15
|
+
checked: CheckedValue;
|
|
16
|
+
}
|
|
17
|
+
/** What a window `message` event carries, as far as the protocol reads it. */
|
|
18
|
+
export interface HostMessageEvent {
|
|
19
|
+
data: unknown;
|
|
20
|
+
source: unknown;
|
|
21
|
+
ports: readonly MessagePort[];
|
|
22
|
+
}
|
|
23
|
+
/** Where the connection runs, and what it serves. */
|
|
24
|
+
export interface HostConnectionOptions {
|
|
25
|
+
/** The page to introduce the tool to: the parent frame, or the opener. */
|
|
26
|
+
host: {
|
|
27
|
+
postMessage: (message: unknown, targetOrigin: string) => void;
|
|
28
|
+
};
|
|
29
|
+
/** Subscribe to this window's messages; the returned function unsubscribes. */
|
|
30
|
+
listen: (listener: (event: HostMessageEvent) => void) => () => void;
|
|
31
|
+
/** What the tool takes and gives, as `hello` announces it. */
|
|
32
|
+
tool: ToolInterface;
|
|
33
|
+
/** The tool's origin, as `hello` states it. */
|
|
34
|
+
origin: string;
|
|
35
|
+
/** The build that is running, as the About states it, or `null`. */
|
|
36
|
+
build: unknown;
|
|
37
|
+
/**
|
|
38
|
+
* Show the inputs of a new document. Throwing means they could not be read:
|
|
39
|
+
* the error's message goes back to the host, and the document is not marked
|
|
40
|
+
* as applied.
|
|
41
|
+
*/
|
|
42
|
+
load: (inputs: readonly LoadedInput[]) => void;
|
|
43
|
+
}
|
|
44
|
+
/** What choosing the items of a request gave. */
|
|
45
|
+
export type InputSelection = {
|
|
46
|
+
ok: true;
|
|
47
|
+
inputs: LoadedInput[];
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
error: HostError;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Say `hello` to the host, and serve its requests once it connects.
|
|
54
|
+
*
|
|
55
|
+
* A `connect` is accepted only from the window `hello` went to, and a second
|
|
56
|
+
* one replaces the first — a host that reloads its own script connects again.
|
|
57
|
+
* A document is applied once: the same one again is answered as before and
|
|
58
|
+
* changes nothing, so a host re-sending it never overwrites the user's work.
|
|
59
|
+
* @param options - The window, the tool, and its load function.
|
|
60
|
+
* @returns The function that stops listening and closes the port.
|
|
61
|
+
*/
|
|
62
|
+
export declare function connectHost(options: HostConnectionOptions): () => void;
|
|
63
|
+
/**
|
|
64
|
+
* Give each input of the tool one item of a request.
|
|
65
|
+
*
|
|
66
|
+
* Each input tries its kinds in its own order of preference, and takes the
|
|
67
|
+
* first item that falls under one and passes that kind's schema: the tool
|
|
68
|
+
* knows which notation serves it best, whatever order the host listed them in.
|
|
69
|
+
* An item naming another input's `key` is left to that input.
|
|
70
|
+
* @param tool - What the tool takes.
|
|
71
|
+
* @param items - What the host sent.
|
|
72
|
+
* @returns One item per input, or why an input got none.
|
|
73
|
+
*/
|
|
74
|
+
export declare function selectInputs(tool: ToolInterface, items: readonly HostItem[]): InputSelection;
|
|
75
|
+
//# sourceMappingURL=connectHost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectHost.d.ts","sourceRoot":"","sources":["../../../src/host/core/connectHost.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,YAAY,CAAC;AAE1D,OAAO,KAAK,EAGV,SAAS,EACT,QAAQ,EAIR,aAAa,EAEd,MAAM,eAAe,CAAC;AAQvB,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;CAC/B;AAED,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,IAAI,EAAE;QAAE,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACxE,+EAA+E;IAC/E,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACpE,8DAA8D;IAC9D,IAAI,EAAE,aAAa,CAAC;IACpB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,KAAK,IAAI,CAAC;CAChD;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAExE;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,IAAI,CA0EtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,QAAQ,EAAE,GACzB,cAAc,CA4BhB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool's side of the host protocol: introduce itself to the page that
|
|
3
|
+
* frames it, take the private port that page answers with, and serve what
|
|
4
|
+
* arrives through it.
|
|
5
|
+
*
|
|
6
|
+
* Free of React and of the DOM — the window is handed in — so a test drives the
|
|
7
|
+
* whole exchange with a fake host and a real `MessageChannel`.
|
|
8
|
+
*/
|
|
9
|
+
import { checkValue, isKnownKind, kindAccepts } from "./kinds.js";
|
|
10
|
+
import { HELLO_TYPE, PROTOCOL_VERSION, isConnect, parseRequest, } from "./protocol.js";
|
|
11
|
+
/**
|
|
12
|
+
* Say `hello` to the host, and serve its requests once it connects.
|
|
13
|
+
*
|
|
14
|
+
* A `connect` is accepted only from the window `hello` went to, and a second
|
|
15
|
+
* one replaces the first — a host that reloads its own script connects again.
|
|
16
|
+
* A document is applied once: the same one again is answered as before and
|
|
17
|
+
* changes nothing, so a host re-sending it never overwrites the user's work.
|
|
18
|
+
* @param options - The window, the tool, and its load function.
|
|
19
|
+
* @returns The function that stops listening and closes the port.
|
|
20
|
+
*/
|
|
21
|
+
export function connectHost(options) {
|
|
22
|
+
const { host, listen, tool, origin, build, load } = options;
|
|
23
|
+
let port = null;
|
|
24
|
+
let appliedDocument = null;
|
|
25
|
+
let appliedUsed = [];
|
|
26
|
+
function serve(data) {
|
|
27
|
+
const request = parseRequest(data);
|
|
28
|
+
if (request === null)
|
|
29
|
+
return;
|
|
30
|
+
const result = request.type === 'load' ? applyLoad(request) : answerGet(request, tool);
|
|
31
|
+
port?.postMessage(result);
|
|
32
|
+
}
|
|
33
|
+
function applyLoad(request) {
|
|
34
|
+
const { id, document, items } = request;
|
|
35
|
+
if (document === appliedDocument) {
|
|
36
|
+
return { type: 'result', id, ok: true, used: appliedUsed };
|
|
37
|
+
}
|
|
38
|
+
const selection = selectInputs(tool, items);
|
|
39
|
+
if (!selection.ok) {
|
|
40
|
+
return { type: 'result', id, ok: false, error: selection.error };
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
load(selection.inputs);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
47
|
+
return {
|
|
48
|
+
type: 'result',
|
|
49
|
+
id,
|
|
50
|
+
ok: false,
|
|
51
|
+
error: { code: 'unreadable', message },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
appliedDocument = document;
|
|
55
|
+
appliedUsed = selection.inputs.map(({ key, item }) => ({
|
|
56
|
+
key,
|
|
57
|
+
kind: item.kind,
|
|
58
|
+
}));
|
|
59
|
+
return { type: 'result', id, ok: true, used: appliedUsed };
|
|
60
|
+
}
|
|
61
|
+
const stopListening = listen((event) => {
|
|
62
|
+
if (event.source !== host || !isConnect(event.data))
|
|
63
|
+
return;
|
|
64
|
+
const received = event.ports[0];
|
|
65
|
+
if (received === undefined)
|
|
66
|
+
return;
|
|
67
|
+
port?.close();
|
|
68
|
+
port = received;
|
|
69
|
+
port.addEventListener('message', (message) => {
|
|
70
|
+
serve(message.data);
|
|
71
|
+
});
|
|
72
|
+
port.start();
|
|
73
|
+
});
|
|
74
|
+
const hello = {
|
|
75
|
+
type: HELLO_TYPE,
|
|
76
|
+
version: PROTOCOL_VERSION,
|
|
77
|
+
tool: {
|
|
78
|
+
name: tool.name,
|
|
79
|
+
origin,
|
|
80
|
+
build,
|
|
81
|
+
inputs: tool.inputs,
|
|
82
|
+
outputs: tool.outputs,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
// `hello` says nothing a stranger may not read, and the parent's origin is
|
|
86
|
+
// not knowable until it answers.
|
|
87
|
+
host.postMessage(hello, '*');
|
|
88
|
+
return () => {
|
|
89
|
+
stopListening();
|
|
90
|
+
port?.close();
|
|
91
|
+
port = null;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Give each input of the tool one item of a request.
|
|
96
|
+
*
|
|
97
|
+
* Each input tries its kinds in its own order of preference, and takes the
|
|
98
|
+
* first item that falls under one and passes that kind's schema: the tool
|
|
99
|
+
* knows which notation serves it best, whatever order the host listed them in.
|
|
100
|
+
* An item naming another input's `key` is left to that input.
|
|
101
|
+
* @param tool - What the tool takes.
|
|
102
|
+
* @param items - What the host sent.
|
|
103
|
+
* @returns One item per input, or why an input got none.
|
|
104
|
+
*/
|
|
105
|
+
export function selectInputs(tool, items) {
|
|
106
|
+
const inputs = [];
|
|
107
|
+
for (const input of tool.inputs) {
|
|
108
|
+
const errors = [];
|
|
109
|
+
const loaded = selectInput(input, items, errors);
|
|
110
|
+
if (loaded !== null) {
|
|
111
|
+
inputs.push(loaded);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (errors.length > 0) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
error: {
|
|
118
|
+
code: 'invalid',
|
|
119
|
+
message: `No item for ${input.key} has the shape its kind requires, so ${tool.name} loaded nothing.`,
|
|
120
|
+
errors,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
error: {
|
|
127
|
+
code: 'no-input',
|
|
128
|
+
message: `No item is a ${KIND_LIST.format(input.kinds)}, so ${tool.name} loaded nothing.`,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { ok: true, inputs };
|
|
133
|
+
}
|
|
134
|
+
function selectInput(input, items, errors) {
|
|
135
|
+
for (const accepted of input.kinds) {
|
|
136
|
+
if (!isKnownKind(accepted))
|
|
137
|
+
continue;
|
|
138
|
+
for (const item of items) {
|
|
139
|
+
if (item.key !== undefined && item.key !== input.key)
|
|
140
|
+
continue;
|
|
141
|
+
if (!kindAccepts(accepted, item.kind))
|
|
142
|
+
continue;
|
|
143
|
+
const loaded = checkItem(input.key, accepted, item, errors);
|
|
144
|
+
if (loaded !== null)
|
|
145
|
+
return loaded;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
function checkItem(key, accepted, item, errors) {
|
|
151
|
+
const outcome = checkValue(accepted, item.value);
|
|
152
|
+
if (outcome.valid)
|
|
153
|
+
return { key, item, checked: outcome.checked };
|
|
154
|
+
for (const error of outcome.errors)
|
|
155
|
+
errors.push(`${item.kind} ${error}`);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
function answerGet(request, tool) {
|
|
159
|
+
// Nothing goes back yet: no tool declares an output.
|
|
160
|
+
return {
|
|
161
|
+
type: 'result',
|
|
162
|
+
id: request.id,
|
|
163
|
+
ok: false,
|
|
164
|
+
error: {
|
|
165
|
+
code: 'no-output',
|
|
166
|
+
message: `${tool.name} has nothing to give back yet.`,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const KIND_LIST = new Intl.ListFormat('en', { type: 'disjunction' });
|
|
171
|
+
//# sourceMappingURL=connectHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectHost.js","sourceRoot":"","sources":["../../../src/host/core/connectHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A structure a host handed over, read into the molecule a tool works on.
|
|
3
|
+
*
|
|
4
|
+
* Every tool of the family that takes a structure takes it the same way — in
|
|
5
|
+
* the three notations a notebook keeps, the one that says the most first — so
|
|
6
|
+
* the kinds, the parsing and the sentence a host reads when it fails are
|
|
7
|
+
* written once, here.
|
|
8
|
+
*/
|
|
9
|
+
import type { Molecule } from 'openchemlib';
|
|
10
|
+
import type { StructureSource } from '../../structure/core/structureSource.ts';
|
|
11
|
+
import type { LoadedInput } from './connectHost.ts';
|
|
12
|
+
import type { CheckedValue } from './kinds.ts';
|
|
13
|
+
/**
|
|
14
|
+
* The kinds a structure input accepts, in order of preference: a molfile
|
|
15
|
+
* carries the layout its author drew, an idcode the exact structure, a SMILES
|
|
16
|
+
* only the connectivity.
|
|
17
|
+
*/
|
|
18
|
+
export declare const STRUCTURE_KINDS: readonly ["chem.molfile", "chem.ocl.id", "chem.smiles"];
|
|
19
|
+
/** A checked value holding a structure. */
|
|
20
|
+
export type StructureValue = Extract<CheckedValue, {
|
|
21
|
+
kind: (typeof STRUCTURE_KINDS)[number];
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* The function a tool hands `useHostConnection` as `load` when its input is a
|
|
25
|
+
* structure.
|
|
26
|
+
*
|
|
27
|
+
* The structure is parsed before `show` is called, so one that cannot be read
|
|
28
|
+
* is answered `unreadable` with a sentence the host can show, and nothing on
|
|
29
|
+
* the tool's screen changes.
|
|
30
|
+
* @param show - Puts the molecule on screen, under the host's label for it.
|
|
31
|
+
* @param key - The input the structure arrives on.
|
|
32
|
+
* @returns The `load` function.
|
|
33
|
+
*/
|
|
34
|
+
export declare function hostStructureLoader(show: (molecule: Molecule, label: string | undefined) => void, key?: string): (inputs: readonly LoadedInput[]) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Read a structure a host sent.
|
|
37
|
+
*
|
|
38
|
+
* A molfile whose atoms all sit on one point — SciPeaks stores some that way —
|
|
39
|
+
* is laid out again, so a tool that draws it does not draw one dot.
|
|
40
|
+
* @param checked - The value, already checked against its kind.
|
|
41
|
+
* @returns A molecule with at least one atom.
|
|
42
|
+
* @throws {Error} When the notation does not parse or describes no atoms; the
|
|
43
|
+
* message is the sentence the host is answered with.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readHostMolecule(checked: StructureValue): Molecule;
|
|
46
|
+
/**
|
|
47
|
+
* A structure a host sent, as the notation a depiction is drawn from.
|
|
48
|
+
* @param checked - The value, already checked against its kind.
|
|
49
|
+
* @returns The notation and its text; an idcode keeps its coordinates.
|
|
50
|
+
*/
|
|
51
|
+
export declare function hostStructureSource(checked: StructureValue): StructureSource;
|
|
52
|
+
//# sourceMappingURL=hostStructure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostStructure.d.ts","sourceRoot":"","sources":["../../../src/host/core/hostStructure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAI5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,eAAe,yDAIlB,CAAC;AAEX,2CAA2C;AAC3C,MAAM,MAAM,cAAc,GAAG,OAAO,CAClC,YAAY,EACZ;IAAE,IAAI,EAAE,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;CAAE,CAC3C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,EAC7D,GAAG,SAAc,GAChB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,KAAK,IAAI,CAO1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,QAAQ,CAmBlE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAW5E"}
|