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.
- package/README.md +6 -6
- package/bin/ga4.js +14 -1
- package/dist/agent-docs/AGENTS.md +10 -10
- package/dist/builtin-taxonomy/$defs/.yo/meta.yo +18 -23
- package/dist/builtin-taxonomy/$defs/annotation +6 -6
- package/dist/builtin-taxonomy/$defs/board +4 -4
- package/dist/builtin-taxonomy/$defs/bullets +2 -2
- package/dist/builtin-taxonomy/$defs/chapter +6 -7
- package/dist/builtin-taxonomy/$defs/chunk +4 -3
- package/dist/builtin-taxonomy/$defs/config +5 -5
- package/dist/builtin-taxonomy/$defs/fragment +2 -2
- package/dist/builtin-taxonomy/$defs/numbered +2 -2
- package/dist/builtin-taxonomy/$defs/{tag → onto} +6 -6
- package/dist/builtin-taxonomy/$defs/table +13 -12
- package/dist/builtin-taxonomy/$defs/task +6 -6
- package/dist/builtin-taxonomy/$defs/workflow +4 -4
- package/dist/builtin-taxonomy/ontos/.yo/body.yo +46 -0
- package/dist/client/assets/{decoded-D_YQdg1-.js → decoded-5u9KK4Nb.js} +1 -1
- package/dist/client/assets/{djvu-Di4fPA-J.js → djvu-CvRKxWcX.js} +1 -1
- package/dist/client/assets/{docx-BSduN32X.js → docx-CFqmrRMY.js} +1 -1
- package/dist/client/assets/{heic-DOAG7EsW.js → heic-P0RPecFK.js} +1 -1
- package/dist/client/assets/{imagemap-B8RthxNE.js → imagemap-BCrt0kPn.js} +1 -1
- package/dist/client/assets/index-_gAtxDG4.css +1 -0
- package/dist/client/assets/index-l1SxxFJR.js +754 -0
- package/dist/client/assets/{map-Cf7ar1_U.js → map-ClMfiQr8.js} +1 -1
- package/dist/client/assets/{openable-CCBlc-Ws.js → openable-9ABNW3A9.js} +1 -1
- package/dist/client/assets/{paged-bLurvatj.js → paged-UVifI3SC.js} +1 -1
- package/dist/client/assets/{pdf-D1ox8M9A.js → pdf-BGgu5LFZ.js} +1 -1
- package/dist/client/assets/{psd-AT50x-YR.js → psd-D15IXPVu.js} +1 -1
- package/dist/client/assets/{spreadsheet-DeQh5CNF.js → spreadsheet-CeOcWWb2.js} +1 -1
- package/dist/client/assets/{tiff-B3-awhzQ.js → tiff-pZPBtPPg.js} +1 -1
- package/dist/client/assets/{xyflow-DuQ4jjaq.js → xyflow-uN1JIC1A.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server.js +1420 -425
- package/package.json +1 -1
- package/dist/builtin-taxonomy/tags/.yo/body.yo +0 -46
- package/dist/client/assets/index-Bf2L7I9e.js +0 -752
- 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/
|
|
96
|
-
`…/IMG.jpg/
|
|
97
|
-
`…/IMG.jpg#
|
|
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-
|
|
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:
|
|
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
|
-
- `*::
|
|
90
|
-
- `*::: host.example: $defs:
|
|
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:
|
|
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
|
-
- **`
|
|
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
|
-
- *::
|
|
248
|
-
- {description: 'A math block', tag: *::
|
|
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 (`
|
|
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: *::
|
|
317
|
-
world: *::: host.example: $defs:
|
|
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
|
-
|
|
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
|
-
|
|
4
|
-
format: yamlover/meta
|
|
7
|
+
concrete: yamlover/meta
|
|
5
8
|
chunk:
|
|
6
|
-
|
|
7
|
-
format: yamlover/meta
|
|
9
|
+
concrete: yamlover/meta
|
|
8
10
|
tag:
|
|
9
|
-
|
|
10
|
-
format: yamlover/meta
|
|
11
|
+
concrete: yamlover/meta
|
|
11
12
|
annotation:
|
|
12
|
-
|
|
13
|
-
format: yamlover/meta
|
|
13
|
+
concrete: yamlover/meta
|
|
14
14
|
fragment:
|
|
15
|
-
|
|
16
|
-
format: yamlover/meta
|
|
15
|
+
concrete: yamlover/meta
|
|
17
16
|
task:
|
|
18
|
-
|
|
19
|
-
format: yamlover/meta
|
|
17
|
+
concrete: yamlover/meta
|
|
20
18
|
workflow:
|
|
21
|
-
|
|
22
|
-
format: yamlover/meta
|
|
19
|
+
concrete: yamlover/meta
|
|
23
20
|
board:
|
|
24
|
-
|
|
25
|
-
format: yamlover/meta
|
|
21
|
+
concrete: yamlover/meta
|
|
26
22
|
table:
|
|
27
|
-
|
|
28
|
-
format: yamlover/meta
|
|
23
|
+
concrete: yamlover/meta
|
|
29
24
|
bullets:
|
|
30
|
-
|
|
31
|
-
format: yamlover/meta
|
|
25
|
+
concrete: yamlover/meta
|
|
32
26
|
numbered:
|
|
33
|
-
|
|
34
|
-
|
|
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 (`- *::
|
|
4
|
-
# • parametrized — an object carrying `tag: *::
|
|
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:
|
|
13
|
-
|
|
14
|
-
tag: *:: yamlover: $defs:
|
|
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
|
-
|
|
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
|
-
|
|
10
|
-
workflow: *:: yamlover: $defs:
|
|
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
|
-
|
|
13
|
+
others: # = a plain lane, several = per-tag SUBLANES stacked
|
|
14
14
|
type: array # vertically. Edited via the lane headers, persisted by
|
|
15
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
12
|
-
#
|
|
13
|
-
#
|
|
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
|
-
|
|
20
|
+
members:
|
|
22
21
|
description: # optional subtitle / heading annotation — stays keyed
|
|
23
22
|
type: string
|
|
24
23
|
format: text/marklower
|
|
25
|
-
|
|
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
|
|
4
|
-
#
|
|
5
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
14
|
+
others:
|
|
15
15
|
type: string
|
|
16
|
-
annotations: *:: yamlover: $defs:
|
|
17
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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/
|
|
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 (`
|
|
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/
|
|
7
|
+
# taxonomy root with the tag !!<*yamlover/$defs/onto> — it propagates down.
|
|
8
8
|
type: variant
|
|
9
|
-
format: x-yamlover-
|
|
9
|
+
format: x-yamlover-onto
|
|
10
10
|
value:
|
|
11
11
|
type: string
|
|
12
12
|
format: text/marklower
|
|
13
|
-
|
|
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
|
-
|
|
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
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# `width` is deliberately schema-untyped (an
|
|
10
|
-
# A cell that is a `*` pointer to its adjacent
|
|
11
|
-
#
|
|
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, tables — the 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
29
|
+
others: # a row
|
|
29
30
|
type: array
|
|
30
|
-
|
|
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]`
|
|
12
|
-
#
|
|
13
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
17
|
-
initial: *:: yamlover: $defs:
|
|
18
|
-
|
|
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-
|
|
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-
|
|
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};
|