@uniweb/core 0.7.31 → 0.7.32

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 (2) hide show
  1. package/package.json +3 -2
  2. package/src/section-id.js +67 -0
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@uniweb/core",
3
- "version": "0.7.31",
3
+ "version": "0.7.32",
4
4
  "description": "Core classes for the Uniweb platform - Uniweb, Website, Page, Block",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./src/index.js",
8
- "./locale-config": "./src/locale-config.js"
8
+ "./locale-config": "./src/locale-config.js",
9
+ "./section-id": "./src/section-id.js"
9
10
  },
10
11
  "files": [
11
12
  "src"
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The DOM id of a rendered section — one rule, shared by everything that
3
+ * needs to name a section.
4
+ *
5
+ * A section's id is written by the renderer and read by anything that links
6
+ * to a section: the search index's anchors, a table of contents, a deep link
7
+ * someone pastes. Those only agree if they derive the id the same way, and
8
+ * they cannot check each other — a mismatch produces no error anywhere. The
9
+ * link simply lands on the page and does not scroll, and if the target is the
10
+ * page you are already on, nothing visibly happens at all.
11
+ *
12
+ * That is not hypothetical. The renderers moved from the positional `id` to
13
+ * `stableId` (so an id survives reordering) and the search extractor was not
14
+ * updated, so it kept emitting `Section1` while the DOM said
15
+ * `section-what-is-uniweb`. Every section-level search result on every site
16
+ * pointed at a fragment that did not exist, and no test failed.
17
+ *
18
+ * So this is deliberately the ONLY place the rule is written down, and it
19
+ * captures both halves — which identity to use AND how to spell it. A helper
20
+ * that only formatted a value the caller picked would have prevented the
21
+ * spelling half of that bug and none of the identity half.
22
+ *
23
+ * **Zero imports, and it must stay that way.** `@uniweb/projections` consumes
24
+ * this through the leaf subpath `@uniweb/core/section-id` because its
25
+ * environment contract forbids the bare `@uniweb/core` entry (that pulls in
26
+ * semantic-parser and theming). Adding an import here would break that
27
+ * package's `tests/environment.test.js`.
28
+ */
29
+
30
+ /** Prefix for every section wrapper id. */
31
+ const PREFIX = 'section-'
32
+
33
+ /**
34
+ * The DOM id for a section, from either a Block or the raw section data.
35
+ *
36
+ * Accepts both shapes on purpose: the runtime holds `Block` instances while
37
+ * build-time consumers hold plain objects off the wire. Both carry the same
38
+ * two fields, so one function serves both rather than each growing its own.
39
+ *
40
+ * `stableId` is preferred because it is derived from the section's filename
41
+ * (or an authored `id:`) and therefore survives reordering; the positional
42
+ * `id` is the fallback for content that has no stable identity.
43
+ *
44
+ * @param {{stableId?: string, id?: string|number}} section - A Block, or a
45
+ * section object from site content.
46
+ * @returns {string} e.g. `section-hero`. Returns `section-unknown` rather
47
+ * than an id ending in `undefined` when a section carries no identity at
48
+ * all — a wrong-but-obvious anchor beats a malformed one.
49
+ */
50
+ export function sectionDomId(section) {
51
+ if (!section) return `${PREFIX}unknown`
52
+ const id = section.stableId || section.id
53
+ return `${PREFIX}${id === undefined || id === null || id === '' ? 'unknown' : id}`
54
+ }
55
+
56
+ /**
57
+ * The same id as a URL fragment, for building a link to a section.
58
+ *
59
+ * Exists so a caller composing an href never has to remember whether the
60
+ * `#` is already included — the concatenation is the part people get wrong.
61
+ *
62
+ * @param {{stableId?: string, id?: string|number}} section
63
+ * @returns {string} e.g. `#section-hero`
64
+ */
65
+ export function sectionHash(section) {
66
+ return `#${sectionDomId(section)}`
67
+ }