yamlover 0.3.49 → 0.3.51

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.
Files changed (38) hide show
  1. package/README.md +6 -6
  2. package/bin/ga4.js +14 -1
  3. package/dist/agent-docs/AGENTS.md +10 -10
  4. package/dist/builtin-taxonomy/$defs/.yo/meta.yo +18 -23
  5. package/dist/builtin-taxonomy/$defs/annotation +6 -6
  6. package/dist/builtin-taxonomy/$defs/board +4 -4
  7. package/dist/builtin-taxonomy/$defs/bullets +2 -2
  8. package/dist/builtin-taxonomy/$defs/chapter +6 -7
  9. package/dist/builtin-taxonomy/$defs/chunk +4 -3
  10. package/dist/builtin-taxonomy/$defs/config +5 -5
  11. package/dist/builtin-taxonomy/$defs/fragment +2 -2
  12. package/dist/builtin-taxonomy/$defs/numbered +2 -2
  13. package/dist/builtin-taxonomy/$defs/{tag → onto} +6 -6
  14. package/dist/builtin-taxonomy/$defs/table +13 -12
  15. package/dist/builtin-taxonomy/$defs/task +6 -6
  16. package/dist/builtin-taxonomy/$defs/workflow +4 -4
  17. package/dist/builtin-taxonomy/ontos/.yo/body.yo +46 -0
  18. package/dist/client/assets/{decoded-D_YQdg1-.js → decoded-5u9KK4Nb.js} +1 -1
  19. package/dist/client/assets/{djvu-Di4fPA-J.js → djvu-CvRKxWcX.js} +1 -1
  20. package/dist/client/assets/{docx-BSduN32X.js → docx-CFqmrRMY.js} +1 -1
  21. package/dist/client/assets/{heic-DOAG7EsW.js → heic-P0RPecFK.js} +1 -1
  22. package/dist/client/assets/{imagemap-B8RthxNE.js → imagemap-BCrt0kPn.js} +1 -1
  23. package/dist/client/assets/index-_gAtxDG4.css +1 -0
  24. package/dist/client/assets/index-l1SxxFJR.js +754 -0
  25. package/dist/client/assets/{map-Cf7ar1_U.js → map-ClMfiQr8.js} +1 -1
  26. package/dist/client/assets/{openable-CCBlc-Ws.js → openable-9ABNW3A9.js} +1 -1
  27. package/dist/client/assets/{paged-bLurvatj.js → paged-UVifI3SC.js} +1 -1
  28. package/dist/client/assets/{pdf-D1ox8M9A.js → pdf-BGgu5LFZ.js} +1 -1
  29. package/dist/client/assets/{psd-AT50x-YR.js → psd-D15IXPVu.js} +1 -1
  30. package/dist/client/assets/{spreadsheet-DeQh5CNF.js → spreadsheet-CeOcWWb2.js} +1 -1
  31. package/dist/client/assets/{tiff-B3-awhzQ.js → tiff-pZPBtPPg.js} +1 -1
  32. package/dist/client/assets/{xyflow-DuQ4jjaq.js → xyflow-uN1JIC1A.js} +1 -1
  33. package/dist/client/index.html +2 -2
  34. package/dist/server.js +1420 -425
  35. package/package.json +1 -1
  36. package/dist/builtin-taxonomy/tags/.yo/body.yo +0 -46
  37. package/dist/client/assets/index-Bf2L7I9e.js +0 -752
  38. package/dist/client/assets/index-N41EyNG2.css +0 -1
package/README.md CHANGED
@@ -7,8 +7,8 @@ serves a browser UI (tree, editor, renderers, live queries) over a yamlover
7
7
  directory, and an HTTP API an agent can drive directly.
8
8
 
9
9
  - **Repo:** https://github.com/dims12/yamlover
