react-cheminfo 0.47.0 → 0.48.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 +69 -0
- package/lib/core.d.ts +1 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +1 -0
- package/lib/core.js.map +1 -1
- package/lib/download/core/cssPaint.d.ts +27 -0
- package/lib/download/core/cssPaint.d.ts.map +1 -0
- package/lib/download/core/cssPaint.js +63 -0
- package/lib/download/core/cssPaint.js.map +1 -0
- package/lib/download/core/drawingMarkup.d.ts +11 -0
- package/lib/download/core/drawingMarkup.d.ts.map +1 -0
- package/lib/download/core/drawingMarkup.js +32 -0
- package/lib/download/core/drawingMarkup.js.map +1 -0
- package/lib/download/core/figureHtml.d.ts +25 -0
- package/lib/download/core/figureHtml.d.ts.map +1 -0
- package/lib/download/core/figureHtml.js +174 -0
- package/lib/download/core/figureHtml.js.map +1 -0
- package/lib/download/core/figureHtmlMarkup.d.ts +107 -0
- package/lib/download/core/figureHtmlMarkup.d.ts.map +1 -0
- package/lib/download/core/figureHtmlMarkup.js +75 -0
- package/lib/download/core/figureHtmlMarkup.js.map +1 -0
- package/lib/download/core/figureSvg.d.ts.map +1 -1
- package/lib/download/core/figureSvg.js +16 -35
- package/lib/download/core/figureSvg.js.map +1 -1
- package/lib/download/core/figureSvgDocument.d.ts +3 -3
- package/lib/download/core/figureSvgDocument.d.ts.map +1 -1
- package/lib/download/core/figureTarget.d.ts +14 -3
- package/lib/download/core/figureTarget.d.ts.map +1 -1
- package/lib/download/core/figureTarget.js +42 -3
- package/lib/download/core/figureTarget.js.map +1 -1
- package/lib/download/core/index.d.ts +1 -1
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +1 -1
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/core/textLines.d.ts +27 -0
- package/lib/download/core/textLines.d.ts.map +1 -0
- package/lib/download/core/textLines.js +51 -0
- package/lib/download/core/textLines.js.map +1 -0
- package/lib/ecosystem/core/lookup.d.ts +2 -1
- package/lib/ecosystem/core/lookup.d.ts.map +1 -1
- package/lib/ecosystem/core/lookup.js +10 -3
- package/lib/ecosystem/core/lookup.js.map +1 -1
- package/lib/ecosystem/core/types.d.ts +2 -2
- package/lib/ecosystem/core/types.d.ts.map +1 -1
- package/lib/ecosystem/core/unlistedSites.d.ts +9 -0
- package/lib/ecosystem/core/unlistedSites.d.ts.map +1 -0
- package/lib/ecosystem/core/unlistedSites.js +35 -0
- package/lib/ecosystem/core/unlistedSites.js.map +1 -0
- package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.js +7 -0
- package/lib/ecosystem/ui/glyphs.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 +55 -1
- package/lib/locales/en.json +55 -1
- package/lib/locales/es.json +55 -1
- package/lib/locales/fr.json +55 -1
- package/lib/locales/it.json +55 -1
- package/lib/periodic/ui/PeriodicTable.d.ts +3 -107
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +5 -82
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/periodic/ui/PeriodicTableChrome.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTableChrome.js +3 -25
- package/lib/periodic/ui/PeriodicTableChrome.js.map +1 -1
- package/lib/periodic/ui/SelectAllCorner.d.ts +23 -0
- package/lib/periodic/ui/SelectAllCorner.d.ts.map +1 -0
- package/lib/periodic/ui/SelectAllCorner.js +40 -0
- package/lib/periodic/ui/SelectAllCorner.js.map +1 -0
- package/lib/periodic/ui/headerStyles.d.ts +17 -0
- package/lib/periodic/ui/headerStyles.d.ts.map +1 -0
- package/lib/periodic/ui/headerStyles.js +19 -0
- package/lib/periodic/ui/headerStyles.js.map +1 -0
- package/lib/periodic/ui/periodicTableProps.d.ts +115 -0
- package/lib/periodic/ui/periodicTableProps.d.ts.map +1 -0
- package/lib/periodic/ui/periodicTableProps.js +8 -0
- package/lib/periodic/ui/periodicTableProps.js.map +1 -0
- package/lib/periodic/ui/tableLayout.d.ts +26 -0
- package/lib/periodic/ui/tableLayout.d.ts.map +1 -0
- package/lib/periodic/ui/tableLayout.js +86 -0
- package/lib/periodic/ui/tableLayout.js.map +1 -0
- package/lib/split/ui/SplitColumn.d.ts +0 -1
- package/lib/split/ui/SplitColumn.d.ts.map +1 -1
- package/lib/split/ui/SplitColumn.js +0 -1
- package/lib/split/ui/SplitColumn.js.map +1 -1
- package/lib/split/ui/SplitRow.d.ts +0 -1
- package/lib/split/ui/SplitRow.d.ts.map +1 -1
- package/lib/split/ui/SplitRow.js +0 -1
- package/lib/split/ui/SplitRow.js.map +1 -1
- package/lib/split/ui/splitPanes.d.ts +12 -1
- package/lib/split/ui/splitPanes.d.ts.map +1 -1
- package/lib/split/ui/splitPanes.js +1 -4
- package/lib/split/ui/splitPanes.js.map +1 -1
- package/lib/taxonomy/core/index.d.ts +8 -0
- package/lib/taxonomy/core/index.d.ts.map +1 -0
- package/lib/taxonomy/core/index.js +5 -0
- package/lib/taxonomy/core/index.js.map +1 -0
- package/lib/taxonomy/core/lineage.d.ts +83 -0
- package/lib/taxonomy/core/lineage.d.ts.map +1 -0
- package/lib/taxonomy/core/lineage.js +126 -0
- package/lib/taxonomy/core/lineage.js.map +1 -0
- package/lib/taxonomy/core/ncbi.d.ts +8 -0
- package/lib/taxonomy/core/ncbi.d.ts.map +1 -0
- package/lib/taxonomy/core/ncbi.js +10 -0
- package/lib/taxonomy/core/ncbi.js.map +1 -0
- package/lib/taxonomy/core/organismName.d.ts +28 -0
- package/lib/taxonomy/core/organismName.d.ts.map +1 -0
- package/lib/taxonomy/core/organismName.js +188 -0
- package/lib/taxonomy/core/organismName.js.map +1 -0
- package/lib/taxonomy/core/organismWords.d.ts +20 -0
- package/lib/taxonomy/core/organismWords.d.ts.map +1 -0
- package/lib/taxonomy/core/organismWords.js +86 -0
- package/lib/taxonomy/core/organismWords.js.map +1 -0
- package/lib/taxonomy/core/ranks.d.ts +51 -0
- package/lib/taxonomy/core/ranks.d.ts.map +1 -0
- package/lib/taxonomy/core/ranks.js +123 -0
- package/lib/taxonomy/core/ranks.js.map +1 -0
- package/lib/taxonomy/ui/OrganismName.d.ts +28 -0
- package/lib/taxonomy/ui/OrganismName.d.ts.map +1 -0
- package/lib/taxonomy/ui/OrganismName.js +28 -0
- package/lib/taxonomy/ui/OrganismName.js.map +1 -0
- package/lib/taxonomy/ui/TaxonLineage.d.ts +67 -0
- package/lib/taxonomy/ui/TaxonLineage.d.ts.map +1 -0
- package/lib/taxonomy/ui/TaxonLineage.js +45 -0
- package/lib/taxonomy/ui/TaxonLineage.js.map +1 -0
- package/lib/taxonomy/ui/index.d.ts +6 -0
- package/lib/taxonomy/ui/index.d.ts.map +1 -0
- package/lib/taxonomy/ui/index.js +4 -0
- package/lib/taxonomy/ui/index.js.map +1 -0
- package/lib/taxonomy/ui/rankLabel.d.ts +17 -0
- package/lib/taxonomy/ui/rankLabel.d.ts.map +1 -0
- package/lib/taxonomy/ui/rankLabel.js +77 -0
- package/lib/taxonomy/ui/rankLabel.js.map +1 -0
- package/lib/ui.d.ts +1 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +1 -0
- package/lib/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/core.ts +1 -0
- package/src/download/core/cssPaint.ts +71 -0
- package/src/download/core/drawingMarkup.ts +35 -0
- package/src/download/core/figureHtml.ts +214 -0
- package/src/download/core/figureHtmlMarkup.ts +187 -0
- package/src/download/core/figureSvg.ts +17 -38
- package/src/download/core/figureSvgDocument.ts +3 -3
- package/src/download/core/figureTarget.ts +41 -8
- package/src/download/core/index.ts +1 -0
- package/src/download/core/textLines.ts +67 -0
- package/src/ecosystem/core/lookup.ts +11 -3
- package/src/ecosystem/core/types.ts +4 -2
- package/src/ecosystem/core/unlistedSites.ts +37 -0
- package/src/ecosystem/ui/glyphs.tsx +44 -0
- package/src/locales/de.json +55 -1
- package/src/locales/en.json +55 -1
- package/src/locales/es.json +55 -1
- package/src/locales/fr.json +55 -1
- package/src/locales/it.json +55 -1
- package/src/periodic/ui/PeriodicTable.tsx +16 -204
- package/src/periodic/ui/PeriodicTableChrome.tsx +3 -24
- package/src/periodic/ui/SelectAllCorner.tsx +65 -0
- package/src/periodic/ui/headerStyles.ts +23 -0
- package/src/periodic/ui/periodicTableProps.ts +117 -0
- package/src/periodic/ui/tableLayout.ts +96 -0
- package/src/split/ui/SplitColumn.tsx +0 -1
- package/src/split/ui/SplitRow.tsx +0 -1
- package/src/split/ui/splitPanes.tsx +21 -5
- package/src/taxonomy/core/index.ts +20 -0
- package/src/taxonomy/core/lineage.ts +161 -0
- package/src/taxonomy/core/ncbi.ts +9 -0
- package/src/taxonomy/core/organismName.ts +217 -0
- package/src/taxonomy/core/organismWords.ts +86 -0
- package/src/taxonomy/core/ranks.ts +134 -0
- package/src/taxonomy/ui/OrganismName.tsx +59 -0
- package/src/taxonomy/ui/TaxonLineage.tsx +183 -0
- package/src/taxonomy/ui/index.ts +5 -0
- package/src/taxonomy/ui/rankLabel.ts +81 -0
- package/src/ui.ts +1 -0
- package/styles/chrome.css +135 -6
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isModifiedClick } from "../../chrome/ui/navItem.js";
|
|
3
|
+
import { useChromeT } from "../../i18n/ui/useT.js";
|
|
4
|
+
import { joinClassNames } from "../../shared/ui/joinClassNames.js";
|
|
5
|
+
import { genusOrBelow, principalLineage } from "../core/lineage.js";
|
|
6
|
+
import { ncbiTaxonomyUrl } from "../core/ncbi.js";
|
|
7
|
+
import { OrganismName } from "./OrganismName.js";
|
|
8
|
+
import { rankLabel } from "./rankLabel.js";
|
|
9
|
+
/**
|
|
10
|
+
* A lineage as a breadcrumb: the taxa from the top of the tree down, each
|
|
11
|
+
* named with its rank, the last one emphasised.
|
|
12
|
+
*
|
|
13
|
+
* The names under a genus are set in italics as nomenclature sets them, by
|
|
14
|
+
* {@link OrganismName}; the ranks are the chrome's words, translated with it.
|
|
15
|
+
* @param props - See {@link TaxonLineageProps}.
|
|
16
|
+
* @returns The breadcrumb, or nothing for an empty lineage.
|
|
17
|
+
*/
|
|
18
|
+
export function TaxonLineage(props) {
|
|
19
|
+
const { lineage, principal = true, taxonHref, onTaxonSelect, showRanks = false, ncbiLink = false, current = false, label, className, } = props;
|
|
20
|
+
const t = useChromeT();
|
|
21
|
+
const shown = principal ? principalLineage(lineage) : lineage;
|
|
22
|
+
if (shown.length === 0)
|
|
23
|
+
return null;
|
|
24
|
+
const italic = genusOrBelow(shown);
|
|
25
|
+
const steps = [];
|
|
26
|
+
for (let index = 0; index < shown.length; index++) {
|
|
27
|
+
const taxon = shown[index];
|
|
28
|
+
const last = index === shown.length - 1;
|
|
29
|
+
const rank = rankLabel(t, taxon.rank);
|
|
30
|
+
const name = italic[index] ? (_jsx(OrganismName, { name: taxon.name })) : (taxon.name);
|
|
31
|
+
const isCurrent = last && current;
|
|
32
|
+
const href = isCurrent ? undefined : taxonHref?.(taxon);
|
|
33
|
+
steps.push(_jsxs("li", { className: joinClassNames('taxon-lineage__taxon', last && 'taxon-lineage__taxon--leaf'), title: showRanks ? undefined : rank, children: [_jsxs("span", { className: "taxon-lineage__step", children: [showRanks && _jsx("span", { className: "taxon-lineage__rank", children: rank }), href === undefined ? (_jsx("span", { className: "taxon-lineage__name", "aria-current": isCurrent ? 'page' : undefined, children: name })) : (_jsx("a", { className: "taxon-lineage__name", href: href, onClick: onTaxonSelect === undefined
|
|
34
|
+
? undefined
|
|
35
|
+
: (event) => {
|
|
36
|
+
if (isModifiedClick(event) || event.button !== 0)
|
|
37
|
+
return;
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
onTaxonSelect(taxon);
|
|
40
|
+
}, children: name })), !showRanks && (_jsxs("span", { className: "taxon-lineage__spoken", children: [' ', t('taxonomy.rankNote', { rank })] }))] }), last ? (ncbiLink &&
|
|
41
|
+
taxon.taxId !== undefined && (_jsx("a", { className: "taxon-lineage__ncbi", href: ncbiTaxonomyUrl(taxon.taxId), target: "_blank", rel: "noreferrer", title: t('taxonomy.ncbiTitle', { name: taxon.name }), children: t('taxonomy.ncbi') }))) : (_jsx("span", { className: "taxon-lineage__separator", "aria-hidden": "true", children: "\u203A" }))] }, `${taxon.taxId ?? ''}:${taxon.rank}:${taxon.name}`));
|
|
42
|
+
}
|
|
43
|
+
return (_jsx("nav", { className: joinClassNames('taxon-lineage', showRanks && 'taxon-lineage--ranks', className), "aria-label": label ?? t('taxonomy.lineage'), children: _jsx("ol", { className: "taxon-lineage__list", children: steps }) }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=TaxonLineage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaxonLineage.js","sourceRoot":"","sources":["../../../src/taxonomy/ui/TaxonLineage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { OrganismNameProps } from './OrganismName.tsx';
|
|
2
|
+
export { OrganismName } from './OrganismName.tsx';
|
|
3
|
+
export type { TaxonLineageProps } from './TaxonLineage.tsx';
|
|
4
|
+
export { TaxonLineage } from './TaxonLineage.tsx';
|
|
5
|
+
export { useRankLabel } from './rankLabel.ts';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/taxonomy/ui/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/taxonomy/ui/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAoB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
|
|
2
|
+
import type { Translate } from '../../i18n/ui/useT.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A rank as the reader's language names it.
|
|
5
|
+
* @param t - The chrome's formatter.
|
|
6
|
+
* @param rank - The rank, as NCBI writes it.
|
|
7
|
+
* @returns Its label, or the rank itself when the catalog has none for it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function rankLabel(t: Translate<ChromeKey>, rank: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* The label of a rank in the reader's language, for a site writing a rank
|
|
12
|
+
* beside the lineage — a taxon's heading, a list of its children.
|
|
13
|
+
* @returns `label(rank)`: the rank as NCBI writes it, named the way the chrome
|
|
14
|
+
* names it; a rank the catalog does not know is returned as it is.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useRankLabel(): (rank: string) => string;
|
|
17
|
+
//# sourceMappingURL=rankLabel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rankLabel.d.ts","sourceRoot":"","sources":["../../../src/taxonomy/ui/rankLabel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA2DvD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAGvD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useChromeT } from "../../i18n/ui/useT.js";
|
|
2
|
+
// Each rank NCBI writes, with the key its label is translated under. Written
|
|
3
|
+
// out rather than built from the rank, so a key the catalog lacks fails the
|
|
4
|
+
// type check instead of rendering raw.
|
|
5
|
+
const RANK_KEYS = {
|
|
6
|
+
realm: 'taxonomy.rank.realm',
|
|
7
|
+
domain: 'taxonomy.rank.domain',
|
|
8
|
+
superkingdom: 'taxonomy.rank.superkingdom',
|
|
9
|
+
kingdom: 'taxonomy.rank.kingdom',
|
|
10
|
+
subkingdom: 'taxonomy.rank.subkingdom',
|
|
11
|
+
superphylum: 'taxonomy.rank.superphylum',
|
|
12
|
+
phylum: 'taxonomy.rank.phylum',
|
|
13
|
+
subphylum: 'taxonomy.rank.subphylum',
|
|
14
|
+
superclass: 'taxonomy.rank.superclass',
|
|
15
|
+
class: 'taxonomy.rank.class',
|
|
16
|
+
subclass: 'taxonomy.rank.subclass',
|
|
17
|
+
infraclass: 'taxonomy.rank.infraclass',
|
|
18
|
+
cohort: 'taxonomy.rank.cohort',
|
|
19
|
+
subcohort: 'taxonomy.rank.subcohort',
|
|
20
|
+
superorder: 'taxonomy.rank.superorder',
|
|
21
|
+
order: 'taxonomy.rank.order',
|
|
22
|
+
suborder: 'taxonomy.rank.suborder',
|
|
23
|
+
infraorder: 'taxonomy.rank.infraorder',
|
|
24
|
+
parvorder: 'taxonomy.rank.parvorder',
|
|
25
|
+
superfamily: 'taxonomy.rank.superfamily',
|
|
26
|
+
family: 'taxonomy.rank.family',
|
|
27
|
+
subfamily: 'taxonomy.rank.subfamily',
|
|
28
|
+
tribe: 'taxonomy.rank.tribe',
|
|
29
|
+
subtribe: 'taxonomy.rank.subtribe',
|
|
30
|
+
genus: 'taxonomy.rank.genus',
|
|
31
|
+
subgenus: 'taxonomy.rank.subgenus',
|
|
32
|
+
section: 'taxonomy.rank.section',
|
|
33
|
+
subsection: 'taxonomy.rank.subsection',
|
|
34
|
+
series: 'taxonomy.rank.series',
|
|
35
|
+
subseries: 'taxonomy.rank.subseries',
|
|
36
|
+
'species group': 'taxonomy.rank.speciesGroup',
|
|
37
|
+
'species subgroup': 'taxonomy.rank.speciesSubgroup',
|
|
38
|
+
species: 'taxonomy.rank.species',
|
|
39
|
+
'forma specialis': 'taxonomy.rank.formaSpecialis',
|
|
40
|
+
subspecies: 'taxonomy.rank.subspecies',
|
|
41
|
+
varietas: 'taxonomy.rank.varietas',
|
|
42
|
+
subvariety: 'taxonomy.rank.subvariety',
|
|
43
|
+
forma: 'taxonomy.rank.forma',
|
|
44
|
+
pathogroup: 'taxonomy.rank.pathogroup',
|
|
45
|
+
serogroup: 'taxonomy.rank.serogroup',
|
|
46
|
+
serotype: 'taxonomy.rank.serotype',
|
|
47
|
+
biotype: 'taxonomy.rank.biotype',
|
|
48
|
+
genotype: 'taxonomy.rank.genotype',
|
|
49
|
+
morph: 'taxonomy.rank.morph',
|
|
50
|
+
strain: 'taxonomy.rank.strain',
|
|
51
|
+
isolate: 'taxonomy.rank.isolate',
|
|
52
|
+
'no rank': 'taxonomy.rank.noRank',
|
|
53
|
+
clade: 'taxonomy.rank.clade',
|
|
54
|
+
'cellular root': 'taxonomy.rank.cellularRoot',
|
|
55
|
+
'acellular root': 'taxonomy.rank.acellularRoot',
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* A rank as the reader's language names it.
|
|
59
|
+
* @param t - The chrome's formatter.
|
|
60
|
+
* @param rank - The rank, as NCBI writes it.
|
|
61
|
+
* @returns Its label, or the rank itself when the catalog has none for it.
|
|
62
|
+
*/
|
|
63
|
+
export function rankLabel(t, rank) {
|
|
64
|
+
const key = Object.hasOwn(RANK_KEYS, rank) ? RANK_KEYS[rank] : undefined;
|
|
65
|
+
return key === undefined ? rank : t(key);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The label of a rank in the reader's language, for a site writing a rank
|
|
69
|
+
* beside the lineage — a taxon's heading, a list of its children.
|
|
70
|
+
* @returns `label(rank)`: the rank as NCBI writes it, named the way the chrome
|
|
71
|
+
* names it; a rank the catalog does not know is returned as it is.
|
|
72
|
+
*/
|
|
73
|
+
export function useRankLabel() {
|
|
74
|
+
const t = useChromeT();
|
|
75
|
+
return (rank) => rankLabel(t, rank);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=rankLabel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rankLabel.js","sourceRoot":"","sources":["../../../src/taxonomy/ui/rankLabel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,6EAA6E;AAC7E,4EAA4E;AAC5E,uCAAuC;AACvC,MAAM,SAAS,GAAwC;IACrD,KAAK,EAAE,qBAAqB;IAC5B,MAAM,EAAE,sBAAsB;IAC9B,YAAY,EAAE,4BAA4B;IAC1C,OAAO,EAAE,uBAAuB;IAChC,UAAU,EAAE,0BAA0B;IACtC,WAAW,EAAE,2BAA2B;IACxC,MAAM,EAAE,sBAAsB;IAC9B,SAAS,EAAE,yBAAyB;IACpC,UAAU,EAAE,0BAA0B;IACtC,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,wBAAwB;IAClC,UAAU,EAAE,0BAA0B;IACtC,MAAM,EAAE,sBAAsB;IAC9B,SAAS,EAAE,yBAAyB;IACpC,UAAU,EAAE,0BAA0B;IACtC,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,wBAAwB;IAClC,UAAU,EAAE,0BAA0B;IACtC,SAAS,EAAE,yBAAyB;IACpC,WAAW,EAAE,2BAA2B;IACxC,MAAM,EAAE,sBAAsB;IAC9B,SAAS,EAAE,yBAAyB;IACpC,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,wBAAwB;IAClC,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,wBAAwB;IAClC,OAAO,EAAE,uBAAuB;IAChC,UAAU,EAAE,0BAA0B;IACtC,MAAM,EAAE,sBAAsB;IAC9B,SAAS,EAAE,yBAAyB;IACpC,eAAe,EAAE,4BAA4B;IAC7C,kBAAkB,EAAE,+BAA+B;IACnD,OAAO,EAAE,uBAAuB;IAChC,iBAAiB,EAAE,8BAA8B;IACjD,UAAU,EAAE,0BAA0B;IACtC,QAAQ,EAAE,wBAAwB;IAClC,UAAU,EAAE,0BAA0B;IACtC,KAAK,EAAE,qBAAqB;IAC5B,UAAU,EAAE,0BAA0B;IACtC,SAAS,EAAE,yBAAyB;IACpC,QAAQ,EAAE,wBAAwB;IAClC,OAAO,EAAE,uBAAuB;IAChC,QAAQ,EAAE,wBAAwB;IAClC,KAAK,EAAE,qBAAqB;IAC5B,MAAM,EAAE,sBAAsB;IAC9B,OAAO,EAAE,uBAAuB;IAChC,SAAS,EAAE,sBAAsB;IACjC,KAAK,EAAE,qBAAqB;IAC5B,eAAe,EAAE,4BAA4B;IAC7C,gBAAgB,EAAE,6BAA6B;CAChD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAuB,EAAE,IAAY;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;IACvB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC"}
|
package/lib/ui.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export * from './scatter3d/ui/index.ts';
|
|
|
31
31
|
export * from './share/ui/index.ts';
|
|
32
32
|
export * from './shared/ui/index.ts';
|
|
33
33
|
export * from './split/ui/index.ts';
|
|
34
|
+
export * from './taxonomy/ui/index.ts';
|
|
34
35
|
export type { ConformerTableProps } from './structure/ui/ConformerTable.tsx';
|
|
35
36
|
export { ConformerTable } from './structure/ui/ConformerTable.tsx';
|
|
36
37
|
export type { ConformerColumn } from './structure/ui/conformerColumns.ts';
|
package/lib/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAKvC,YAAY,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
|
package/lib/ui.js
CHANGED
|
@@ -31,6 +31,7 @@ export * from "./scatter3d/ui/index.js";
|
|
|
31
31
|
export * from "./share/ui/index.js";
|
|
32
32
|
export * from "./shared/ui/index.js";
|
|
33
33
|
export * from "./split/ui/index.js";
|
|
34
|
+
export * from "./taxonomy/ui/index.js";
|
|
34
35
|
export { ConformerTable } from "./structure/ui/ConformerTable.js";
|
|
35
36
|
export { CONFORMER_COLUMN_LABELS, PICKER_COLUMNS, RANKING_COLUMNS, } from "./structure/ui/conformerColumns.js";
|
|
36
37
|
//# sourceMappingURL=ui.js.map
|
package/lib/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AAMvC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAmC,CAAC;AAEnE,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,oCAAoC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-cheminfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React components, hooks and framework-free helpers shared by the cheminfo sites: site chrome, citations, sharing, routing, pedagogy, charts, and the structure, orbital and 3D molecule viewers",
|
|
6
6
|
"author": "Luc Patiny",
|
package/src/core.ts
CHANGED
|
@@ -35,5 +35,6 @@ export * from './state/core/index.ts';
|
|
|
35
35
|
// Framework-free molfile and editor-value helpers, so a worker can read a
|
|
36
36
|
// molfile without loading the editor that `react-cheminfo/structure` exports.
|
|
37
37
|
export * from './structure/core/index.ts';
|
|
38
|
+
export * from './taxonomy/core/index.ts';
|
|
38
39
|
export * from './tokens/core/index.ts';
|
|
39
40
|
export * from './worker/core/index.ts';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a computed style says is painted, read the way a figure file needs it.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A colour, or nothing where the page paints nothing with it.
|
|
7
|
+
* @param color - A computed colour, as `getComputedStyle` writes it.
|
|
8
|
+
* @returns The colour, or undefined where it is transparent.
|
|
9
|
+
*/
|
|
10
|
+
export function visibleColor(color: string): string | undefined {
|
|
11
|
+
const value = color.trim();
|
|
12
|
+
if (value === '' || value === 'transparent') return undefined;
|
|
13
|
+
if (ZERO_ALPHA_COMMAS.test(value) || ZERO_ALPHA_SLASH.test(value)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The dashes a CSS line style is drawn with.
|
|
21
|
+
* @param style - The computed `border-*-style` or `outline-style`.
|
|
22
|
+
* @param width - The line's width, in pixels.
|
|
23
|
+
* @returns The dashes and gaps in pixels — empty for a solid line — or
|
|
24
|
+
* undefined where no line is drawn. `auto` is a focus ring, which is the
|
|
25
|
+
* state of the pointer rather than a part of the figure.
|
|
26
|
+
*/
|
|
27
|
+
export function lineDash(
|
|
28
|
+
style: string,
|
|
29
|
+
width: number,
|
|
30
|
+
): readonly number[] | undefined {
|
|
31
|
+
if (!(width > 0)) return undefined;
|
|
32
|
+
switch (style) {
|
|
33
|
+
case 'none':
|
|
34
|
+
case 'hidden':
|
|
35
|
+
case 'auto':
|
|
36
|
+
case '':
|
|
37
|
+
return undefined;
|
|
38
|
+
case 'dashed':
|
|
39
|
+
return [width * 3, width * 3];
|
|
40
|
+
case 'dotted':
|
|
41
|
+
return [width, width];
|
|
42
|
+
default:
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A corner radius in pixels.
|
|
49
|
+
* @param radius - The computed `border-*-radius`, in pixels or as a share.
|
|
50
|
+
* @param width - The box's width, which a share is taken of.
|
|
51
|
+
* @param height - Its height.
|
|
52
|
+
* @returns The radius, in pixels.
|
|
53
|
+
*/
|
|
54
|
+
export function cornerRadius(
|
|
55
|
+
radius: string,
|
|
56
|
+
width: number,
|
|
57
|
+
height: number,
|
|
58
|
+
): number {
|
|
59
|
+
const value = Number.parseFloat(radius);
|
|
60
|
+
if (!Number.isFinite(value) || value <= 0) return 0;
|
|
61
|
+
if (radius.trim().endsWith('%')) {
|
|
62
|
+
return (Math.min(width, height) * value) / 100;
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** `rgba(r, g, b, 0)`, which is what a transparent ground computes to. */
|
|
68
|
+
const ZERO_ALPHA_COMMAS = /^rgba\((?:[^,]+,){3}\s*0(?:\.0*)?\)$/;
|
|
69
|
+
|
|
70
|
+
/** `rgb(r g b / 0)` and `color(srgb r g b / 0)`. */
|
|
71
|
+
const ZERO_ALPHA_SLASH = /\/\s*0(?:\.0*)?%?\)$/;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cssTokenNames, resolveCssTokens } from './cssTokens.ts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One drawing, serialized with every token it names written out.
|
|
5
|
+
*
|
|
6
|
+
* The copy is taken first and read from the original, because the values are a
|
|
7
|
+
* property of where the figure sits on the page: a detached clone inherits
|
|
8
|
+
* nothing and would resolve every token to an empty string.
|
|
9
|
+
* @param drawing - The drawing, as it sits on the page.
|
|
10
|
+
* @returns Its markup.
|
|
11
|
+
*/
|
|
12
|
+
export function drawingMarkup(drawing: SVGSVGElement): string {
|
|
13
|
+
const clone = drawing.cloneNode(true) as SVGSVGElement;
|
|
14
|
+
const markup = new XMLSerializer().serializeToString(clone);
|
|
15
|
+
return resolveCssTokens(markup, tokenValues(drawing, cssTokenNames(markup)));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* What each token the markup names is worth where the figure is drawn.
|
|
20
|
+
* @param drawing - The drawing, as it sits on the page.
|
|
21
|
+
* @param names - The tokens it asks for.
|
|
22
|
+
* @returns The values, keyed by token name.
|
|
23
|
+
*/
|
|
24
|
+
function tokenValues(
|
|
25
|
+
drawing: SVGSVGElement,
|
|
26
|
+
names: readonly string[],
|
|
27
|
+
): Record<string, string> {
|
|
28
|
+
const values: Record<string, string> = {};
|
|
29
|
+
if (names.length === 0) return values;
|
|
30
|
+
const styles = window.getComputedStyle(drawing);
|
|
31
|
+
for (const name of names) {
|
|
32
|
+
values[name] = styles.getPropertyValue(name);
|
|
33
|
+
}
|
|
34
|
+
return values;
|
|
35
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A part of a figure the page draws in HTML, painted from where the browser put
|
|
3
|
+
* it.
|
|
4
|
+
*
|
|
5
|
+
* Some figures are not drawings: a periodic table is a grid of buttons, because
|
|
6
|
+
* every cell has to be reachable by Tab and read by a screen reader. Saved as
|
|
7
|
+
* SVG it still has to look like the table the reader saw, so each box, each
|
|
8
|
+
* line round it and each line of words is measured off the page and painted
|
|
9
|
+
* again — never re-derived from the styles that made it, so the copy cannot
|
|
10
|
+
* drift from the screen.
|
|
11
|
+
*
|
|
12
|
+
* What is painted: a box's ground, its border (as drawn on its top edge), its
|
|
13
|
+
* corner, its outline, its opacity, every line of its words in their colour,
|
|
14
|
+
* size, weight and style, and any `<svg>` inside it. What is not: images,
|
|
15
|
+
* gradients, shadows, filters and generated `::before` / `::after` content.
|
|
16
|
+
* Chrome inside the part — `data-figure="chrome"` — is left behind.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { cornerRadius, lineDash, visibleColor } from './cssPaint.ts';
|
|
20
|
+
import { drawingMarkup } from './drawingMarkup.ts';
|
|
21
|
+
import type { HtmlPaint } from './figureHtmlMarkup.ts';
|
|
22
|
+
import { figureHtmlMarkup } from './figureHtmlMarkup.ts';
|
|
23
|
+
import { lineBoxes } from './textLines.ts';
|
|
24
|
+
|
|
25
|
+
/** Chrome inside the part, which is not part of the picture. */
|
|
26
|
+
const CHROME = '[data-figure="chrome"]';
|
|
27
|
+
|
|
28
|
+
/** What every measurement of one part is taken against. */
|
|
29
|
+
interface PaintContext {
|
|
30
|
+
/** The part's own box: every position is written from its corner. */
|
|
31
|
+
origin: DOMRect;
|
|
32
|
+
/** The type the document is set in, which a run need not repeat. */
|
|
33
|
+
documentFont: string;
|
|
34
|
+
/** One range, moved over each character in turn. */
|
|
35
|
+
range: Range;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* One part of a figure drawn in HTML, as SVG markup.
|
|
40
|
+
* @param part - The element the part is drawn in.
|
|
41
|
+
* @param documentFont - The font family the saved document is set in.
|
|
42
|
+
* @returns The markup, in the part's own coordinates: the caller places it.
|
|
43
|
+
*/
|
|
44
|
+
export function figureHtml(part: Element, documentFont: string): string {
|
|
45
|
+
const context: PaintContext = {
|
|
46
|
+
origin: part.getBoundingClientRect(),
|
|
47
|
+
documentFont,
|
|
48
|
+
range: document.createRange(),
|
|
49
|
+
};
|
|
50
|
+
const paints: HtmlPaint[] = [];
|
|
51
|
+
paintElement(part, context, paints);
|
|
52
|
+
return figureHtmlMarkup(paints);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function paintElement(
|
|
56
|
+
element: Element,
|
|
57
|
+
context: PaintContext,
|
|
58
|
+
into: HtmlPaint[],
|
|
59
|
+
): void {
|
|
60
|
+
if (element.matches(CHROME)) return;
|
|
61
|
+
const styles = window.getComputedStyle(element);
|
|
62
|
+
if (styles.display === 'none') return;
|
|
63
|
+
const visible = styles.visibility === 'visible';
|
|
64
|
+
const box = element.getBoundingClientRect();
|
|
65
|
+
|
|
66
|
+
if (element instanceof SVGSVGElement) {
|
|
67
|
+
if (!visible || box.width <= 0 || box.height <= 0) return;
|
|
68
|
+
into.push({
|
|
69
|
+
kind: 'drawing',
|
|
70
|
+
markup: drawingMarkup(element),
|
|
71
|
+
x: box.left - context.origin.left,
|
|
72
|
+
y: box.top - context.origin.top,
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const own: HtmlPaint[] = [];
|
|
78
|
+
if (visible) paintGround(box, styles, context, own);
|
|
79
|
+
for (const child of element.childNodes) {
|
|
80
|
+
if (child instanceof Text) {
|
|
81
|
+
if (visible) paintText(child, styles, context, own);
|
|
82
|
+
} else if (child instanceof Element) {
|
|
83
|
+
paintElement(child, context, own);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (visible) paintOutline(box, styles, context, own);
|
|
87
|
+
if (own.length === 0) return;
|
|
88
|
+
|
|
89
|
+
const opacity = Number.parseFloat(styles.opacity);
|
|
90
|
+
if (Number.isFinite(opacity) && opacity < 1) {
|
|
91
|
+
into.push({ kind: 'group', opacity, children: own });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const paint of own) into.push(paint);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function paintGround(
|
|
98
|
+
box: DOMRect,
|
|
99
|
+
styles: CSSStyleDeclaration,
|
|
100
|
+
context: PaintContext,
|
|
101
|
+
into: HtmlPaint[],
|
|
102
|
+
): void {
|
|
103
|
+
if (box.width <= 0 || box.height <= 0) return;
|
|
104
|
+
const x = box.left - context.origin.left;
|
|
105
|
+
const y = box.top - context.origin.top;
|
|
106
|
+
const radius = cornerRadius(
|
|
107
|
+
styles.borderTopLeftRadius,
|
|
108
|
+
box.width,
|
|
109
|
+
box.height,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const fill = visibleColor(styles.backgroundColor);
|
|
113
|
+
if (fill !== undefined) {
|
|
114
|
+
into.push({
|
|
115
|
+
kind: 'box',
|
|
116
|
+
x,
|
|
117
|
+
y,
|
|
118
|
+
width: box.width,
|
|
119
|
+
height: box.height,
|
|
120
|
+
radius,
|
|
121
|
+
fill,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// A border lies inside the box, where a stroke straddles its line: the
|
|
126
|
+
// stroke is drawn half a width in, over the ground the page drew under it.
|
|
127
|
+
const width = Number.parseFloat(styles.borderTopWidth);
|
|
128
|
+
const dash = lineDash(styles.borderTopStyle, width);
|
|
129
|
+
const stroke = visibleColor(styles.borderTopColor);
|
|
130
|
+
if (dash === undefined || stroke === undefined) return;
|
|
131
|
+
const half = width / 2;
|
|
132
|
+
into.push({
|
|
133
|
+
kind: 'box',
|
|
134
|
+
x: x + half,
|
|
135
|
+
y: y + half,
|
|
136
|
+
width: box.width - width,
|
|
137
|
+
height: box.height - width,
|
|
138
|
+
radius: Math.max(0, radius - half),
|
|
139
|
+
stroke,
|
|
140
|
+
strokeWidth: width,
|
|
141
|
+
dash,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function paintOutline(
|
|
146
|
+
box: DOMRect,
|
|
147
|
+
styles: CSSStyleDeclaration,
|
|
148
|
+
context: PaintContext,
|
|
149
|
+
into: HtmlPaint[],
|
|
150
|
+
): void {
|
|
151
|
+
const width = Number.parseFloat(styles.outlineWidth);
|
|
152
|
+
const dash = lineDash(styles.outlineStyle, width);
|
|
153
|
+
const stroke = visibleColor(styles.outlineColor);
|
|
154
|
+
if (dash === undefined || stroke === undefined) return;
|
|
155
|
+
const offset = Number.parseFloat(styles.outlineOffset) || 0;
|
|
156
|
+
const grow = offset + width / 2;
|
|
157
|
+
const radius = cornerRadius(
|
|
158
|
+
styles.borderTopLeftRadius,
|
|
159
|
+
box.width,
|
|
160
|
+
box.height,
|
|
161
|
+
);
|
|
162
|
+
into.push({
|
|
163
|
+
kind: 'box',
|
|
164
|
+
x: box.left - context.origin.left - grow,
|
|
165
|
+
y: box.top - context.origin.top - grow,
|
|
166
|
+
width: box.width + grow * 2,
|
|
167
|
+
height: box.height + grow * 2,
|
|
168
|
+
radius: radius > 0 ? Math.max(0, radius + grow) : 0,
|
|
169
|
+
stroke,
|
|
170
|
+
strokeWidth: width,
|
|
171
|
+
dash,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function paintText(
|
|
176
|
+
node: Text,
|
|
177
|
+
styles: CSSStyleDeclaration,
|
|
178
|
+
context: PaintContext,
|
|
179
|
+
into: HtmlPaint[],
|
|
180
|
+
): void {
|
|
181
|
+
const color = visibleColor(styles.color);
|
|
182
|
+
if (color === undefined || node.data.trim() === '') return;
|
|
183
|
+
const fontSize = Number.parseFloat(styles.fontSize);
|
|
184
|
+
const fontStyle =
|
|
185
|
+
styles.fontStyle === 'normal' ? undefined : styles.fontStyle;
|
|
186
|
+
const fontFamily =
|
|
187
|
+
styles.fontFamily === context.documentFont ? undefined : styles.fontFamily;
|
|
188
|
+
|
|
189
|
+
for (const line of lineBoxes(node, context.range)) {
|
|
190
|
+
const words = transformed(
|
|
191
|
+
node.data.slice(line.start, line.end).replaceAll(/\s+/g, ' ').trim(),
|
|
192
|
+
styles.textTransform,
|
|
193
|
+
);
|
|
194
|
+
if (words === '') continue;
|
|
195
|
+
into.push({
|
|
196
|
+
kind: 'text',
|
|
197
|
+
text: words,
|
|
198
|
+
x: line.left - context.origin.left,
|
|
199
|
+
y: (line.top + line.bottom) / 2 - context.origin.top,
|
|
200
|
+
width: line.right - line.left,
|
|
201
|
+
color,
|
|
202
|
+
fontSize,
|
|
203
|
+
fontWeight: styles.fontWeight,
|
|
204
|
+
fontStyle,
|
|
205
|
+
fontFamily,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function transformed(words: string, transform: string): string {
|
|
211
|
+
if (transform === 'uppercase') return words.toUpperCase();
|
|
212
|
+
if (transform === 'lowercase') return words.toLowerCase();
|
|
213
|
+
return words;
|
|
214
|
+
}
|