@heycys/gallery 0.1.0 → 0.1.1
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/THIRD-PARTY-NOTICES.md +51 -1
- package/browser/editor/components/callout/index.mjs +40 -15
- package/browser/editor/components/columns/page.mjs +41 -28
- package/browser/editor/components/details/index.mjs +2 -1
- package/browser/editor/components/dialog/index.mjs +2 -1
- package/browser/editor/components/dialog/page.mjs +0 -18
- package/browser/editor/components/divider/index.mjs +1 -1
- package/browser/editor/components/figure/page.mjs +10 -1
- package/browser/editor/components/file/page.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +2 -2
- package/browser/editor/components/heading/index.mjs +2 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +4 -20
- package/browser/editor/components/icons.mjs +5 -2
- package/browser/editor/components/image/page.mjs +2 -2
- package/browser/editor/components/installed/index.mjs +71 -25
- package/browser/editor/components/installed/page.mjs +122 -21
- package/browser/editor/components/kit.mjs +3 -0
- package/browser/editor/components/media/page.mjs +44 -14
- package/browser/editor/components/pages.mjs +2 -2
- package/browser/editor/components/registry.mjs +56 -30
- package/browser/editor/components/section/index.mjs +2 -1
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/table/index.mjs +5 -3
- package/browser/editor/components/table/page.mjs +29 -18
- package/browser/editor/page/annotate/anchors.mjs +4 -3
- package/browser/editor/page/annotate/index.mjs +61 -34
- package/browser/editor/page/autosave.mjs +50 -4
- package/browser/editor/page/beside.mjs +5 -5
- package/browser/editor/page/block-menu/colors.mjs +3 -1
- package/browser/editor/page/block-menu/index.mjs +8 -6
- package/browser/editor/page/blocks.mjs +16 -7
- package/browser/editor/page/caret.mjs +4 -1
- package/browser/editor/page/changes/bar.mjs +102 -0
- package/browser/editor/page/changes/ghost.mjs +206 -0
- package/browser/editor/page/changes/gone-words.mjs +94 -0
- package/browser/editor/page/changes/index.mjs +447 -0
- package/browser/editor/page/changes/words.mjs +27 -0
- package/browser/editor/page/clipboard/import/colors.mjs +3 -3
- package/browser/editor/page/clipboard/index.mjs +32 -13
- package/browser/editor/page/clipboard/own/blocks.mjs +14 -5
- package/browser/editor/page/clipboard/own/describe.mjs +16 -7
- package/browser/editor/page/clipboard/own/export.mjs +6 -6
- package/browser/editor/page/clipboard/own/selection.mjs +2 -2
- package/browser/editor/page/clipboard/own/writers.mjs +0 -11
- package/browser/editor/page/columns/index.mjs +1 -1
- package/browser/editor/page/commit.mjs +19 -4
- package/browser/editor/page/conflicts.mjs +6 -26
- package/browser/editor/page/convert.mjs +8 -7
- package/browser/editor/page/core.mjs +55 -17
- package/browser/editor/page/drag/index.mjs +40 -24
- package/browser/editor/page/drag/preview.mjs +9 -4
- package/browser/editor/page/editor.mjs +70 -15
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
- package/browser/editor/page/emoji-picker/grid.mjs +7 -5
- package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
- package/browser/editor/page/emoji-picker/icons.mjs +0 -1
- package/browser/editor/page/emoji-picker/index.mjs +11 -9
- package/browser/editor/page/emoji-picker/styles.mjs +161 -2
- package/browser/editor/page/emoji-picker/support.mjs +6 -4
- package/browser/editor/page/emoji-picker/upload.mjs +12 -11
- package/browser/editor/page/fills.mjs +5 -3
- package/browser/editor/page/fold/index.mjs +348 -0
- package/browser/editor/page/fold/rule.mjs +125 -0
- package/browser/editor/page/folded.mjs +23 -0
- package/browser/editor/page/format-bar/bar.mjs +2 -1
- package/browser/editor/page/format-bar/index.mjs +1 -1
- package/browser/editor/page/geometry.mjs +8 -6
- package/browser/editor/page/handle/index.mjs +17 -6
- package/browser/editor/page/hints/index.mjs +1 -1
- package/browser/editor/page/insert/index.mjs +30 -17
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +15 -3
- package/browser/editor/page/margin.mjs +45 -24
- package/browser/editor/page/menu.mjs +69 -25
- package/browser/editor/page/merge.mjs +24 -0
- package/browser/editor/page/notices.mjs +1 -1
- package/browser/editor/page/offered.mjs +1 -1
- package/browser/editor/page/outline/folds.mjs +11 -10
- package/browser/editor/page/outline/index.mjs +131 -45
- package/browser/editor/page/outline/list.mjs +23 -11
- package/browser/editor/page/outline/read.mjs +1 -1
- package/browser/editor/page/outline/strip.mjs +7 -1
- package/browser/editor/page/panel.mjs +5 -4
- package/browser/editor/page/resize/index.mjs +1 -1
- package/browser/editor/page/selection/delete.mjs +8 -6
- package/browser/editor/page/selection/index.mjs +10 -3
- package/browser/editor/page/session.mjs +54 -3
- package/browser/editor/page/table/cell-bar.mjs +4 -1
- package/browser/editor/page/table/cells.mjs +1 -1
- package/browser/editor/page/table/icons.mjs +1 -1
- package/browser/editor/page/table/index.mjs +13 -8
- package/browser/editor/page/table/widths.mjs +9 -4
- package/browser/editor/page/text-select/index.mjs +18 -3
- package/browser/editor/page/tooltip.mjs +1 -1
- package/browser/editor/page/type-grid.mjs +4 -3
- package/browser/editor/page/typing/code-edges.mjs +63 -17
- package/browser/editor/page/typing/index.mjs +12 -6
- package/browser/editor/page/typing/leave.mjs +1 -1
- package/browser/shared/annotations.mjs +8 -10
- package/browser/shared/code-folds.mjs +5 -1
- package/browser/shared/colors.mjs +15 -13
- package/browser/shared/component-catalog.mjs +24 -10
- package/browser/shared/components/callout.mjs +4 -2
- package/browser/shared/components/index.mjs +61 -7
- package/browser/shared/components/installed.mjs +75 -5
- package/browser/shared/components/page.mjs +10 -1
- package/browser/shared/components/table.mjs +1 -1
- package/browser/shared/components/text.mjs +2 -2
- package/browser/shared/document-look.mjs +178 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/README.md +4 -2
- package/browser/shared/emoji/data/categories.json +1 -1
- package/browser/shared/emoji/data/keywords-en.json +1 -1
- package/browser/shared/emoji/data/keywords-zh.json +1 -1
- package/browser/shared/emoji/data/names.json +1 -1
- package/browser/shared/emoji/data/positions.json +1 -1
- package/browser/shared/emoji/data/twemoji-index.json +1 -1
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +10 -12
- package/browser/shared/emoji/emoji.mjs +8 -7
- package/browser/shared/emoji/icon-value.mjs +4 -3
- package/browser/shared/html-tree.mjs +11 -5
- package/browser/shared/i18n/en.mjs +67 -8
- package/browser/shared/long-runs.mjs +39 -0
- package/browser/shared/new-names.mjs +5 -2
- package/browser/shared/outline.mjs +194 -0
- package/browser/shared/preferences.mjs +10 -4
- package/browser/shared/session.mjs +5 -4
- package/browser/shared/workspace-look.mjs +91 -0
- package/browser/shared/zoom.mjs +5 -5
- package/dist/chunk-3HIRPVLU.mjs +2 -0
- package/dist/chunk-4FS7Z7WR.mjs +2 -0
- package/dist/{chunk-LHTFLRB6.mjs → chunk-5MHMDLZD.mjs} +2 -2
- package/dist/{chunk-YXAUQPVK.mjs → chunk-5ZKJ3H4P.mjs} +3 -3
- package/dist/{chunk-ZBIM6ARY.mjs → chunk-64K7IPLO.mjs} +55 -16
- package/dist/{chunk-QYKCJ7FG.mjs → chunk-6QXGZM36.mjs} +1 -1
- package/dist/chunk-6RGJOMJP.mjs +16 -0
- package/dist/{chunk-EUX7IC5J.mjs → chunk-7DTINW6U.mjs} +2 -2
- package/dist/{chunk-6CYG3Z4V.mjs → chunk-AJ73XJF3.mjs} +1 -1
- package/dist/chunk-AUZGSZJH.mjs +13 -0
- package/dist/{chunk-7QQBR7PB.mjs → chunk-BFE45AKL.mjs} +1 -1
- package/dist/chunk-BGGDRNYQ.mjs +10 -0
- package/dist/{chunk-L4DVONOG.mjs → chunk-BXO2ZY5P.mjs} +1 -1
- package/dist/chunk-CEH4MRCC.mjs +2 -0
- package/dist/chunk-CY2FNNAB.mjs +16 -0
- package/dist/{chunk-LC7YNQFG.mjs → chunk-DFUDV4LX.mjs} +1 -1
- package/dist/chunk-DKXG4XDG.mjs +2 -0
- package/dist/chunk-E7LWZRXY.mjs +4 -0
- package/dist/chunk-EZQ34M3F.mjs +124 -0
- package/dist/chunk-FDLXYYG4.mjs +4 -0
- package/dist/chunk-FUKQNOQS.mjs +9 -0
- package/dist/{chunk-DB4WKGYF.mjs → chunk-GB5SOYQJ.mjs} +2 -2
- package/dist/{chunk-ACOPDCNB.mjs → chunk-IVDLMMBD.mjs} +1 -1
- package/dist/chunk-JPOSLGOC.mjs +6 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-L3QKH4OK.mjs +26 -0
- package/dist/{chunk-B3VTYBYR.mjs → chunk-LCTHTZIL.mjs} +2 -2
- package/dist/chunk-LEF6DRCK.mjs +59 -0
- package/dist/chunk-LS4F7JUM.mjs +2 -0
- package/dist/chunk-NO5NJCHO.mjs +2 -0
- package/dist/{chunk-UNUEWH4S.mjs → chunk-NQPVAU63.mjs} +1 -1
- package/dist/chunk-O35FIXRB.mjs +2 -0
- package/dist/chunk-PL6GHLGD.mjs +15 -0
- package/dist/{chunk-G7TOXONE.mjs → chunk-QJIR2BLP.mjs} +1 -1
- package/dist/chunk-QUPLVPB2.mjs +7 -0
- package/dist/chunk-R7BNENLY.mjs +4 -0
- package/dist/chunk-S6O4UHLC.mjs +2 -0
- package/dist/{chunk-HMHK3EQ6.mjs → chunk-SGJWQKEI.mjs} +1 -1
- package/dist/chunk-SYGN7GLU.mjs +2 -0
- package/dist/chunk-TYK6VNAB.mjs +10 -0
- package/dist/{chunk-EVJ3BX3M.mjs → chunk-U6KNPJPR.mjs} +1 -1
- package/dist/{chunk-YZ5Z6H4W.mjs → chunk-UALRNVSE.mjs} +1 -1
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-V3HXVQEM.mjs +2 -0
- package/dist/{chunk-UXUK4PMC.mjs → chunk-V5JTW2LH.mjs} +1 -1
- package/dist/chunk-V5VXUJKG.mjs +2 -0
- package/dist/chunk-VBXMADMP.mjs +2 -0
- package/dist/chunk-VNV55RUA.mjs +2 -0
- package/dist/chunk-VPD2PS35.mjs +2 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-W4VKN3GF.mjs +7 -0
- package/dist/chunk-W5BXXPDJ.mjs +3 -0
- package/dist/{chunk-Z52HTUW7.mjs → chunk-XNROSH2T.mjs} +2 -2
- package/dist/chunk-XUNHRCOG.mjs +6 -0
- package/dist/{chunk-6U2SLSDN.mjs → chunk-Y6RLRPG3.mjs} +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/math.js +18 -2
- package/kit/report.css +248 -137
- package/kit/runtime.js +126 -51
- package/kit/tables.js +51 -1
- package/kit/ui.js +97 -0
- package/package.json +1 -1
- package/release.json +8 -8
- package/sdk/doc-kit.d.ts +9 -3
- package/skill/SKILL.md +22 -10
- package/skill/references/building-components.md +46 -6
- package/skill/references/example-report.html +1 -1
- package/skill/references/writing-html.md +4 -4
- package/skill/sdk/doc-kit.d.ts +9 -3
- package/web/assets/index-Bh74DfsV.css +1 -0
- package/web/assets/index-UW0RyFFt.js +13 -0
- package/web/index.html +2 -2
- package/browser/editor/components/callout/page.mjs +0 -13
- package/dist/chunk-2PBALTR3.mjs +0 -57
- package/dist/chunk-3LA3EMDE.mjs +0 -15
- package/dist/chunk-5FRMCDPY.mjs +0 -16
- package/dist/chunk-5LEK2CBS.mjs +0 -2
- package/dist/chunk-5OFN5AHC.mjs +0 -2
- package/dist/chunk-5SIYS5HN.mjs +0 -2
- package/dist/chunk-5TEK3RAD.mjs +0 -2
- package/dist/chunk-7GHT2UCA.mjs +0 -15
- package/dist/chunk-ATCJYAR4.mjs +0 -2
- package/dist/chunk-C7HWOBIF.mjs +0 -2
- package/dist/chunk-E7VYDG2X.mjs +0 -2
- package/dist/chunk-FQGQH4KM.mjs +0 -2
- package/dist/chunk-GPF4YWWB.mjs +0 -9
- package/dist/chunk-GYQV7Y4J.mjs +0 -120
- package/dist/chunk-HQQMJCQJ.mjs +0 -10
- package/dist/chunk-IERUOGC3.mjs +0 -6
- package/dist/chunk-ITNLYXXV.mjs +0 -3
- package/dist/chunk-NFIBI4IP.mjs +0 -26
- package/dist/chunk-O52JMOCZ.mjs +0 -2
- package/dist/chunk-QMQUXTU4.mjs +0 -12
- package/dist/chunk-QVWVFC5K.mjs +0 -6
- package/dist/chunk-QZY6Q64C.mjs +0 -2
- package/dist/chunk-TDQP3DKQ.mjs +0 -10
- package/dist/chunk-V4CPWKMZ.mjs +0 -2
- package/dist/chunk-VACRB2NE.mjs +0 -3
- package/dist/chunk-W63L7367.mjs +0 -7
- package/dist/chunk-W7CXPCRV.mjs +0 -6
- package/dist/chunk-XINNG4F2.mjs +0 -4
- package/dist/chunk-YL2DPWVS.mjs +0 -4
- package/web/assets/index-B6Ai3wsa.js +0 -13
- package/web/assets/index-SYPC3EZy.css +0 -1
|
@@ -23,6 +23,7 @@ import sheets from "./sheets/index.mjs";
|
|
|
23
23
|
import table from "./table/index.mjs";
|
|
24
24
|
import widget from "./widget/index.mjs";
|
|
25
25
|
import { CATEGORIES, componentOf } from "../../shared/components/index.mjs";
|
|
26
|
+
import { slotAround } from "../../shared/components/installed.mjs";
|
|
26
27
|
import { COLOR_CLASSES } from "./colors.mjs";
|
|
27
28
|
import { MEDIA_HOSTS } from "./media/parts.mjs";
|
|
28
29
|
import { t } from "../../shared/i18n/index.mjs";
|
|
@@ -34,14 +35,16 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
34
35
|
// whose category it takes: a basic block, a container, a card or a whole block (CATEGORIES there).
|
|
35
36
|
// Each describes itself:
|
|
36
37
|
//
|
|
37
|
-
// listed what 设置 ›
|
|
38
|
+
// listed what 设置 › 组件列表 calls it (a function, as the server says it in both languages), for a
|
|
38
39
|
// component the reader meets in the "/" menu or as a block of its own; every component
|
|
39
|
-
// with a type in that menu says it.
|
|
40
|
+
// with a type in that menu says it. Its line there shows the icon of its first row in the
|
|
41
|
+
// "/" menu (basic before advanced, by place), or, for a component with no type there (分区),
|
|
42
|
+
// its first unit's `icon`; a listed component with neither throws. hideable: false, it stays offered whatever gallery.json
|
|
40
43
|
// says, its switch there off and locked (文本, 标题, 列表, 分区): what a page cannot do
|
|
41
44
|
// without. What is hidden goes from "/", 在下方新建 and the handle's grid and nothing else
|
|
42
45
|
// (page/offered.mjs); its blocks, its Markdown shortcut and "Blocks at a glance" stay.
|
|
43
46
|
// units the unit kinds it defines (blocks the reader selects, moves and deletes):
|
|
44
|
-
// { [kind]: { name, icon?, match, chapter?, fixed?, block?, handle?, below?, boxed?, beside?, inRow?, sharesHeight?, entersAfter?, resizable?, copy?, clipboard?, sizes?, toggles?, colors?, colorDefaults?, removedEmpty?, turnsEmpty?, canHaveChildren?, emptyIsNothing?, fromWords?, attributes? } }
|
|
47
|
+
// { [kind]: { name, icon?, match, chapter?, fixed?, block?, handle?, below?, boxed?, beside?, inRow?, sharesHeight?, entersAfter?, resizable?, copy?, clipboard?, sizes?, toggles?, colors?, colorDefaults?, removedEmpty?, turnsEmpty?, leadsChapter?, canHaveChildren?, emptyIsNothing?, fromWords?, attributes? } }
|
|
45
48
|
// match: rules an element matches by its tag (one of `tag`), its class and its
|
|
46
49
|
// attribute, and by the element it stands in (`parent`: { tag?, class? }, a flowchart's
|
|
47
50
|
// step being an li whose parent is an ol.doc-flow), whichever are given; every
|
|
@@ -80,25 +83,30 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
80
83
|
// the page, each with the test of its values. icon: what its handle shows, for a
|
|
81
84
|
// kind no block type stands for (a type's own icon is its `types` entry's). removedEmpty:
|
|
82
85
|
// Backspace on the one empty block in it deletes it whole (a code block, a highlight block,
|
|
83
|
-
// a quote, a disclosure: typing/). turnsEmpty: it holds nothing to carry, so what it is
|
|
86
|
+
// a callout, a quote, a disclosure: typing/). turnsEmpty: it holds nothing to carry, so what it is
|
|
84
87
|
// turned into is an empty block of the type, in its place (a divider line: convert.mjs).
|
|
88
|
+
// leadsChapter: it may stand first in a chapter as the line above its heading, so a
|
|
89
|
+
// folded heading with only such blocks before it covers the chapter (a divider: fold/rule.mjs).
|
|
85
90
|
// canHaveChildren: notion-lite's, a block right after it goes under it by Tab, so the
|
|
86
91
|
// keys of a block stand after it as they stand in what it is in (a list: under its last item).
|
|
87
92
|
// emptyIsNothing: a block of it left empty counts as nothing written, in a container
|
|
88
93
|
// that says `removedEmpty`. fromWords: a block of it can be made again from its words alone.
|
|
89
94
|
// boxes the box kinds it defines (containers whose children are units): { [kind]: { role,
|
|
90
|
-
// name?, classes?, find?, owner?, takenBy?, also?, leaveByEnter?, lead?, firstLineActs?, firstBlock?, groups?, holdsOne?, emptyIsNothing?, outer?, selectAll? } }, classes being the kit's classes that make an element one
|
|
95
|
+
// name?, classes?, find?, owner?, takenBy?, also?, leaveByEnter?, endIsPadding?, lead?, firstLineActs?, firstBlock?, groups?, holdsOne?, emptyIsNothing?, outer?, selectAll? } }, classes being the kit's classes that make an element one
|
|
91
96
|
// (rank order, as above); the others the server knows by their tag (findUnits). find: where
|
|
92
97
|
// a unit's box of this kind is (a list item's lists, a disclosure's content, a Sheet area's
|
|
93
|
-
// panels); owner: the element of its unit that takes the box along (a Sheet panel's tab:
|
|
98
|
+
// panels, an instance's slots by their name: `find(unit, key)`); owner: the element of its unit that takes the box along (a Sheet panel's tab:
|
|
94
99
|
// boxOwner); takenBy: whether a unit's element is that one, for a box of this key, told from
|
|
95
100
|
// the element alone, which may be off the page with the box (takesBox);
|
|
96
101
|
// also: the unit kinds it takes besides what its role takes (a highlight block's icon);
|
|
97
102
|
// leaveByEnter: Enter on its empty last block moves that block out after it (typing/leave.mjs);
|
|
103
|
+
// endIsPadding: what is under its last block is its own padding (a highlight block, a
|
|
104
|
+
// callout, a disclosure's content): a click there makes no block, it is a gap like any other
|
|
105
|
+
// (geometry.mjs endOf, insert/ clickBlank);
|
|
98
106
|
// lead: the kind of unit it opens with as its fixed head, which is no block to fall
|
|
99
107
|
// between (a highlight block's icon: a box selection passes over it, a place before it is
|
|
100
108
|
// the place after it); firstLineActs: its first block shows the container's handle, not a
|
|
101
|
-
// handle of its own (Notion's disableFirstItemHoverMenu: a highlight block's, a quote's);
|
|
109
|
+
// handle of its own (Notion's disableFirstItemHoverMenu: a highlight block's, a callout's, a quote's);
|
|
102
110
|
// firstBlock: the type its first block (after its lead) always is, its first line (a
|
|
103
111
|
// flowchart's node: "paragraph", its title), which is turned into no other type (no
|
|
104
112
|
// 转换为, no Markdown shortcut there) and has nothing made, dropped or pasted before it;
|
|
@@ -107,7 +115,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
107
115
|
// groups: a plain <div> with no class in it is a group of blocks, not a block of its own (the
|
|
108
116
|
// same boxes as the shared descriptions' GROUPING_FLOWS: tests/unit/components.mjs);
|
|
109
117
|
// holdsOne: a change that leaves it empty puts an empty paragraph in it, so there is always a
|
|
110
|
-
// block to write in (a disclosure's content, a highlight block: core.mjs tidyEmptied);
|
|
118
|
+
// block to write in (a disclosure's content, a highlight block, a callout: core.mjs tidyEmptied);
|
|
111
119
|
// emptyIsNothing: as on a unit, of a box that is an element of its own, by its `classes`;
|
|
112
120
|
// outer: false, a block straight in it has no block around it for the reader, whatever
|
|
113
121
|
// stands around its element: no 选中外层 (a detail card's content: block-info.mjs outerOf);
|
|
@@ -121,16 +129,17 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
121
129
|
// sealed a selector: what stands in such an element is no text of a text block around it, as
|
|
122
130
|
// a list item holding it (caret.mjs editable): its own text blocks are the only hosts in it
|
|
123
131
|
// readOnly why an element of it stays read-only, on hover and on a click (hints/): rules
|
|
124
|
-
// { rank, at, says }, at a selector found from the element (closest),
|
|
132
|
+
// { rank, at, says }, at a selector found from the element (closest), or a function
|
|
133
|
+
// of the element saying whether the rule is its (an instance's own region, heldBy, which
|
|
134
|
+
// no selector tells from its slots), says the reason
|
|
125
135
|
// in the reader's words, or null for an element that needs none, having a tool of its
|
|
126
136
|
// own. Every component's rules are tried in `rank` order, with the page's (PAGE below),
|
|
127
137
|
// and the first match wins: a rule ranked below the page's 80 goes before any control's,
|
|
128
138
|
// and is the one that can claim a button as its own.
|
|
129
|
-
// hosts the kinds of text block it defines (data-ge-kind): { [kind]: { name, caps, tex?, wrapped?, parts?,
|
|
139
|
+
// hosts the kinds of text block it defines (data-ge-kind): { [kind]: { name, caps, tex?, wrapped?, parts?, opensBefore?, textFilters?, formula?, closed?, inner?, blankSays?, placeholder? } }, caps
|
|
130
140
|
// ({ bound, blockLevel }) giving what such a text block can do (source/); opensBefore:
|
|
131
141
|
// Enter at its very start, with words in it, puts an empty paragraph before its block
|
|
132
|
-
// where it does not split, as one that splits does (typing/);
|
|
133
|
-
// very end, a paragraph after its block, where it does not split; textFilters: false, what
|
|
142
|
+
// where it does not split, as one that splits does (typing/); textFilters: false, what
|
|
134
143
|
// is typed in it is taken as it is, no inline code, no space set by itself (notion-lite's);
|
|
135
144
|
// formula: false, no inline formula is offered in it or pasted as one, the kit drawing
|
|
136
145
|
// none there (takesFormula);
|
|
@@ -139,9 +148,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
139
148
|
// nodes say (a code block's code);
|
|
140
149
|
// parts: the parts of components ([component id, part name]: a part of its shared
|
|
141
150
|
// description edited as text, src/shared/components/) whose elements are text blocks
|
|
142
|
-
// of this kind, found so by the server's scan;
|
|
143
|
-
// text block of this kind, by the scan too, while it holds inline text alone (a callout); takes: the tag of a
|
|
144
|
-
// block that, standing alone in `whole` with nothing of its own, natural HTML makes its words; tex: its text is a formula's TeX alone; wrapped: the page makes the text block a
|
|
151
|
+
// of this kind, found so by the server's scan; tex: its text is a formula's TeX alone; wrapped: the page makes the text block a
|
|
145
152
|
// span inside the element, which keeps its own behaviour (a Sheet tab's button);
|
|
146
153
|
// blankSays: what the status line says of one left blank that must hold words, as a
|
|
147
154
|
// type's says of a block of it (blankSaysOf); placeholder: what one says while it
|
|
@@ -152,7 +159,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
152
159
|
// false` says nothing where a block of it would (a list item)
|
|
153
160
|
// types the blocks the reader can make on the page or turn a block into (the "/" menu,
|
|
154
161
|
// Markdown shortcuts, the block menu), written by the server in the kit's plain markup:
|
|
155
|
-
// { [type]: { tag, className?, kind,
|
|
162
|
+
// { [type]: { tag, className?, kind, box?, leaf?, wraps?, container?, part?, text?, inside?, tex?,
|
|
156
163
|
// empty?, resettable?, bare?, placeholder?, bar?, label?, icon?, hint?, markdown?, words?, turn?, menu?, fresh?,
|
|
157
164
|
// corner?, preload?, onSplit?, create?, takesAsIs?, holder?, nests?, joins?, leadIcon?, fromSelection?, clipboard?, glance? } } and, for the blocks the page
|
|
158
165
|
// and the server write apart from text, title?, content?, keyed?, written?,
|
|
@@ -165,7 +172,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
165
172
|
// quote's paragraph, a list item: notion-lite's `resettable`, typing/leave.mjs). leaf: the text block a block turned
|
|
166
173
|
// into the type becomes; wraps: such a text block sits in a container of the type, found
|
|
167
174
|
// by `container` (a selector); text: a plain text leaf; empty: a leaf written with no
|
|
168
|
-
// text too (a paragraph, a heading, a list item, a code block
|
|
175
|
+
// text too (a paragraph, a heading, a list item, a code block: an empty
|
|
169
176
|
// one stays, as Notion's; the page's core.mjs and the server's source/checks.mjs read
|
|
170
177
|
// this and nothing else); inside: the element its text is written in, as plain text
|
|
171
178
|
// (a code block's code element); tex: its text is a formula's TeX alone (a display
|
|
@@ -180,8 +187,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
180
187
|
// over (page/markdown/rules.mjs); turn: its place among
|
|
181
188
|
// the types a text block is turned into; fresh: its place among the types made as an
|
|
182
189
|
// empty block that stands for an empty one; menu: [group, place], its place in the "/"
|
|
183
|
-
// menu (group "basic" or "advanced"), which the block menu's 在下方新建 shows too;
|
|
184
|
-
// kind of text block a new one is (`hosts`; "flow" without: core.mjs newHost); corner: the
|
|
190
|
+
// menu (group "basic" or "advanced"), which the block menu's 在下方新建 shows too; corner: the
|
|
185
191
|
// type in whose cell of a type grid it sits, as a gray corner, when the grid has both
|
|
186
192
|
// (type-grid.mjs); preload: true, it needs something on the page as soon as a type grid
|
|
187
193
|
// offers it, and before a block with text is turned into it, which its page object's
|
|
@@ -197,7 +203,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
197
203
|
// paragraph. It returns the node the caret or the choice goes to (null: none); a type
|
|
198
204
|
// without is a text block, made by convert.mjs standIn.
|
|
199
205
|
// takesAsIs: a block turned into it goes into it as it is, each keeping its type (a
|
|
200
|
-
// highlight block, a disclosure); holder: its place among the containers that turn into
|
|
206
|
+
// highlight block, a callout, a disclosure); holder: its place among the containers that turn into
|
|
201
207
|
// one another, what they hold carried along; nests: false, none inside another of its
|
|
202
208
|
// kind; joins: false, a block turned into it never joins the one beside it; leadIcon: the
|
|
203
209
|
// icon a new one opens with; fromSelection: { label, icon }, its row of the format bar's
|
|
@@ -295,8 +301,10 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
295
301
|
// label, width }, or null; reason: why the block may not go, remove(): delete it); rowBeside(target),
|
|
296
302
|
// a row for a block of another component, beside its color, every page object being asked and each
|
|
297
303
|
// testing the block itself; acceptsFile(file), whether a file pasted makes a block of it, and
|
|
298
|
-
// fromFiles(
|
|
299
|
-
//
|
|
304
|
+
// fromFiles(put, files), that block made and handed to `put(block)`, the paste's, which puts it where a
|
|
305
|
+
// block pasted at the caret goes (one undo step) and says whether it could (notion-lite's
|
|
306
|
+
// createFromFiles(files, width, place), whose fromFiles gives the data of a new block and whose place
|
|
307
|
+
// the paste gives; the first page object that takes a file in their order); fromLink(figure,
|
|
300
308
|
// url, options), a block of the component filled from an address (notion-lite's, here the figure
|
|
301
309
|
// is there first: one pasted with its address, `{ pasted: true }`, a bookmark in an embed's place).
|
|
302
310
|
// What the rest of the editor asks of a component that does something of its own where every block
|
|
@@ -336,8 +344,17 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
336
344
|
// A new kit component gets a folder of its own and a line below.
|
|
337
345
|
export const COMPONENTS = [paragraph, heading, list, flowchart, quote, callout, highlight, details, code, divider, section, sheets, table, figure, image, file, bookmark, embed, columns, math, dialog, widget, icon, installed];
|
|
338
346
|
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
// The "/" menu's groups, in order (MENU_GROUPS below says the same).
|
|
348
|
+
const MENU_GROUP_ORDER = ["basic", "advanced"];
|
|
349
|
+
const menuRank = ({ menu }) => MENU_GROUP_ORDER.indexOf(menu[0]) * 1000 + menu[1];
|
|
350
|
+
// The mark of a component's line in 设置 › 组件列表: the icon of its first row in the "/" menu, the
|
|
351
|
+
// same drawing; one with no type there (分区) shows its first unit's (`icon`, a kind no type stands for).
|
|
352
|
+
const listedIcon = ({ types = {}, units = {} }) => Object.values(types).filter((spec) => spec.menu && spec.icon).sort((a, b) => menuRank(a) - menuRank(b))[0]?.icon
|
|
353
|
+
?? Object.values(units).find((unit) => unit.icon)?.icon ?? null;
|
|
354
|
+
|
|
355
|
+
/** The built-in components 设置 › 组件列表 lists: { id, name() (in the language t() says it in), icon (svg markup), hideable }, by the order above. */
|
|
356
|
+
export const LISTED_BLOCKS = COMPONENTS.filter((component) => component.listed).map((component) => ({ id: component.name, name: component.listed, icon: listedIcon(component), hideable: component.hideable ?? true }));
|
|
357
|
+
for (const { id, icon } of LISTED_BLOCKS) if (!icon) throw new Error(`component ${id} has a line in the settings (listed), so it needs an icon: a type in the "/" menu, or a unit's icon`);
|
|
341
358
|
|
|
342
359
|
/** The names of those the reader may hide. */
|
|
343
360
|
export const HIDEABLE = new Set(LISTED_BLOCKS.filter(({ hideable }) => hideable).map(({ id }) => id));
|
|
@@ -487,7 +504,7 @@ export const FRESH = inOrder((spec) => spec.fresh);
|
|
|
487
504
|
export const HOLDERS = inOrder((spec) => spec.holder);
|
|
488
505
|
|
|
489
506
|
/** The "/" menu's groups of block types, in order: { basic, advanced } (the menu says their names). */
|
|
490
|
-
export const MENU_GROUPS = Object.fromEntries(
|
|
507
|
+
export const MENU_GROUPS = Object.fromEntries(MENU_GROUP_ORDER.map((group) => [group, inOrder((spec) => (spec.menu?.[0] === group ? spec.menu[1] : undefined))]));
|
|
491
508
|
|
|
492
509
|
/** The types a block is made of from selected text, each with its row of the format bar's 更多 (`fromSelection`). */
|
|
493
510
|
export const FROM_SELECTION = Object.entries(BLOCK_TYPES).filter(([, spec]) => spec.fromSelection).map(([type, spec]) => ({ type, ...spec.fromSelection }));
|
|
@@ -538,9 +555,12 @@ const ONE_BLOCK_AT = ONE_BLOCK.map(({ at }) => at).join(", ");
|
|
|
538
555
|
/** What no text block around it reaches into (`sealed`), a selector, "" where no component says. */
|
|
539
556
|
export const SEALED = COMPONENTS.map((component) => component.sealed).filter(Boolean).join(", ");
|
|
540
557
|
|
|
558
|
+
// What is one block is found inside the slot whose inside is the document's region an element stands
|
|
559
|
+
// in, where it does (an instance's slot holds blocks of their own: installed.mjs slotAround).
|
|
541
560
|
const oneBlockOf = (element) => {
|
|
542
|
-
|
|
543
|
-
|
|
561
|
+
const region = slotAround(element);
|
|
562
|
+
let whole = null;
|
|
563
|
+
for (let around = element.closest(ONE_BLOCK_AT); around && (!region || region.contains(around)); around = around.parentElement?.closest(ONE_BLOCK_AT)) whole = around;
|
|
544
564
|
return whole && ONE_BLOCK.find(({ at }) => whole.matches(at)).name;
|
|
545
565
|
};
|
|
546
566
|
|
|
@@ -554,7 +574,8 @@ const textPartOf = (element) => TEXT_PARTS.find(({ match, at }) => [...(element.
|
|
|
554
574
|
|
|
555
575
|
/**
|
|
556
576
|
* The component an element is of, by name, or null. Nothing inside an element that is one block is
|
|
557
|
-
* anyone else's, whatever its tag or class (a cell's list, a Sheet's tab)
|
|
577
|
+
* anyone else's, whatever its tag or class (a cell's list, a Sheet's tab), but what an instance's slot
|
|
578
|
+
* holds, the document's blocks, each its own. Else that of its kind of text
|
|
558
579
|
* block, where a component defines the kind (a cell, a tab's name), that of the text part of a
|
|
559
580
|
* component it is, that of the unit it is (a flowchart's node, though an li) and last that of its type
|
|
560
581
|
* (a list's item made on the page). What stands in a container is its own component's, not the
|
|
@@ -598,7 +619,7 @@ export const takesBox = (element, { kind, key }) => Boolean(element && BOXES[kin
|
|
|
598
619
|
const FROM_WORDS = flagged("fromWords");
|
|
599
620
|
export const PLAIN_TEXT = new Set(Object.keys(BLOCK_TYPES).filter((type) => FROM_WORDS.has(BLOCK_TYPES[type].kind)));
|
|
600
621
|
|
|
601
|
-
/** Plain text leaves (paragraphs, small text, headings
|
|
622
|
+
/** Plain text leaves (paragraphs, small text, headings). */
|
|
602
623
|
export const TEXT_TYPES = new Set(Object.keys(BLOCK_TYPES).filter((type) => BLOCK_TYPES[type].text));
|
|
603
624
|
|
|
604
625
|
/** The heading type of each heading tag (H1 -> heading1). */
|
|
@@ -682,6 +703,8 @@ const ROLES = Object.fromEntries(Object.entries(BOXES).map(([kind, box]) => [kin
|
|
|
682
703
|
/** What a chapter is: the page and Sheet panels hold these besides body text. */
|
|
683
704
|
export const CHAPTER = flagged("chapter");
|
|
684
705
|
const FIXED = flagged("fixed"); // never inside a flow
|
|
706
|
+
/** What may stand first in a chapter as the line above its heading (`leadsChapter`: a divider, fold/). */
|
|
707
|
+
export const LEADS_CHAPTER = flagged("leadsChapter");
|
|
685
708
|
|
|
686
709
|
/** The kinds of box a plain <div> without a class is a group of blocks in (`groups`; source/units.mjs boxKind). */
|
|
687
710
|
export const GROUPING = new Set(Object.keys(BOXES).filter((kind) => BOXES[kind].groups));
|
|
@@ -695,6 +718,9 @@ export const HOLDS_ONE = new Set(Object.keys(BOXES).filter((kind) => BOXES[kind]
|
|
|
695
718
|
/** The box kinds whose empty last block Enter moves out after the box (`leaveByEnter`). */
|
|
696
719
|
export const LEAVES_BY_ENTER = new Set(Object.keys(BOXES).filter((kind) => BOXES[kind].leaveByEnter));
|
|
697
720
|
|
|
721
|
+
/** Whether what is under the last block of a box of this kind is its own padding (`endIsPadding`): a click there makes no block (geometry.mjs endOf). */
|
|
722
|
+
export const endIsPadding = (boxKind) => Boolean(BOXES[boxKind]?.endIsPadding);
|
|
723
|
+
|
|
698
724
|
/** The unit kinds Backspace deletes whole once nothing is written in them (`removedEmpty`). */
|
|
699
725
|
export const REMOVED_EMPTY = Object.keys(UNITS).filter((kind) => UNITS[kind].removedEmpty);
|
|
700
726
|
|
|
@@ -742,7 +768,7 @@ export const hasOuter = (boxKind) => BOXES[boxKind]?.outer !== false;
|
|
|
742
768
|
/** The unit kinds with a frame of their own (`boxed`): a double click between two makes a paragraph (insert/). */
|
|
743
769
|
export const BOXED = flagged("boxed");
|
|
744
770
|
|
|
745
|
-
/** The unit kinds a click to the right of one selects: the boxed ones and those that say `beside` (beside.mjs). */
|
|
771
|
+
/** The unit kinds a click to the right of one, past the text area it stands in, selects: the boxed ones and those that say `beside` (beside.mjs). */
|
|
746
772
|
export const BESIDE = new Set([...BOXED, ...flagged("beside")]);
|
|
747
773
|
|
|
748
774
|
/** Whether a unit of this kind stands beside another now, `element` being that unit (`beside`, `inRow`). */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SECTION_ICON } from "../icons.mjs";
|
|
1
2
|
import { HIGHLIGHT } from "../kit.mjs";
|
|
2
3
|
import { t } from "../../../shared/i18n/index.mjs";
|
|
3
4
|
// 分区: section.doc-section, a container of ordinary blocks (its title is whatever heading it
|
|
@@ -18,7 +19,7 @@ export default {
|
|
|
18
19
|
name: "section",
|
|
19
20
|
listed: () => t("分区"), hideable: false,
|
|
20
21
|
units: {
|
|
21
|
-
section: { name: t("分区"), match: [{ rank: 40, tag: "section" }], chapter: true, fixed: true, handle: "bar" },
|
|
22
|
+
section: { name: t("分区"), icon: SECTION_ICON, match: [{ rank: 40, tag: "section" }], chapter: true, fixed: true, handle: "bar" },
|
|
22
23
|
},
|
|
23
24
|
boxes: {
|
|
24
25
|
section: { role: "flow", name: t("分区"), groups: true },
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { escapeText } from "../../shared/escape.mjs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How a box of blocks set apart (a highlight block, a callout: `match` its elements) is copied, one
|
|
5
|
+
* rule for both, their clipboard's hooks (registry.mjs `clipboard`) for the block of `type`: its
|
|
6
|
+
* blocks; one with words straight in it (an Agent's, a callout written the old way), a paragraph of
|
|
7
|
+
* what it says. A list with its class is a list, and a text block of a type of its own that type.
|
|
8
|
+
*/
|
|
9
|
+
export const setApart = (type, match) => ({
|
|
10
|
+
describe(node, { isHost, holding, colorOf, copiedType, serializeInner, plain }) {
|
|
11
|
+
if (!node.matches(match) || node.matches("ul, ol") || (isHost(node) && copiedType(node))) return undefined;
|
|
12
|
+
const straight = [...node.childNodes].some((child) => child.nodeType === 3 && child.data.trim());
|
|
13
|
+
const words = isHost(node) ? serializeInner(node) : straight ? escapeText(plain(node)) : null;
|
|
14
|
+
const blocks = words === null ? holding(node) : [{ type: "paragraph", html: words }];
|
|
15
|
+
const color = colorOf(node);
|
|
16
|
+
return blocks ? { type, blocks, ...(color ? { color } : {}) } : null;
|
|
17
|
+
},
|
|
18
|
+
endsIn(unit, { blocksIn, boxesOf, colorOf }) {
|
|
19
|
+
if (!unit.matches(match)) return undefined;
|
|
20
|
+
const color = colorOf(unit);
|
|
21
|
+
return [{ type, blocks: blocksIn(boxesOf(unit)), ...(color ? { color } : {}) }];
|
|
22
|
+
},
|
|
23
|
+
check: (block, { container }) => container(block),
|
|
24
|
+
});
|
|
@@ -115,9 +115,11 @@ export const CELL_BOLD = CELL_BOLD_CLASS;
|
|
|
115
115
|
export const CELL_LOOKS = [...BLOCK_COLORS, ...CELL_ALIGNS.map(([name]) => name), ...CELL_VALIGNS.map(([name]) => name), CELL_BOLD];
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
|
-
* The look a cell takes when it becomes a header cell (a th
|
|
119
|
-
*
|
|
120
|
-
* and the gray fill unless it has a color of its own.
|
|
118
|
+
* The look a cell takes when it becomes a header row's cell (a th that is no row's header: 标题行's
|
|
119
|
+
* toggle, a row moved there, a cell made there: page.mjs) and loses when it stops being one: bold,
|
|
120
|
+
* and the gray fill unless it has a color of its own. A header column's cell (th scope="row") has
|
|
121
|
+
* none: 标题列 only makes the first column stay when the frame scrolls sideways (the user's,
|
|
122
|
+
* 2026-11-06). Nothing else of the kit's sets a header apart.
|
|
121
123
|
*/
|
|
122
124
|
export const HEADER_LOOK = [CELL_BOLD, "doc-highlight-gray"];
|
|
123
125
|
|
|
@@ -35,7 +35,7 @@ export function sharedWidths(wrap, count, share = 1) {
|
|
|
35
35
|
* `numbers` is false (识别数字列: index.mjs NUMBERS). `looks`, `widths` and `spans` as tableData
|
|
36
36
|
* describes them: each cell's look classes, each column's width, each cell's [rowspan, colspan]
|
|
37
37
|
* (a cell merged makes a row hold fewer cells); where `looks` is given the cells have just those,
|
|
38
|
-
* where not a header cell takes the header's look. `chart`: the key a chart drawn from it reads it
|
|
38
|
+
* where not a header row's cell takes the header's look (a header column's none). `chart`: the key a chart drawn from it reads it
|
|
39
39
|
* by (its frame's data-doc-chart-source), when it has one.
|
|
40
40
|
*/
|
|
41
41
|
export function newTable(doc, { rows, header = false, column = false, numbers = true, looks, widths, spans, chart }) {
|
|
@@ -55,7 +55,7 @@ export function newTable(doc, { rows, header = false, column = false, numbers =
|
|
|
55
55
|
const first = at[r][index] === 0;
|
|
56
56
|
const cell = newCell(doc, head || (column && first) ? "th" : "td", !head && column && first ? "row" : null);
|
|
57
57
|
if (looks) cell.classList.add(...(looks[r][index] ?? "").split(" ").filter(Boolean));
|
|
58
|
-
else if (
|
|
58
|
+
else if (head) headerLook(cell, true);
|
|
59
59
|
const [down, across] = spans?.[r]?.[index] ?? [1, 1];
|
|
60
60
|
setSpan(cell, down, across);
|
|
61
61
|
if (Array.isArray(html)) cell.append(...html);
|
|
@@ -139,7 +139,7 @@ export function build({ doc, block, inline }) {
|
|
|
139
139
|
/**
|
|
140
140
|
* A table standing for an empty block (its type's `create`): three columns, a header row and two rows
|
|
141
141
|
* (the plan's D6), the caret in its first cell (notion-lite's). It is two fifths as wide as the text
|
|
142
|
-
* it stands in, its columns equal and fixed (typing does not move them);
|
|
142
|
+
* it stands in, its columns equal and fixed (typing does not move them); 自动调整列宽 is the reader's
|
|
143
143
|
* to choose (a pasted table has the kit's widths). Its numeric columns are not read (识别数字列 off):
|
|
144
144
|
* typing numbers does not center or sort them.
|
|
145
145
|
*/
|
|
@@ -164,8 +164,8 @@ export function create({ tables }) {
|
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* A new cell: a text block made on the page (td, or th with its scope). A header cell made in a
|
|
167
|
-
* header row
|
|
168
|
-
*
|
|
167
|
+
* header row takes the look of the header cell beside it (`model`: lookLike), one of a new table
|
|
168
|
+
* the header's (newTable); a header column's cell is made plain.
|
|
169
169
|
*/
|
|
170
170
|
export function newCell(doc, tag = "td", scope = null, model = null) {
|
|
171
171
|
const cell = doc.createElement(tag);
|
|
@@ -175,9 +175,15 @@ export function newCell(doc, tag = "td", scope = null, model = null) {
|
|
|
175
175
|
return cell;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
178
|
+
// Whether a cell of `tag` and `scope` wears the header row's look (index.mjs HEADER_LOOK): a th that is
|
|
179
|
+
// no row's header. A header column's th (scope="row") has no look of its own: 标题列 only makes the
|
|
180
|
+
// column stay at the left when the frame scrolls sideways (the user's, 2026-11-06).
|
|
181
|
+
const wearsHeaderLook = (tag, scope) => tag === "th" && (scope ?? "").trim().toLowerCase() !== "row";
|
|
182
|
+
|
|
183
|
+
// A cell that becomes a header row's cell (wearsHeaderLook) takes the header's look (index.mjs
|
|
184
|
+
// HEADER_LOOK: bold, and the gray fill unless it has a color of its own); one that stops being one
|
|
185
|
+
// loses it; a header column's cell has none (标题列 only sticks). These are looks as any other: the
|
|
186
|
+
// reader may change them.
|
|
181
187
|
function headerLook(cell, on) {
|
|
182
188
|
const [bold, fill] = HEADER_LOOK;
|
|
183
189
|
if (!on) return cell.classList.remove(bold, fill);
|
|
@@ -185,7 +191,7 @@ function headerLook(cell, on) {
|
|
|
185
191
|
if (!BLOCK_COLORS.some((name) => cell.classList.contains(name))) cell.classList.add(fill);
|
|
186
192
|
}
|
|
187
193
|
|
|
188
|
-
// A header cell made beside another of its header row
|
|
194
|
+
// A header cell made beside another of its header row: its color and bold as that one's
|
|
189
195
|
// (a header the reader made plain, or the Agent wrote plain, stays so).
|
|
190
196
|
function lookLike(cell, model) {
|
|
191
197
|
const [bold] = HEADER_LOOK;
|
|
@@ -253,10 +259,10 @@ export function columnRange(unit, from, to = from) {
|
|
|
253
259
|
}
|
|
254
260
|
|
|
255
261
|
// The cell a new row has in column `c`: as the row it is made beside has it there (a header
|
|
256
|
-
// column's th), never a header row's th.
|
|
262
|
+
// column's th, plain), never a header row's th.
|
|
257
263
|
const cellLike = (doc, slots, r, c) => {
|
|
258
264
|
const model = r === null ? null : slots.matrix[r]?.[c];
|
|
259
|
-
return model?.localName === "th" && model.getAttribute("scope") === "row" && c === 0 ? newCell(doc, "th", "row"
|
|
265
|
+
return model?.localName === "th" && model.getAttribute("scope") === "row" && c === 0 ? newCell(doc, "th", "row") : newCell(doc);
|
|
260
266
|
};
|
|
261
267
|
|
|
262
268
|
/** A new row at `at` (0 … rows): in the tbody (in the thead only between its rows). Returns it. */
|
|
@@ -304,7 +310,7 @@ export function insertColumn(unit, at) {
|
|
|
304
310
|
const head = row.parentElement.localName === "thead";
|
|
305
311
|
const first = slots.matrix[r][0];
|
|
306
312
|
const beside = slots.matrix[r][Math.max(0, at - 1)];
|
|
307
|
-
const cell = head ? newCell(doc, "th", null, beside) : at === 0 && headerColumn ? newCell(doc, "th", "row"
|
|
313
|
+
const cell = head ? newCell(doc, "th", null, beside) : at === 0 && headerColumn ? newCell(doc, "th", "row") : newCell(doc);
|
|
308
314
|
row.insertBefore(cell, cellFrom(slots, row, at));
|
|
309
315
|
made.push(cell);
|
|
310
316
|
// A header column stays the first: the cell that was first is a plain one now.
|
|
@@ -464,7 +470,7 @@ export function labelColumn(unit) {
|
|
|
464
470
|
|
|
465
471
|
/**
|
|
466
472
|
* 一键优化 (the table's block menu; a table pasted from elsewhere comes in so): the kit's column
|
|
467
|
-
* widths (
|
|
473
|
+
* widths (自动调整列宽: many columns scroll sideways in the frame), a header row, the first column a
|
|
468
474
|
* header column when its words are the rows' names, its numeric columns read (识别数字列: centered,
|
|
469
475
|
* sorted by their header), and a frame shown whole (显示全部行) that is taller than the kit's scroll
|
|
470
476
|
* height scrolling again (one that scrolls already stays as it is). Inside one undo step (the
|
|
@@ -491,7 +497,7 @@ export function optimizeTable(unit) {
|
|
|
491
497
|
return changed;
|
|
492
498
|
}
|
|
493
499
|
|
|
494
|
-
/** The header column on (each body row's cell in the first column th scope="row") or off (td). */
|
|
500
|
+
/** The header column on (each body row's cell in the first column th scope="row") or off (td); its cells' looks untouched either way (the header column only sticks). */
|
|
495
501
|
export function setHeaderColumn(unit, on) {
|
|
496
502
|
const { rows, body, headerColumn, slots } = tableState(unit);
|
|
497
503
|
if (on === headerColumn) return false;
|
|
@@ -596,7 +602,7 @@ export function splitCell(unit, cell) {
|
|
|
596
602
|
const before = cellFrom(slots, rows[r], place.c + place.cols);
|
|
597
603
|
for (let c = place.c; c < place.c + place.cols; c++) {
|
|
598
604
|
if (r === place.r && c === place.c) continue;
|
|
599
|
-
const piece = rowHeader ? (c === 0 ? newCell(doc, "th", "row"
|
|
605
|
+
const piece = rowHeader ? (c === 0 ? newCell(doc, "th", "row") : newCell(doc)) : newCell(doc, cell.localName, null, cell);
|
|
600
606
|
rows[r].insertBefore(piece, before);
|
|
601
607
|
made.push(piece);
|
|
602
608
|
}
|
|
@@ -647,11 +653,16 @@ function keepWidths(unit, mutate) {
|
|
|
647
653
|
/**
|
|
648
654
|
* A cell as a td or th (`scope`: a th's, null for none): a new element of that tag in its place,
|
|
649
655
|
* taking its attributes, a copy of its content (the old cell keeps its own, for undo to put back)
|
|
650
|
-
* and its identity (it stays the same cell to the commits); the header's look taken or lost
|
|
656
|
+
* and its identity (it stays the same cell to the commits); the header row's look taken or lost when
|
|
657
|
+
* the cell comes into or leaves the kind that wears it (wearsHeaderLook): a header column's th wears
|
|
658
|
+
* none, and a cell switched between td and it keeps its looks. A th only given another scope stays
|
|
659
|
+
* itself unless its look changes (a new element then too, so undo puts its classes back).
|
|
651
660
|
*/
|
|
652
661
|
export function retagCell(cell, tag, scope = null) {
|
|
653
662
|
if (!cell) return cell;
|
|
654
|
-
|
|
663
|
+
const look = wearsHeaderLook(tag, tag === "th" ? scope : null);
|
|
664
|
+
const changes = wearsHeaderLook(cell.localName, cell.getAttribute("scope")) !== look;
|
|
665
|
+
if (cell.localName === tag && !changes) {
|
|
655
666
|
if (tag === "th" && scope) cell.setAttribute("scope", scope);
|
|
656
667
|
else cell.removeAttribute("scope");
|
|
657
668
|
return cell;
|
|
@@ -659,7 +670,7 @@ export function retagCell(cell, tag, scope = null) {
|
|
|
659
670
|
const next = cell.ownerDocument.createElement(tag);
|
|
660
671
|
for (const { name, value } of [...cell.attributes]) if (name !== "scope") next.setAttribute(name, value);
|
|
661
672
|
if (tag === "th" && scope) next.setAttribute("scope", scope);
|
|
662
|
-
headerLook(next,
|
|
673
|
+
if (changes) headerLook(next, look);
|
|
663
674
|
next.append(...[...cell.childNodes].map((node) => node.cloneNode(true)));
|
|
664
675
|
cell.replaceWith(next);
|
|
665
676
|
return next;
|
|
@@ -26,9 +26,10 @@ const unitOf = (node) => {
|
|
|
26
26
|
/**
|
|
27
27
|
* The text of `elements` (in page order) as the server reads a block, a line between them: { text,
|
|
28
28
|
* at }, `at[i]` where character `i` comes from ({ node, offset } in a text node, { element } for a
|
|
29
|
-
* formula's TeX, null for a line's end).
|
|
29
|
+
* formula's TeX, null for a line's end). `skip(child)`: an element of theirs read past (a list item's
|
|
30
|
+
* blocks, when its own words alone are read: changes/).
|
|
30
31
|
*/
|
|
31
|
-
export function readText(elements) {
|
|
32
|
+
export function readText(elements, { skip = null } = {}) {
|
|
32
33
|
let text = "";
|
|
33
34
|
const at = [];
|
|
34
35
|
const put = (char, place) => { text += char; at.push(place); };
|
|
@@ -59,7 +60,7 @@ export function readText(elements) {
|
|
|
59
60
|
space({ element: child });
|
|
60
61
|
continue;
|
|
61
62
|
}
|
|
62
|
-
if (child.matches(SKIP)) continue;
|
|
63
|
+
if (child.matches(SKIP) || skip?.(child)) continue;
|
|
63
64
|
const words = isMention(child) ? sourceWords(child) : null;
|
|
64
65
|
if (words !== null) {
|
|
65
66
|
for (const char of words) (/\s/.test(char) ? space : (place) => put(char, place))({ element: child });
|