10
- - **Live demo** (no install): https://yamlover.inthemoon.net/
11
- - **Docs** (written in yamlover, click-through): https://yamlover.inthemoon.net/docs
10
+ - **Live demo** (no install): [yamlover.inthemoon.net](https://yamlover.inthemoon.net/?utm_source=npm&utm_medium=readme&utm_content=demo)
11
+ - **Docs** (written in yamlover, click-through): [yamlover.inthemoon.net/docs](https://yamlover.inthemoon.net/docs?utm_source=npm&utm_medium=readme&utm_content=docs)
12
12
 
13
13
  ```console
14
14
  $ npx yamlover [ROOT] [--port N] [--headless] [--host ADDR] [--base-path PREFIX] [--no-gitignore] [--prod] [--read-only]
@@ -92,9 +92,9 @@ deep link expands the TOC along the path and selects (and scrolls to) the target
92
92
  splitting its path at the page boundary and replacing that `/` with `#`: for a full
93
93
  path `a/b/c/d` whose served page is `a/b`, the *scrollable* URL is `a/b#c/d` — the
94
94
  page loads `a/b` and scrolls to the `c/d` node within it. A **fragment** (a tagged
95
- region — see `docs/server/annotations`) is one instance: a region of `…/IMG.jpg` lives at
96
- `…/IMG.jpg/yamlover-fragments/<slug>`, so its scrollable URL is
97
- `…/IMG.jpg#yamlover-fragments/<slug>` — opening it (or clicking the region in the
95
+ region — see `docs/annotations`) is one instance: a region of `…/IMG.jpg` lives at
96
+ `…/IMG.jpg/yo/fragments/<slug>`, so its scrollable URL is
97
+ `…/IMG.jpg#yo/fragments/<slug>` — opening it (or clicking the region in the
98
98
  fragments panel) scrolls/pans to **and briefly flashes** the region.
99
99
 
100
100
  ## How it works
@@ -239,7 +239,7 @@ Registered today (a representative slice — the registry is the source of truth
239
239
  | renderer | matches (format) | draws with |
240
240
  |----------|------------------|------------|
241
241
  | `chapter` | `x-yamlover-chapter` | a positional body: numbered chunks + subchapter links |
242
- | `tag` / `board` | `x-yamlover-tag` / `x-yamlover-board` | tag-hierarchy diagram / board (handled outside the specificity loop) |
242
+ | `tag` / `board` | `x-yamlover-onto` / `x-yamlover-board` | tag-hierarchy diagram / board (handled outside the specificity loop) |
243
243
  | `task` | `x-yamlover-task` | task view |
244
244
  | `table` | `x-yamlover-table` | a grid (`docs/documents/marklower`): rows/header/caption from the omni entries, merged cells (`colSpan`/`rowSpan`) from resolved relative-index `*` pointers, nested tables inline, marklower cells; prose cells edit in place under the lock |
245
245
  | `marklower` | `text/marklower` (a chapter's prose chunks, by schema propagation) | its own inline grammar (`docs/documents/marklower`): emphasis, `` `code` ``, `$$math$$` via KaTeX, links, and `*[…](…)` media embeds |
package/bin/ga4.js CHANGED
@@ -44,6 +44,19 @@ export function ga4Tag({ measurementId, basePath = "", pagePath = "", collapse =
44
44
  `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}window.gtag=gtag;` +
45
45
  `gtag("js",new Date());` +
46
46
  // The reported path. Query and fragment are dropped wholesale: both carry data paths.
47
+ // Which also drops the `utm_` keys a referral arrives with — and gtag reads campaign
48
+ // attribution off `page_location`, so without the lines below every tagged link (the
49
+ // README's, say) would report as direct traffic. An explicit campaign field overrides
50
+ // its `utm_` twin, so the five standard keys are read once at load and passed by name.
51
+ // By name, and only those five: the allowlist is what keeps the redaction above true.
52
+ //
53
+ // Not on a collapsed instance, though. There the promise is stronger — NOTHING from this
54
+ // URL is forwarded — and a hand-written `?utm_source=<the hash>` would otherwise walk
55
+ // straight through the allowlist. A demo is reached through the registration page anyway,
56
+ // which is a plain document with a stock tag that reads the query itself.
57
+ `var CAMPAIGN={};if(!COLLAPSE){var Q=new URLSearchParams(location.search);` +
58
+ `["source","medium","campaign","term","content"].forEach(function(k){` +
59
+ `var v=Q.get("utm_"+k);if(v)CAMPAIGN["campaign_"+k]=v})}` +
47
60
  `function at(){if(COLLAPSE)return PUB+"/";var p=location.pathname;` +
48
61
  `if(BASE&&p.indexOf(BASE)===0)p=p.slice(BASE.length)||"/";return PUB+p}` +
49
62
  // Stamped as GLOBAL parameters rather than per-event: the tag's own enhanced-measurement
@@ -51,7 +64,7 @@ export function ga4Tag({ measurementId, basePath = "", pagePath = "", collapse =
51
64
  // report location.href, routing around the redaction above.
52
65
  `var last="";function stamp(){var p=at();last=p;` +
53
66
  `gtag("set",{page_path:p,page_location:location.origin+p,page_title:COLLAPSE?"yamlover demo":document.title})}` +
54
- `stamp();gtag("config",ID,{send_page_view:false});gtag("event","page_view");` +
67
+ `stamp();gtag("config",ID,Object.assign({send_page_view:false},CAMPAIGN));gtag("event","page_view");` +
55
68
  // The SPA routes on the JSON path with no document load, so page_view is re-sent by hand.
56
69
  // A collapsed instance reports one path, so every navigation inside it is a repeat — the
57
70
  // `last` guard keeps it to a single page_view instead of one per click.
@@ -81,13 +81,13 @@ parses as a path: `*/pets` is a dangling reference to the literal key "/pets". A
81
81
  current: object: path # bare — current scope (siblings)
82
82
  : document: rooted: path # : — this document's root
83
83
  :: project: rooted: path # :: — this project's root
84
- ::: yamlover.inthemoon.net: $defs: tag # ::: — the world (an external project)
84
+ ::: yamlover.inthemoon.net: $defs: onto # ::: — the world (an external project)
85
85
  ```
86
86
 
87
87
  - `*pets: 1` — bare: a **sibling** named `pets`, position 1.
88
88
  - `*: pets: 0` — `:` document root.
89
- - `*:: tags: genre` — `::` this project's root.
90
- - `*::: host.example: $defs: tag` — `:::` a world/external reference.
89
+ - `*:: ontos: genre` — `::` this project's root.
90
+ - `*::: host.example: $defs: onto` — `:::` a world/external reference.
91
91
 
92
92
  ### The bare-token rule — what a portion means
93
93
 
@@ -184,7 +184,7 @@ longer parses.
184
184
  mychapter: !!<*:: yamlover: $defs: chapter>
185
185
  ```
186
186
  Reusable schemas live at the project root under **`$defs`** (e.g. `$defs: chapter`,
187
- `$defs: tag`, `$defs: annotation`, `$defs: fragment`). They are referenced project-scoped
187
+ `$defs: onto`, `$defs: annotation`, `$defs: fragment`). They are referenced project-scoped
188
188
  (`*:: $defs: name`) or via the self-import (`*:: yamlover: $defs: name` — synonyms inside this
189
189
  project). Schemas are **metadata** (typing/format/presentation), not data storage.
190
190
 
@@ -237,22 +237,22 @@ see §10).
237
237
 
238
238
  The human marks up documents in the UI. These live **on the target node**, not in side files:
239
239
 
240
- - **`yamlover-fragments`** — a mapping of slug → selector (a text span, image/PDF rectangle, or
240
+ - **`yo: fragments:`** — a mapping of slug → selector (a text span, image/PDF rectangle, or
241
241
  map box) identifying a region within the node.
242
242
  - **`yamlover-annotations`** — a sequence; each element applies a tag to the node (or a
243
243
  fragment). An element is either a bare **tag pointer** or an object with a `tag:` field plus
244
244
  parameters:
245
245
  ```yamlover
246
246
  yamlover-annotations:
247
- - *:: tags: genre: brevity # parameterless
248
- - {description: 'A math block', tag: *:: tags: topic: math} # parametrized
247
+ - *:: ontos: genre: brevity # parameterless
248
+ - {description: 'A math block', tag: *:: ontos: topic: math} # parametrized
249
249
  ```
250
250
 
251
251
  (A flow scalar carrying a SPACE must be quoted — an unquoted `A math block` inside `{…}` is a
252
252
  parse error.)
253
253
 
254
254
  Prefer letting the human create these through the UI. If you must touch them by hand, keep the
255
- exact key names (`yamlover-fragments`, `yamlover-annotations`) and the tag-pointer form, and do
255
+ exact key names (`yo: fragments:`, `yamlover-annotations`) and the tag-pointer form, and do
256
256
  not renumber or reorder fragment slugs.
257
257
 
258
258
  ---
@@ -313,8 +313,8 @@ sibling: *pets: 1 # current scope, by position (bare digits =
313
313
  rooted: *: humans: 0: name # document root → position 0 → key name
314
314
  strkey: *: counts: '1' # QUOTED digits = the numeric STRING key
315
315
  nullkey: *: doc: ~ # the null key
316
- projscope: *:: tags: genre # this project's root
317
- world: *::: host.example: $defs: tag
316
+ projscope: *:: ontos: genre # this project's root
317
+ world: *::: host.example: $defs: onto
318
318
 
319
319
  # anchors (push) — "I also live there"; real keys; unambiguous only
320
320
  here: &: chief # also at document-root key `chief`
@@ -1,34 +1,29 @@
1
- properties:
1
+ # $defs/.yo/meta.yo — every definition file is a yamlover/meta document: the CONCRETE names
2
+ # the decoding (parse the text as a schema doc); the parsed type follows from it (docs/meta —
3
+ # the concrete/type/format split; the old spelling `type: string` + `format: yamlover/meta`
4
+ # stays readable but is not authored anymore).
5
+ members:
2
6
  chapter:
3
- type: string
4
- format: yamlover/meta
7
+ concrete: yamlover/meta
5
8
  chunk:
6
- type: string
7
- format: yamlover/meta
9
+ concrete: yamlover/meta
8
10
  tag:
9
- type: string
10
- format: yamlover/meta
11
+ concrete: yamlover/meta
11
12
  annotation:
12
- type: string
13
- format: yamlover/meta
13
+ concrete: yamlover/meta
14
14
  fragment:
15
- type: string
16
- format: yamlover/meta
15
+ concrete: yamlover/meta
17
16
  task:
18
- type: string
19
- format: yamlover/meta
17
+ concrete: yamlover/meta
20
18
  workflow:
21
- type: string
22
- format: yamlover/meta
19
+ concrete: yamlover/meta
23
20
  board:
24
- type: string
25
- format: yamlover/meta
21
+ concrete: yamlover/meta
26
22
  table:
27
- type: string
28
- format: yamlover/meta
23
+ concrete: yamlover/meta
29
24
  bullets:
30
- type: string
31
- format: yamlover/meta
25
+ concrete: yamlover/meta
32
26
  numbered:
33
- type: string
34
- format: yamlover/meta
27
+ concrete: yamlover/meta
28
+ config:
29
+ concrete: yamlover/meta
@@ -1,7 +1,7 @@
1
1
  # $defs/annotation — ONE TAG APPLICATION on the host node (a whole document, or a fragment within
2
2
  # it). It lives as an element of the host's `yamlover-annotations` array. Two forms:
3
- # • parameterless — a bare tag pointer (`- *::tags:…`): the host simply HAS this tag.
4
- # • parametrized — an object carrying `tag: *::tags:…` plus parameters (e.g. `description`).
3
+ # • parameterless — a bare tag pointer (`- *::ontos:…`): the host simply HAS this tag.
4
+ # • parametrized — an object carrying `tag: *::ontos:…` plus parameters (e.g. `description`).
5
5
  # The applied tag drives the display color (its `color`, else a name-derived hue). The region, if
6
6
  # any, is the host fragment's selector — an annotation carries no selector of its own. This
7
7
  # replaces the old separate-file annotation (a `target` pointer + `selector` + reverse tag
@@ -9,10 +9,10 @@
9
9
  # !!<*::yamlover/$defs/annotation> is optional, for the parametrized object form.
10
10
  type: variant
11
11
  format: x-yamlover-annotation
12
- value: *:: yamlover: $defs: tag # the parameterless case: the self-value IS a tag (by ref)
13
- properties:
14
- tag: *:: yamlover: $defs: tag # the parametrized case: the applied tag, by pointer
12
+ value: *:: yamlover: $defs: onto # the parameterless case: the self-value IS a tag (by ref)
13
+ members:
14
+ tag: *:: yamlover: $defs: onto # the parametrized case: the applied tag, by pointer
15
15
  description:
16
16
  type: string
17
17
  format: text/marklower
18
- additionalProperties: true # any other field is a free-form parameter
18
+ others: true # any other field is a free-form parameter
@@ -6,10 +6,10 @@
6
6
  # Spec: ../TICKETS.md §3.
7
7
  type: object
8
8
  format: x-yamlover-board
9
- properties:
10
- workflow: *:: yamlover: $defs: tag # ref → the workflow that SEEDS the default lanes
9
+ members:
10
+ workflow: *:: yamlover: $defs: onto # ref → the workflow that SEEDS the default lanes
11
11
  lanes: # optional saved lanes (the explorer board view's config):
12
12
  type: array # a sequence of lanes, each a list of tag refs — one tag
13
- items: # = a plain lane, several = per-tag SUBLANES stacked
13
+ others: # = a plain lane, several = per-tag SUBLANES stacked
14
14
  type: array # vertically. Edited via the lane headers, persisted by
15
- items: *:: yamlover: $defs: tag # POST /api/board.
15
+ others: *:: yamlover: $defs: onto # POST /api/board.
@@ -2,11 +2,11 @@
2
2
  # keyless entries are the items. An item is marklower prose (a chunk) or — when it is an
3
3
  # UNTAGGED container — a nested bullets list: unlike table's two-level budget, the list
4
4
  # schema applies at ANY depth, until an explicit !!<…> tag switches to something else.
5
- # A titled list is a chapter holding a list — no keyed properties here on purpose.
5
+ # A titled list is a chapter holding a list — no keyed member clauses here on purpose.
6
6
  # Attach with !!<*yamlover: $defs: bullets>.
7
7
  # No explicit `format:` — `type: variant` derives x-yamlover-bullets. Spec: docs/documents/marklower.
8
8
  type: variant
9
- items:
9
+ others:
10
10
  anyOf:
11
11
  - *:: yamlover: $defs: bullets # an untagged container item = a nested sublist, SAME kind
12
12
  - *:: yamlover: $defs: chunk # a list item — marklower prose
@@ -8,21 +8,20 @@
8
8
  # tag !!<*yamlover/$defs/chapter>. Spec: docs/documents/chapter, docs/meta.
9
9
  #
10
10
  # `type: variant` is the omni node: a scalar self-value (the title, given as `value:`) AND
11
- # keyed fields (description) AND positional elements (the body) at once. The body element type
12
- # is a union a chapter OR a chunk; the two are told apart structurally (a chapter is a
13
- # container, a chunk is a leaf). A BARE SCALAR body element is therefore both "a chunk" and
11
+ # keyed fields (description) AND positional elements (the body) at once. ONE omni `members:`
12
+ # clause describes the members (here: the keyed `description`); the sibling `others:` covers
13
+ # every member no clause matched the BODY, a union routed structurally (a container element
14
+ # is a chapter, a leaf is a chunk). A BARE SCALAR body element is therefore both "a chunk" and
14
15
  # "a title-only subchapter" — the same thing, by design (docs/documents/chapter).
15
- # NOTE: `value` (scalar) + `properties` (keyed) + `items` (ordinal) is the JSON-Schema encoding
16
- # of an omni node's facets; docs/meta proposes a native `elements`/`additionalElements`.
17
16
  type: variant
18
17
  value: # the self-value — the chapter's TITLE
19
18
  type: string
20
19
  format: text/marklower
21
- properties:
20
+ members:
22
21
  description: # optional subtitle / heading annotation — stays keyed
23
22
  type: string
24
23
  format: text/marklower
25
- items: # the body — a positional sequence, read top to bottom
24
+ others: # the body — every unmatched member, read top to bottom
26
25
  anyOf:
27
26
  - *:: yamlover: $defs: chapter # a nested subchapter (a container) — the recursion
28
27
  - *:: yamlover: $defs: table # a table — enters only by its EXPLICIT tag (docs/documents/marklower)
@@ -1,8 +1,9 @@
1
1
  # $defs/chunk — one renderable content block, a leaf of a chapter's positional body.
2
2
  #
3
- # A chunk is a typed value; its (type, format) selects the renderer. The default is
4
- # markdown prose; a chunk overrides type/format/concrete to be a diagram, image, LaTeX,
5
- # CSV, a file pointer, etc. `binary` covers image/pdf/… chunks (a `*` pointer to a file).
3
+ # A chunk is a typed value; its (type, format) selects the renderer the format CONSTRAINS
4
+ # the value, and the concrete (declared in meta, docs/meta) says how its bytes decode. The
5
+ # default is markdown prose; a chunk overrides them to be a diagram, image, LaTeX, CSV, a
6
+ # file pointer, etc. `binary` covers image/pdf/… chunks (a `*` pointer to a file).
6
7
  # Spec: docs/documents/chapter.
7
8
  type: [string, binary]
8
9
  format: text/marklower
@@ -6,19 +6,19 @@
6
6
  # !!<*yamlover:$defs:config>.
7
7
  type: object
8
8
  format: x-yamlover-config
9
- properties:
9
+ members:
10
10
  uri: # this project's identity (IMPORTS.md §1) — an authority,
11
11
  type: string # authored as `::: host`; identity, not transport
12
12
  exports: # the paths exported to importers (IMPORTS.md §2):
13
13
  type: array # a list of pointer/query texts
14
- items:
14
+ others:
15
15
  type: string
16
- annotations: *:: yamlover: $defs: tag # where new annotations are created (`*:: annotations`)
17
- tags: *:: yamlover: $defs: tag # where new tags are created (`*:: tags`)
16
+ annotations: *:: yamlover: $defs: onto # where new annotations are created (`*:: annotations`)
17
+ ontos: *:: yamlover: $defs: onto # where new tags are created (`*:: tags`)
18
18
  sidecars: # where derived sidecar blobs go: per-directory | project
19
19
  type: string
20
20
  width: # reading width (ch) for rendered prose (markdown/asciidoc/
21
21
  type: integer # chapter); the browser settings layer overrides it per device
22
22
  theme: # ui palette: dark | light; the browser settings layer
23
23
  type: string # overrides it per device
24
- annotation-tag: *:: yamlover: $defs: tag # the last-used annotation tag (the picker default)
24
+ annotation-tag: *:: yamlover: $defs: onto # the last-used annotation tag (the picker default)
@@ -7,7 +7,7 @@
7
7
  # its own `yamlover-annotations`. Attach with the tag !!<*::yamlover/$defs/fragment>.
8
8
  type: object
9
9
  format: x-yamlover-fragment
10
- properties:
10
+ members:
11
11
  type:
12
12
  type: string
13
13
  description: The locator kind — text | rect | pdf | djvu | map
@@ -41,4 +41,4 @@ properties:
41
41
  type: string
42
42
  yamlover-annotations:
43
43
  type: array
44
- items: *:: yamlover: $defs: annotation
44
+ others: *:: yamlover: $defs: annotation
@@ -2,11 +2,11 @@
2
2
  # keyless entries are the items. An item is marklower prose (a chunk) or — when it is an
3
3
  # UNTAGGED container — a nested numbered list: unlike table's two-level budget, the list
4
4
  # schema applies at ANY depth, until an explicit !!<…> tag switches to something else.
5
- # A titled list is a chapter holding a list — no keyed properties here on purpose.
5
+ # A titled list is a chapter holding a list — no keyed member clauses here on purpose.
6
6
  # Attach with !!<*yamlover: $defs: numbered>.
7
7
  # No explicit `format:` — `type: variant` derives x-yamlover-numbered. Spec: docs/documents/marklower.
8
8
  type: variant
9
- items:
9
+ others:
10
10
  anyOf:
11
11
  - *:: yamlover: $defs: numbered # an untagged container item = a nested sublist, SAME kind
12
12
  - *:: yamlover: $defs: chunk # a list item — marklower prose
@@ -1,17 +1,17 @@
1
- # $defs/tag — a node in a tag taxonomy. A tag's description is its BODY (the node's own scalar
1
+ # $defs/onto — a node in an ontology. A tag's description is its BODY (the node's own scalar
2
2
  # value — author `name: !!omni The description` when the tag also has fields, or a plain
3
3
  # `name: The description` for a leaf); an optional explicit `color` ("#rrggbb" — a "pure color
4
4
  # tag"; absent ⇒ the UI derives a stable hue from the name); every OTHER key is a sub-tag, so
5
- # the taxonomy recurses to any depth (`additionalProperties`tag). The format `x-yamlover-tag`
5
+ # the taxonomy recurses to any depth (`others:`onto). The format `x-yamlover-onto`
6
6
  # makes the server render each one as a tag (a badge wired to its super/sub-tags). Attach to the
7
- # taxonomy root with the tag !!<*yamlover/$defs/tag> — it propagates down.
7
+ # taxonomy root with the tag !!<*yamlover/$defs/onto> — it propagates down.
8
8
  type: variant
9
- format: x-yamlover-tag
9
+ format: x-yamlover-onto
10
10
  value:
11
11
  type: string
12
12
  format: text/marklower
13
- properties:
13
+ members:
14
14
  color:
15
15
  type: string
16
16
  description: An explicit display color ("#rrggbb"); absent ⇒ derived from the tag's name
17
- additionalProperties: *:: yamlover: $defs: tag
17
+ others: *:: yamlover: $defs: onto
@@ -1,33 +1,34 @@
1
1
  # $defs/table — a grid node: an OMNI node whose keyless entries are the ROWS (top to
2
2
  # bottom), each row an array of CELLS (left to right). A row keyed `header` is the header
3
3
  # row; optional keyed `title` is the caption. The column count is inferred from the first
4
- # row. The table schema consumes exactly TWO nesting levels — rows, then cells; a cell
5
- # that is an untagged container switches BACK to a CHAPTER (prose, subchapters, tables
6
- # the same rules as a top chapter). A NESTED table like a list enters a cell only by
7
- # its explicit !!<…> tag. A header cell may be an omni scalar carrying a keyed `width`
8
- # sidecar a proportional column weight (AsciiDoc `cols` style), rendered weight/sum %;
9
- # `width` is deliberately schema-untyped (an omni cell must stay a LEAF for shape routing).
10
- # A cell that is a `*` pointer to its adjacent previous cell (`*[.-1]` left, `*..[.-1][.]`
11
- # up relative indexes, docs/language/pointers/relative-indexes) declares a MERGED cell: colspan/rowspan. Attach with
4
+ # row. The table schema consumes exactly TWO nesting levels — rows, then cells (the outer
5
+ # `others:` sweep is a row, ITS `others:` a cell); a cell that is an untagged container
6
+ # switches BACK to a CHAPTER (prose, subchapters, tablesthe same rules as a top chapter).
7
+ # A NESTED table like a list — enters a cell only by its explicit !!<…> tag. A header cell
8
+ # may be an omni scalar carrying a keyed `width` sidecar a proportional column weight
9
+ # (AsciiDoc `cols` style), rendered weight/sum %; `width` is deliberately schema-untyped (an
10
+ # omni cell must stay a LEAF for shape routing). A cell that is a `*` pointer to its adjacent
11
+ # previous cell (`*[.-1]` left, `*..[.-1][.]` up relative indexes,
12
+ # docs/language/pointers/relative-indexes) declares a MERGED cell: colspan/rowspan. Attach with
12
13
  # !!<*yamlover: $defs: table>.
13
14
  # No explicit `format:` — `type: variant` derives x-yamlover-table. Spec: docs/documents/marklower.
14
15
  type: variant
15
- properties:
16
+ members:
16
17
  title: # optional caption
17
18
  type: string
18
19
  format: text/marklower
19
20
  header: # the header row — same shape as a body row (the schema
20
21
  type: array # loader follows only $defs pointers, so the row
21
- items: # schema is repeated literally rather than *: items)
22
+ others: # schema is repeated literally rather than *: others)
22
23
  anyOf:
23
24
  - *:: yamlover: $defs: chunk
24
25
  - *:: yamlover: $defs: chapter
25
26
  - *:: yamlover: $defs: table
26
27
  - *:: yamlover: $defs: bullets
27
28
  - *:: yamlover: $defs: numbered
28
- items: # a row
29
+ others: # a row
29
30
  type: array
30
- items: # a cell
31
+ others: # a cell
31
32
  anyOf:
32
33
  - *:: yamlover: $defs: chunk # marklower prose (the default leaf)
33
34
  - *:: yamlover: $defs: chapter # an UNTAGGED container cell IS a chapter (the first
@@ -8,17 +8,17 @@
8
8
  # machinery is reused. Every planning field is optional — defaults-never-constraints: an
9
9
  # untouched task is just a titled note. Attach with !!<*yamlover:$defs:task>. Spec: ../TICKETS.md.
10
10
  #
11
- # `allOf: [*chapter]` is the (provisional) JSON-Schema way to say "a task is a chapter plus
12
- # more". Because task chapter, narrowing the body union to (task | chunk) below intersects
13
- # with chapter's (chapter | chunk) to exactly (task | chunk) — subtasks, not subchapters.
11
+ # `allOf: [*chapter]` extends: a task is a chapter plus more. Because task chapter, the OWN
12
+ # `others:` below run before the inherited one — narrows the body union to (task | chunk),
13
+ # intersecting chapter's (chapter | chunk): subtasks, not subchapters.
14
14
  allOf:
15
15
  - *:: yamlover: $defs: chapter
16
16
  type: variant
17
- items: # the body — SUBTASKS (the recursion) and chunks, interleaved
17
+ others: # the body — SUBTASKS (the recursion) and chunks, interleaved
18
18
  anyOf:
19
19
  - *:: yamlover: $defs: task # a subtask — the task tree
20
20
  - *:: yamlover: $defs: chunk # a content block
21
- properties:
21
+ members:
22
22
  priority: # free ordinal: low | normal | high | urgent (advisory)
23
23
  type: string
24
24
  due:
@@ -28,6 +28,6 @@ properties:
28
28
  type: string
29
29
  depends: # "blocked-by" edges → other tasks (ref; the dependency DAG)
30
30
  type: array
31
- items: *:: yamlover: $defs: task
31
+ others: *:: yamlover: $defs: task
32
32
  estimate: # free: "2h", "3pt"
33
33
  type: string
@@ -1,5 +1,5 @@
1
1
  # $defs/workflow — a state machine, expressed as a TAG whose CONTAINED sub-tags are its STATES
2
- # (each an ordinary $defs/tag: a description body, an optional `color`). Transitions are REF
2
+ # (each an ordinary $defs/onto: a description body, an optional `color`). Transitions are REF
3
3
  # edges, not containment: a state's `next:` holds pointer(s) to its successor state(s) elsewhere
4
4
  # in the SAME workflow — a cross-link in the or-graph, so a successor is NOT nested under its
5
5
  # predecessor (the contain-vs-ref distinction; a pointer-valued entry is a ref member, never a
@@ -13,6 +13,6 @@ format: x-yamlover-workflow
13
13
  value: # the workflow's description (its body)
14
14
  type: string
15
15
  format: text/marklower
16
- properties:
17
- initial: *:: yamlover: $defs: tag # ref → the start state
18
- additionalProperties: *:: yamlover: $defs: tag # every other key is a STATE (a plain tag)
16
+ members:
17
+ initial: *:: yamlover: $defs: onto # ref → the start state
18
+ others: *:: yamlover: $defs: onto # every other key is a STATE (a plain tag)
@@ -0,0 +1,46 @@
1
+ # The built-in ONTOLOGIES: the PALETTE (colors — pure color ontos, each with an explicit
2
+ # color) plus named ontos created from the picker (settings.yo:
3
+ # ontos.location). The palette ships with the yamlover project (::: yamlover.inthemoon.net);
4
+ # the engine grafts {$defs, ontos} as the `yamlover` self-import key into every served
5
+ # root, so *//yamlover/ontos/colors/<name> resolves from any project. Spec: ../$defs/onto.
6
+ !!<*yamlover: $defs: onto>
7
+ !!var Ontos
8
+ colors: Pure color ontos — the annotation palette; each carries an explicit color
9
+ yellow:
10
+ color: "#f9e2af"
11
+ green:
12
+ color: "#a6e3a1"
13
+ sky:
14
+ color: "#89dceb"
15
+ mauve:
16
+ color: "#cba6f7"
17
+ pink:
18
+ color: "#f5c2e7"
19
+ peach:
20
+ color: "#fab387"
21
+ first tag: !!<*::yamlover:$defs:onto>
22
+ second tag: !!<*::yamlover:$defs:onto>
23
+ third tag: !!<*::yamlover:$defs:onto>
24
+ forth tag: !!<*::yamlover:$defs:onto>
25
+ fifth tag: !!<*::yamlover:$defs:onto>
26
+ # Workflows — state machines (TICKETS.md §2). Each `next:` is a REF edge to a successor STATE in
27
+ # the SAME workflow (a cross-link, not a contained sub-tag); a terminal state has no `next`.
28
+ workflow: Lifecycles — task/ticket state machines
29
+ dev: !!<*yamlover:$defs:workflow> Software task lifecycle
30
+ initial: *::yamlover:ontos:workflow:dev:backlog
31
+ backlog: Captured, not yet refined
32
+ color: "#9399b2"
33
+ next: *::yamlover:ontos:workflow:dev:ready
34
+ ready: Refined, ready to pick up
35
+ color: "#89b4fa"
36
+ next: *::yamlover:ontos:workflow:dev:in-progress
37
+ in-progress: Being worked
38
+ color: "#fab387"
39
+ next:
40
+ - *::yamlover:ontos:workflow:dev:done
41
+ - *::yamlover:ontos:workflow:dev:cancelled
42
+ done: Completed
43
+ color: "#a6e3a1"
44
+ cancelled: Dropped
45
+ color: "#f38ba8"
46
+ верхушка: !!<*::yamlover:$defs:onto>
@@ -1 +1 @@
1
- import{r as f,b as d,j as o}from"./index-Bf2L7I9e.js";import{StaticImageChunk as h,PanZoomImage as x}from"./imagemap-B8RthxNE.js";function E({node:t,label:a,decode:s,chunk:e}){const[r,i]=f.useState([]),[g,u]=f.useState(null);return f.useEffect(()=>{let n=!1;const c=[];return i([]),u(null),(async()=>{const l=await fetch(d(t.path)).then(m=>m.arrayBuffer()),p=await s(l);if(!n){for(const m of p)c.push(URL.createObjectURL(m));n||i(c)}})().catch(l=>!n&&u(String(l.message||l))),()=>{n=!0,c.forEach(URL.revokeObjectURL)}},[t.path]),g?o.jsxs("div",{className:"error",children:[a,": ",g]}):r.length?o.jsx(o.Fragment,{children:r.map((n,c)=>e?o.jsx(h,{src:n,path:t.path,onNavigate:e.onNavigate},c):o.jsx(x,{src:n,className:"filemap fileimagemap",fill:r.length===1},c))}):o.jsxs("div",{className:"loading",children:["decoding ",a,"…"]})}async function w(t,a,s){const e=document.createElement("canvas");e.width=a,e.height=s;const r=e.getContext("2d");if(!r)throw new Error("no 2d context");const i=r.createImageData(a,s);return i.data.set(t),r.putImageData(i,0,0),b(e)}function b(t){return new Promise((a,s)=>t.toBlob(e=>e?a(e):s(new Error("canvas export failed")),"image/png"))}export{E as D,b as c,w as r};
1
+ import{r as f,b as d,j as o}from"./index-l1SxxFJR.js";import{StaticImageChunk as h,PanZoomImage as x}from"./imagemap-BCrt0kPn.js";function E({node:t,label:a,decode:s,chunk:e}){const[r,i]=f.useState([]),[g,u]=f.useState(null);return f.useEffect(()=>{let n=!1;const c=[];return i([]),u(null),(async()=>{const l=await fetch(d(t.path)).then(m=>m.arrayBuffer()),p=await s(l);if(!n){for(const m of p)c.push(URL.createObjectURL(m));n||i(c)}})().catch(l=>!n&&u(String(l.message||l))),()=>{n=!0,c.forEach(URL.revokeObjectURL)}},[t.path]),g?o.jsxs("div",{className:"error",children:[a,": ",g]}):r.length?o.jsx(o.Fragment,{children:r.map((n,c)=>e?o.jsx(h,{src:n,path:t.path,onNavigate:e.onNavigate},c):o.jsx(x,{src:n,className:"filemap fileimagemap",fill:r.length===1},c))}):o.jsxs("div",{className:"loading",children:["decoding ",a,"…"]})}async function w(t,a,s){const e=document.createElement("canvas");e.width=a,e.height=s;const r=e.getContext("2d");if(!r)throw new Error("no 2d context");const i=r.createImageData(a,s);return i.data.set(t),r.putImageData(i,0,0),b(e)}function b(t){return new Promise((a,s)=>t.toBlob(e=>e?a(e):s(new Error("canvas export failed")),"image/png"))}export{E as D,b as c,w as r};
@@ -1 +1 @@
1
- import{r as u,u as te,a as ne,e as oe,c as re,D as W,b as se,j as d,f as ae}from"./index-Bf2L7I9e.js";import{u as ce,a as ie}from"./paged-bLurvatj.js";const le=""+new URL("djvu-Ci0lFKxE.js",import.meta.url).href;let X=null;function ue(){return window.DjVu?Promise.resolve(window.DjVu):(X??=new Promise((s,c)=>{const i=document.createElement("script");i.src=le,i.onload=()=>window.DjVu?s(window.DjVu):c(new Error("DjVu failed to load")),i.onerror=()=>c(new Error("could not load djvu.js")),document.head.appendChild(i)}),X)}let v=null,Y=null,_=null;const m=new Map,S=new Map,de=6,Q=1500;async function he(s,c){const i=await ue();return v??=new i.Worker,c!==Y&&(Y=c,m.clear(),S.clear(),_=(async()=>(await v.createDocument(s),Number(await v.doc.getPagesQuantity().run())||0))()),_}async function ge(s,c){const i=Math.max(1,Math.round(s.height*c/s.width)),w=await createImageBitmap(s,{resizeWidth:c,resizeHeight:i,resizeQuality:"medium"}),g=document.createElement("canvas");g.width=c,g.height=i;const x=g.getContext("2d");return x.drawImage(w,0,0),w.close(),x.getImageData(0,0,c,i)}function fe(s){const c=m.get(s);if(c)return m.delete(s),m.set(s,c),Promise.resolve(c);const i=S.get(s);if(i)return i;const w=(async()=>{const[g,x,y,A]=await v.run(v.doc.getPage(s).getImageData(),v.doc.getPage(s).getNormalizedTextZones(),v.doc.getPage(s).getWidth(),v.doc.getPage(s).getHeight()),b=Number(y)||g.width,N=Number(A)||g.height,j={image:b>Q?await ge(g,Q):g,zones:Array.isArray(x)?x:[],w:b,h:N};for(S.delete(s),m.set(s,j);m.size>de;)m.delete(m.keys().next().value);return j})();return S.set(s,w),w}const p=s=>Number(s)||0;function pe({image:s}){const c=u.useRef(null);return u.useLayoutEffect(()=>{const i=c.current;i&&(i.width=s.width,i.height=s.height,i.getContext("2d")?.putImageData(s,0,0))},[s]),d.jsx("canvas",{className:"djvu-page",ref:c})}function xe({node:s}){const c=u.useRef(null),[i,w]=u.useState(0),[g,x]=u.useState(1),[y,A]=u.useState(0),[b,N]=u.useState(null),[f,j]=u.useState(null),[E,B]=u.useState(()=>new Set),[D,P]=u.useState(()=>new Map),T=u.useRef(new Map),V=te(s.path),{openCreate:H,openEdit:Z,palette:q,preview:R}=ne(V,s.path),O=V.annotations.filter(e=>e.selector?.type==="djvu").map(e=>({page:p(e.selector.page)||1,x:p(e.selector.x),y:p(e.selector.y),w:p(e.selector.w),h:p(e.selector.h),title:e.description,color:re(e),ann:oe(e)?e:void 0})),U=R?.color??W;if(R?.selector.type==="djvu"){const e=R.selector;O.push({page:p(e.page)||1,x:p(e.x),y:p(e.y),w:p(e.w),h:p(e.h),color:R.color})}const C=u.useRef(new Map),z=ce(c,()=>{const e=[];for(let n=1;n<=i;n++){const t=C.current.get(n);t&&e.push(t)}return e},i>0&&y>0);ie(c);const F=u.useRef(z);F.current=z,u.useLayoutEffect(()=>{z.restoreAnchor()},[g]),u.useEffect(()=>{const e=c.current;e&&!e.closest(".chunk-body")&&e.focus({preventScroll:!0})},[]),u.useLayoutEffect(()=>{const e=c.current;if(!e)return;const n=new ResizeObserver(([t])=>A(t.contentRect.width));return n.observe(e),()=>n.disconnect()},[]);const k=Math.min(y,1e3)*g;u.useEffect(()=>{const e=c.current;if(!e)return;let n=!1,t=0;const o=a=>{(a.ctrlKey||a.altKey||a.metaKey)&&(a.preventDefault(),n||(F.current.captureAnchor(),n=!0),clearTimeout(t),t=window.setTimeout(()=>n=!1,250),x(h=>Math.min(5,Math.max(.4,h*(a.deltaY<0?1.1:1/1.1)))))};return e.addEventListener("wheel",o,{passive:!1}),()=>{e.removeEventListener("wheel",o),clearTimeout(t)}},[]),u.useEffect(()=>{let e=!1;return w(0),N(null),B(new Set),P(new Map),C.current.clear(),T.current.clear(),(async()=>{const n=await fetch(se(s.path)).then(o=>o.arrayBuffer()),t=await he(n,s.path);e||w(t)})().catch(n=>!e&&N(String(n.message||n))),()=>{e=!0}},[s.path]),u.useEffect(()=>{if(!i)return;const e=new IntersectionObserver(n=>{B(t=>{const o=new Set(t);for(const a of n){const h=Number(a.target.dataset.page);a.isIntersecting?o.add(h):o.delete(h)}return o.size===t.size&&[...o].every(a=>t.has(a))?t:o})},{root:c.current,rootMargin:"2000px 0px"});for(const n of C.current.values())e.observe(n);return()=>e.disconnect()},[i,y>0]),u.useEffect(()=>{let e=!0;return E.forEach(n=>{D.has(n)||fe(n).then(t=>{T.current.set(n,{w:t.w,h:t.h}),e&&P(o=>new Map(o).set(n,t))}).catch(()=>{})}),P(n=>{let t=!1;const o=new Map(n);for(const a of o.keys())E.has(a)||(o.delete(a),t=!0);return t?o:n}),()=>{e=!1}},[E]);const G=()=>{const e=window.getSelection();if(!e||e.isCollapsed||!e.anchorNode)return;const t=(e.anchorNode.nodeType===1?e.anchorNode:e.anchorNode.parentElement)?.closest(".djvu-page-wrap");if(!t||!c.current?.contains(t))return;const o=Number(t.dataset.page),a=t.getBoundingClientRect(),h=a.width/(D.get(o)?.w||1);if(!h)return;const l=e.getRangeAt(0).getBoundingClientRect();l.width<2||l.height<2||H({type:"djvu",page:o,x:Math.round((l.left-a.left)/h),y:Math.round((l.top-a.top)/h),w:Math.round(l.width/h),h:Math.round(l.height/h)},{x:l.left,y:l.bottom+6})},I=(e,n)=>n.getBoundingClientRect().width/(D.get(e)?.w||1),J=(e,n)=>{const t=n.currentTarget.getBoundingClientRect(),o=I(e,n.currentTarget);j({page:e,x0:(n.clientX-t.left)/o,y0:(n.clientY-t.top)/o,x1:(n.clientX-t.left)/o,y1:(n.clientY-t.top)/o})},$=(e,n)=>{const t=n.currentTarget.getBoundingClientRect(),o=I(e,n.currentTarget);j(a=>a&&{...a,x1:(n.clientX-t.left)/o,y1:(n.clientY-t.top)/o})},ee=(e,n)=>{const t=f;if(j(null),!t||t.page!==e)return;const o=I(e,n.currentTarget),a=Math.min(t.x0,t.x1),h=Math.min(t.y0,t.y1),l=Math.abs(t.x1-t.x0),r=Math.abs(t.y1-t.y0);if(l*o<3||r*o<3)return;const M=n.currentTarget.getBoundingClientRect();H({type:"djvu",page:e,x:Math.round(a),y:Math.round(h),w:Math.round(l),h:Math.round(r)},{x:M.left+a*o,y:M.top+(h+r)*o+6})};return b?d.jsxs("div",{className:"error",children:["djvu: ",b]}):d.jsxs(d.Fragment,{children:[d.jsxs("div",{className:"filedjvu yo-zoomable",ref:c,tabIndex:0,onMouseUp:G,children:[i===0&&d.jsx("div",{className:"loading",children:"opening djvu…"}),y>0&&Array.from({length:i},(e,n)=>{const t=n+1,o=E.has(t)?D.get(t):void 0,a=T.current.get(t),h=k*(a?a.h/a.w:Math.SQRT2),l=o?k/o.w:0;return d.jsx("div",{className:"djvu-page-wrap","data-page":t,ref:r=>{r?C.current.set(t,r):C.current.delete(t)},style:{width:k,height:o?void 0:h},children:o?d.jsxs(d.Fragment,{children:[d.jsx(pe,{image:o.image}),o.zones.length>0?d.jsx("div",{className:"djvu-textlayer",children:o.zones.map((r,M)=>d.jsx("span",{style:{left:r.x*l,top:r.y*l,width:r.width*l,height:r.height*l,fontSize:r.height*l},children:r.text},M))}):d.jsx("div",{className:"djvu-marquee",onMouseDown:r=>J(t,r),onMouseMove:r=>$(t,r),onMouseUp:r=>ee(t,r),children:f?.page===t&&d.jsx("div",{className:"djvu-region",style:{left:Math.min(f.x0,f.x1)*l,top:Math.min(f.y0,f.y1)*l,width:Math.abs(f.x1-f.x0)*l,height:Math.abs(f.y1-f.y0)*l,borderColor:U,background:U+"2e"}})}),O.filter(r=>r.page===t).map((r,M)=>{const K=r.color||W;return d.jsx("div",{id:r.ann?.fragmentSlug?ae(s.path,r.ann.fragmentSlug):void 0,className:"djvu-region"+(r.ann?" editable":""),title:r.ann?r.title||"click to recolor or delete":r.title,onClick:r.ann?L=>{L.stopPropagation(),Z(r.ann,{x:L.clientX,y:L.clientY})}:void 0,style:{left:r.x*l,top:r.y*l,width:r.w*l,height:r.h*l,borderColor:K,background:K+"2e"}},M)})]}):d.jsx("div",{className:"djvu-placeholder",children:E.has(t)?"decoding…":""})},n)})]}),q]})}export{xe as DjvuView};
1
+ import{r as u,u as te,a as ne,e as oe,c as re,D as W,b as se,j as d,f as ae}from"./index-l1SxxFJR.js";import{u as ce,a as ie}from"./paged-UVifI3SC.js";const le=""+new URL("djvu-Ci0lFKxE.js",import.meta.url).href;let X=null;function ue(){return window.DjVu?Promise.resolve(window.DjVu):(X??=new Promise((s,c)=>{const i=document.createElement("script");i.src=le,i.onload=()=>window.DjVu?s(window.DjVu):c(new Error("DjVu failed to load")),i.onerror=()=>c(new Error("could not load djvu.js")),document.head.appendChild(i)}),X)}let v=null,Y=null,_=null;const m=new Map,S=new Map,de=6,Q=1500;async function he(s,c){const i=await ue();return v??=new i.Worker,c!==Y&&(Y=c,m.clear(),S.clear(),_=(async()=>(await v.createDocument(s),Number(await v.doc.getPagesQuantity().run())||0))()),_}async function ge(s,c){const i=Math.max(1,Math.round(s.height*c/s.width)),w=await createImageBitmap(s,{resizeWidth:c,resizeHeight:i,resizeQuality:"medium"}),g=document.createElement("canvas");g.width=c,g.height=i;const x=g.getContext("2d");return x.drawImage(w,0,0),w.close(),x.getImageData(0,0,c,i)}function fe(s){const c=m.get(s);if(c)return m.delete(s),m.set(s,c),Promise.resolve(c);const i=S.get(s);if(i)return i;const w=(async()=>{const[g,x,y,A]=await v.run(v.doc.getPage(s).getImageData(),v.doc.getPage(s).getNormalizedTextZones(),v.doc.getPage(s).getWidth(),v.doc.getPage(s).getHeight()),b=Number(y)||g.width,N=Number(A)||g.height,j={image:b>Q?await ge(g,Q):g,zones:Array.isArray(x)?x:[],w:b,h:N};for(S.delete(s),m.set(s,j);m.size>de;)m.delete(m.keys().next().value);return j})();return S.set(s,w),w}const p=s=>Number(s)||0;function pe({image:s}){const c=u.useRef(null);return u.useLayoutEffect(()=>{const i=c.current;i&&(i.width=s.width,i.height=s.height,i.getContext("2d")?.putImageData(s,0,0))},[s]),d.jsx("canvas",{className:"djvu-page",ref:c})}function xe({node:s}){const c=u.useRef(null),[i,w]=u.useState(0),[g,x]=u.useState(1),[y,A]=u.useState(0),[b,N]=u.useState(null),[f,j]=u.useState(null),[E,B]=u.useState(()=>new Set),[D,P]=u.useState(()=>new Map),T=u.useRef(new Map),V=te(s.path),{openCreate:H,openEdit:Z,palette:q,preview:R}=ne(V,s.path),O=V.annotations.filter(e=>e.selector?.type==="djvu").map(e=>({page:p(e.selector.page)||1,x:p(e.selector.x),y:p(e.selector.y),w:p(e.selector.w),h:p(e.selector.h),title:e.description,color:re(e),ann:oe(e)?e:void 0})),U=R?.color??W;if(R?.selector.type==="djvu"){const e=R.selector;O.push({page:p(e.page)||1,x:p(e.x),y:p(e.y),w:p(e.w),h:p(e.h),color:R.color})}const C=u.useRef(new Map),z=ce(c,()=>{const e=[];for(let n=1;n<=i;n++){const t=C.current.get(n);t&&e.push(t)}return e},i>0&&y>0);ie(c);const F=u.useRef(z);F.current=z,u.useLayoutEffect(()=>{z.restoreAnchor()},[g]),u.useEffect(()=>{const e=c.current;e&&!e.closest(".chunk-body")&&e.focus({preventScroll:!0})},[]),u.useLayoutEffect(()=>{const e=c.current;if(!e)return;const n=new ResizeObserver(([t])=>A(t.contentRect.width));return n.observe(e),()=>n.disconnect()},[]);const k=Math.min(y,1e3)*g;u.useEffect(()=>{const e=c.current;if(!e)return;let n=!1,t=0;const o=a=>{(a.ctrlKey||a.altKey||a.metaKey)&&(a.preventDefault(),n||(F.current.captureAnchor(),n=!0),clearTimeout(t),t=window.setTimeout(()=>n=!1,250),x(h=>Math.min(5,Math.max(.4,h*(a.deltaY<0?1.1:1/1.1)))))};return e.addEventListener("wheel",o,{passive:!1}),()=>{e.removeEventListener("wheel",o),clearTimeout(t)}},[]),u.useEffect(()=>{let e=!1;return w(0),N(null),B(new Set),P(new Map),C.current.clear(),T.current.clear(),(async()=>{const n=await fetch(se(s.path)).then(o=>o.arrayBuffer()),t=await he(n,s.path);e||w(t)})().catch(n=>!e&&N(String(n.message||n))),()=>{e=!0}},[s.path]),u.useEffect(()=>{if(!i)return;const e=new IntersectionObserver(n=>{B(t=>{const o=new Set(t);for(const a of n){const h=Number(a.target.dataset.page);a.isIntersecting?o.add(h):o.delete(h)}return o.size===t.size&&[...o].every(a=>t.has(a))?t:o})},{root:c.current,rootMargin:"2000px 0px"});for(const n of C.current.values())e.observe(n);return()=>e.disconnect()},[i,y>0]),u.useEffect(()=>{let e=!0;return E.forEach(n=>{D.has(n)||fe(n).then(t=>{T.current.set(n,{w:t.w,h:t.h}),e&&P(o=>new Map(o).set(n,t))}).catch(()=>{})}),P(n=>{let t=!1;const o=new Map(n);for(const a of o.keys())E.has(a)||(o.delete(a),t=!0);return t?o:n}),()=>{e=!1}},[E]);const G=()=>{const e=window.getSelection();if(!e||e.isCollapsed||!e.anchorNode)return;const t=(e.anchorNode.nodeType===1?e.anchorNode:e.anchorNode.parentElement)?.closest(".djvu-page-wrap");if(!t||!c.current?.contains(t))return;const o=Number(t.dataset.page),a=t.getBoundingClientRect(),h=a.width/(D.get(o)?.w||1);if(!h)return;const l=e.getRangeAt(0).getBoundingClientRect();l.width<2||l.height<2||H({type:"djvu",page:o,x:Math.round((l.left-a.left)/h),y:Math.round((l.top-a.top)/h),w:Math.round(l.width/h),h:Math.round(l.height/h)},{x:l.left,y:l.bottom+6})},I=(e,n)=>n.getBoundingClientRect().width/(D.get(e)?.w||1),J=(e,n)=>{const t=n.currentTarget.getBoundingClientRect(),o=I(e,n.currentTarget);j({page:e,x0:(n.clientX-t.left)/o,y0:(n.clientY-t.top)/o,x1:(n.clientX-t.left)/o,y1:(n.clientY-t.top)/o})},$=(e,n)=>{const t=n.currentTarget.getBoundingClientRect(),o=I(e,n.currentTarget);j(a=>a&&{...a,x1:(n.clientX-t.left)/o,y1:(n.clientY-t.top)/o})},ee=(e,n)=>{const t=f;if(j(null),!t||t.page!==e)return;const o=I(e,n.currentTarget),a=Math.min(t.x0,t.x1),h=Math.min(t.y0,t.y1),l=Math.abs(t.x1-t.x0),r=Math.abs(t.y1-t.y0);if(l*o<3||r*o<3)return;const M=n.currentTarget.getBoundingClientRect();H({type:"djvu",page:e,x:Math.round(a),y:Math.round(h),w:Math.round(l),h:Math.round(r)},{x:M.left+a*o,y:M.top+(h+r)*o+6})};return b?d.jsxs("div",{className:"error",children:["djvu: ",b]}):d.jsxs(d.Fragment,{children:[d.jsxs("div",{className:"filedjvu yo-zoomable",ref:c,tabIndex:0,onMouseUp:G,children:[i===0&&d.jsx("div",{className:"loading",children:"opening djvu…"}),y>0&&Array.from({length:i},(e,n)=>{const t=n+1,o=E.has(t)?D.get(t):void 0,a=T.current.get(t),h=k*(a?a.h/a.w:Math.SQRT2),l=o?k/o.w:0;return d.jsx("div",{className:"djvu-page-wrap","data-page":t,ref:r=>{r?C.current.set(t,r):C.current.delete(t)},style:{width:k,height:o?void 0:h},children:o?d.jsxs(d.Fragment,{children:[d.jsx(pe,{image:o.image}),o.zones.length>0?d.jsx("div",{className:"djvu-textlayer",children:o.zones.map((r,M)=>d.jsx("span",{style:{left:r.x*l,top:r.y*l,width:r.width*l,height:r.height*l,fontSize:r.height*l},children:r.text},M))}):d.jsx("div",{className:"djvu-marquee",onMouseDown:r=>J(t,r),onMouseMove:r=>$(t,r),onMouseUp:r=>ee(t,r),children:f?.page===t&&d.jsx("div",{className:"djvu-region",style:{left:Math.min(f.x0,f.x1)*l,top:Math.min(f.y0,f.y1)*l,width:Math.abs(f.x1-f.x0)*l,height:Math.abs(f.y1-f.y0)*l,borderColor:U,background:U+"2e"}})}),O.filter(r=>r.page===t).map((r,M)=>{const K=r.color||W;return d.jsx("div",{id:r.ann?.fragmentSlug?ae(s.path,r.ann.fragmentSlug):void 0,className:"djvu-region"+(r.ann?" editable":""),title:r.ann?r.title||"click to recolor or delete":r.title,onClick:r.ann?L=>{L.stopPropagation(),Z(r.ann,{x:L.clientX,y:L.clientY})}:void 0,style:{left:r.x*l,top:r.y*l,width:r.w*l,height:r.h*l,borderColor:K,background:K+"2e"}},M)})]}):d.jsx("div",{className:"djvu-placeholder",children:E.has(t)?"decoding…":""})},n)})]}),q]})}export{xe as DjvuView};