gp-dimm-city 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +27 -19
- package/package.json +3 -5
- package/plugin.js +19 -10
- package/snippets/npc-stat-compact.md +2 -2
- package/snippets/npc-stat.md +2 -2
- package/snippets/outcome.md +3 -3
- package/snippets/toc-page.md +1 -1
- package/snippets/toc.md +1 -1
- package/styles/components/chrome.css +2 -2
- package/styles/dc-palette.css +4 -3
- package/styles/page-rules.css +5 -7
- package/styles/page-templates.css +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,82 @@ cut a version that has no `## [X.Y.Z]` heading below.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.10.0] - 2026-10-31
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Needs Gutterpress 0.11.22 or later** (was 0.11.20-alpha.3), in
|
|
15
|
+
`engines.gutterpress` and the README. With `size` gone from
|
|
16
|
+
`styles/page-rules.css` (below), the page size comes from the book's
|
|
17
|
+
manifest, which Gutterpress writes from 0.11.22 on. On 0.11.21 a book would
|
|
18
|
+
fall back to Letter (the design guide's full-bleed plates fail its build);
|
|
19
|
+
now Gutterpress refuses to load the extension there and says to update.
|
|
20
|
+
Margins set in Book setup > Book > Margins (`page.margin`, new in
|
|
21
|
+
Gutterpress 0.11.23) leave the full-bleed plates and named pages theirs
|
|
22
|
+
from 0.11.23-beta.1 (dimm-city/gutterpress#454).
|
|
23
|
+
- **Full-page art plates are the sheet the book prints.** `.dc-specialty-art`
|
|
24
|
+
and `.dc-full-page` / `@page full-bleed` take their size from
|
|
25
|
+
`--gp-page-width` / `--gp-page-height` (Gutterpress 0.11.23-beta.1 on), so
|
|
26
|
+
they follow the book's page size instead of a copy of the `dtrpg` sheet; on
|
|
27
|
+
0.11.22 they fall back to that sheet. At that sheet the PDF is identical.
|
|
28
|
+
- **Tests and the guide build run on Gutterpress 0.11.23.** The dev
|
|
29
|
+
dependency moves from 0.11.20-alpha.3, three releases behind, to the 0.11.23
|
|
30
|
+
line the 1.10 release targets. The guide is 172 pages, four fewer than on
|
|
31
|
+
0.11.23-alpha.6: Gutterpress now keeps the guide's own `break-before: auto`
|
|
32
|
+
on specialty specimens in doc pages (dimm-city/gutterpress#476), so the
|
|
33
|
+
blank pages it put before them are gone; the Part 2 example still opens its
|
|
34
|
+
spread on a left page. The design
|
|
35
|
+
guide's manifest uses 0.11.23's flat shape: `chapters:` (was
|
|
36
|
+
`source.files`), no `page.tolerance` (the preset's), and no
|
|
37
|
+
`validate.source.markdownlint` (the repo's `.markdownlint.jsonc` is found by
|
|
38
|
+
walking up to the repository root).
|
|
39
|
+
- **Docs follow Gutterpress 0.11.23.** Vendored copies live under
|
|
40
|
+
`extensions/npm/` (a book vendored earlier keeps `plugins/npm/` until its
|
|
41
|
+
next `ext add` or `ext update`), the app adds an npm extension on Book
|
|
42
|
+
setup's Extensions tab, and the README and `package.json` give the same minimum
|
|
43
|
+
Gutterpress version. The README's `ext list` sample shows
|
|
44
|
+
1.9.0 with the badges in the order Gutterpress prints them.
|
|
45
|
+
- **The design guide and the snippets type the plain spellings** (`---`, `--`,
|
|
46
|
+
`...`, `-`, `'`). `source.characters` findings on the guide drop from 367 to
|
|
47
|
+
0 (its six minus signs are typed on purpose, and Gutterpress no longer
|
|
48
|
+
flags them from 0.11.23-beta.1), and the five snippets paste into a book
|
|
49
|
+
with none.
|
|
50
|
+
|
|
51
|
+
### Removed
|
|
52
|
+
|
|
53
|
+
- **`size` from `styles/page-rules.css`'s `@page`.** Gutterpress 0.11.23
|
|
54
|
+
writes the manifest's page size after every stylesheet and reports a `size`
|
|
55
|
+
in a look as `printsafe/page-size-in-stylesheet` on every build. The sheet is
|
|
56
|
+
the same 8.625 × 11.25 in.
|
|
57
|
+
- **`--page-width` and `--page-height` from `dc-palette.css`.** They copied
|
|
58
|
+
the `dtrpg` sheet and did not follow a book's page size; read
|
|
59
|
+
`--gp-page-width` / `--gp-page-height` instead.
|
|
60
|
+
- **`gutterpress.tokensFile` from `package.json`.** Gutterpress 0.11.23 reads
|
|
61
|
+
every enabled look's `:root` tokens and no longer reads the field.
|
|
62
|
+
- **The `lint` npm script and the `gutterpress lint` row in the design guide.**
|
|
63
|
+
The command does not exist; the print-safety lint runs inside
|
|
64
|
+
`gutterpress build` and `gutterpress validate`, and
|
|
65
|
+
`gutterpress validate <book> --category source` runs the source checks
|
|
66
|
+
alone.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- **`@outcome` rolls and ladder bands accept `--`.** `11--19` prints as
|
|
71
|
+
11–19 and a ladder table typed that way is recognised; the `–` spelling
|
|
72
|
+
still works. The character check asks for `--`, and Gutterpress 0.11.23's
|
|
73
|
+
example books type it.
|
|
74
|
+
- **An alert's first paragraph is typeset like any other.** `---`, `--`, `...`
|
|
75
|
+
and straight quotes inside `> [!NOTE]`, `> [!VIBE]` and the other alert
|
|
76
|
+
blocks printed as typed, and `—` printed as `<>`, in the paragraph
|
|
77
|
+
that followed the marker; later paragraphs were fine. The marker is now cut
|
|
78
|
+
from the text markdown-it had already typeset rather than re-parsed. The six
|
|
79
|
+
em dashes the guide had to leave typed for this (chapters 5 and 11) type
|
|
80
|
+
`---` now.
|
|
81
|
+
- **The guide keeps its six minus signs.** The `−1` (U+2212) in chapters 6,
|
|
82
|
+
11, 304 and 306 print as typed; a minus is not a hyphen and is not converted
|
|
83
|
+
to one. The character check flags them until Gutterpress 0.11.23 stops
|
|
84
|
+
asking for `-`.
|
|
85
|
+
|
|
10
86
|
## [1.9.0] - 2026-10-26
|
|
11
87
|
|
|
12
88
|
### Changed
|
package/README.md
CHANGED
|
@@ -8,10 +8,11 @@ the package renders them and prints them.
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
**In the Gutterpress app:** open the book, then
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
**In the Gutterpress app:** open the book, then Book setup → Extensions, search
|
|
12
|
+
npm for `gp-dimm-city` and click Add (or add it by exact name under *Other ways
|
|
13
|
+
to add*). The package joins Your extensions, and its sheets and snippets are
|
|
14
|
+
live in the preview. The
|
|
15
|
+
[desktop guide](https://github.com/dimm-city/gutterpress/blob/main/docs/desktop-guide/06-plugins.md) has the rest.
|
|
15
16
|
|
|
16
17
|
**From the command line**, in the folder that holds the book:
|
|
17
18
|
|
|
@@ -20,22 +21,22 @@ gutterpress ext add gp-dimm-city my-book
|
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
Either way Gutterpress downloads the package from npm, verifies the registry
|
|
23
|
-
hash, writes a copy under `my-book/
|
|
24
|
+
hash, writes a copy under `my-book/extensions/npm/`, and pins the exact version
|
|
24
25
|
in the manifest:
|
|
25
26
|
|
|
26
27
|
```yaml
|
|
27
28
|
extensions:
|
|
28
|
-
- gp-dimm-city@1.
|
|
29
|
+
- gp-dimm-city@1.9.0
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
**Commit the manifest, not `
|
|
32
|
-
the book's history: Gutterpress adds `
|
|
33
|
-
The pin in the manifest is what you commit. On a fresh clone, the
|
|
34
|
-
export or `gutterpress validate` downloads exactly the pinned
|
|
35
|
-
the same verified path (this needs the network once); after that
|
|
36
|
-
offline.
|
|
32
|
+
**Commit the manifest, not `extensions/npm/`.** The downloaded copy is not part
|
|
33
|
+
of the book's history: Gutterpress adds `extensions/npm/` to the book's
|
|
34
|
+
`.gitignore`. The pin in the manifest is what you commit. On a fresh clone, the
|
|
35
|
+
first build, export or `gutterpress validate` downloads exactly the pinned
|
|
36
|
+
version through the same verified path (this needs the network once); after that
|
|
37
|
+
the book works offline.
|
|
37
38
|
|
|
38
|
-
`gutterpress ext list my-book` shows `gp-dimm-city@1.
|
|
39
|
+
`gutterpress ext list my-book` shows `gp-dimm-city@1.9.0 [npm; markdown, styles, snippets, components]`.
|
|
39
40
|
|
|
40
41
|
## What you get
|
|
41
42
|
|
|
@@ -114,9 +115,10 @@ Also in the box:
|
|
|
114
115
|
|
|
115
116
|
## Quick start
|
|
116
117
|
|
|
117
|
-
Requires Gutterpress **0.11.
|
|
118
|
-
its
|
|
119
|
-
|
|
118
|
+
Requires Gutterpress **0.11.22** or later, the first that prints the book at
|
|
119
|
+
its manifest's page size (this look no longer sets one). Since 0.11.0 it
|
|
120
|
+
wraps every extension's CSS in its own cascade layer, so a book no longer
|
|
121
|
+
needs a starter look removed before this package can win the cascade.
|
|
120
122
|
|
|
121
123
|
```sh
|
|
122
124
|
gutterpress new "My Book" --preset dtrpg
|
|
@@ -126,8 +128,10 @@ gutterpress preview my-book
|
|
|
126
128
|
|
|
127
129
|
Then insert the *Toc Page*, *Credits Page* and *Chapter Start Page* snippets
|
|
128
130
|
to lay down the front matter, and reach for *Skill*, *Learning Path* and
|
|
129
|
-
*Specialty* as you write. `
|
|
130
|
-
|
|
131
|
+
*Specialty* as you write. The `dtrpg` preset sets the sheet, Letter with
|
|
132
|
+
bleed. The look's page margins are a starting point: from Gutterpress
|
|
133
|
+
0.11.23, Book setup > Book > Margins (`page.margin` in the manifest) sets
|
|
134
|
+
the book's own, and the full-bleed plates and named pages keep theirs.
|
|
131
135
|
|
|
132
136
|
## Author overrides
|
|
133
137
|
|
|
@@ -229,7 +233,11 @@ gutterpress ext add gp-dimm-city@1.5.0 my-book
|
|
|
229
233
|
```
|
|
230
234
|
|
|
231
235
|
Installing a version removes the book's copies of other versions of this
|
|
232
|
-
package, so there is nothing to clean up by hand.
|
|
236
|
+
package, so there is nothing to clean up by hand. A book vendored before
|
|
237
|
+
Gutterpress 0.11.23 keeps working from its `plugins/npm/` copy until its next
|
|
238
|
+
`ext add` or `ext update`, which moves the package to `extensions/npm/`, removes
|
|
239
|
+
the old copies and the empty `plugins/` folder, and replaces the `.gitignore`
|
|
240
|
+
line. Commit the manifest change.
|
|
233
241
|
|
|
234
242
|
Rebuild and compare before you commit — the Dimm City books gate every bump
|
|
235
243
|
with a render-parity run (text runs, image placement, and a pixel comparison
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gp-dimm-city",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Dimm City design system for Gutterpress: the markdown-it macros (@skill, @specialty, @learning-path, @callout, …), print stylesheets, design tokens, fonts and page templates the Dimm City TTRPG books are set in.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "plugin.js",
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
"styles/page-rules.css",
|
|
56
56
|
"styles/dc-native.css"
|
|
57
57
|
],
|
|
58
|
-
"tokensFile": "styles/dc-palette.css",
|
|
59
58
|
"components": "components.yaml",
|
|
60
59
|
"snippets": "snippets"
|
|
61
60
|
},
|
|
@@ -63,18 +62,17 @@
|
|
|
63
62
|
"dev": "gutterpress preview design-guide --open",
|
|
64
63
|
"build": "gutterpress build design-guide --format pdf --out .build/design-guide.pdf",
|
|
65
64
|
"build:html": "gutterpress build design-guide --format html --out .build/design-guide-site",
|
|
66
|
-
"lint": "gutterpress lint design-guide",
|
|
67
65
|
"test": "bun test",
|
|
68
66
|
"test:update-snapshot": "bun test --update-snapshots",
|
|
69
67
|
"book-diff": "bun scripts/book-diff.mjs",
|
|
70
68
|
"pack:check": "npm pack --dry-run"
|
|
71
69
|
},
|
|
72
70
|
"devDependencies": {
|
|
73
|
-
"gutterpress": "0.11.
|
|
71
|
+
"gutterpress": "0.11.23",
|
|
74
72
|
"markdown-it": "^14.1.0"
|
|
75
73
|
},
|
|
76
74
|
"engines": {
|
|
77
|
-
"gutterpress": ">=0.11.
|
|
75
|
+
"gutterpress": ">=0.11.22"
|
|
78
76
|
},
|
|
79
77
|
"peerDependencies": {
|
|
80
78
|
"markdown-it": ">=14"
|
package/plugin.js
CHANGED
|
@@ -386,9 +386,9 @@ const OUTCOME_NAMES = { crit: 'Crit', hit: 'Hit', mixed: 'Hard Choice', miss: 'M
|
|
|
386
386
|
// Any other set of bands (six bands, three, a split at 10) is NOT a ladder.
|
|
387
387
|
const LADDER_TIER_OF_BAND = { '20': 'crit', '11-19': 'hit', '6-10': 'mixed', '2-5': 'miss', '1': 'fail' };
|
|
388
388
|
|
|
389
|
-
// "11 – 19" → [11, 19], "**20**" → [20, 20]; anything that is not a number or a range → null.
|
|
389
|
+
// "11 – 19" → [11, 19], "11--19" → [11, 19], "**20**" → [20, 20]; anything that is not a number or a range → null.
|
|
390
390
|
function parseBand(cell) {
|
|
391
|
-
const text = cell.replace(/[*_`\s]/g, '').replace(/[\u2010-\u2015\u2212]/g, '-');
|
|
391
|
+
const text = cell.replace(/[*_`\s]/g, '').replace(/[\u2010-\u2015\u2212]|-{2,3}/g, '-');
|
|
392
392
|
const m = /^(\d{1,3})(?:-(\d{1,3}))?$/.exec(text);
|
|
393
393
|
if (!m) return null;
|
|
394
394
|
const [lo, hi] = [Number(m[1]), Number(m[2] ?? m[1])];
|
|
@@ -423,7 +423,7 @@ function outcomeRowsHtml(rows, md, head = []) {
|
|
|
423
423
|
: ' <div class="dc-outcomes-label">Outcomes</div>\n';
|
|
424
424
|
rows.forEach(({ tier, name, roll, text }) => {
|
|
425
425
|
html += ' <div class="dc-outcome-row ' + tier + '">\n';
|
|
426
|
-
html += ' <span class="dc-outcome-key tier-' + tier + '"><span class="dc-outcome-name">' + esc(name) + '</span><span class="dc-outcome-roll">' + esc(roll) + '</span></span>\n';
|
|
426
|
+
html += ' <span class="dc-outcome-key tier-' + tier + '"><span class="dc-outcome-name">' + esc(name) + '</span><span class="dc-outcome-roll">' + esc(roll.replace(/(\d)\s*--\s*(\d)/g, '$1\u2013$2')) + '</span></span>\n';
|
|
427
427
|
html += ' <span class="dc-outcome-text">' + md.renderInline(text) + '</span>\n';
|
|
428
428
|
html += ' </div>\n';
|
|
429
429
|
});
|
|
@@ -663,7 +663,8 @@ function dcAlertsTransform(state) {
|
|
|
663
663
|
if (closeIdx === -1 || firstInlineIdx === -1) { newTokens.push(tok); continue; }
|
|
664
664
|
|
|
665
665
|
const inlineTok = tokens[firstInlineIdx];
|
|
666
|
-
const
|
|
666
|
+
const lead = inlineTok && inlineTok.children && inlineTok.children[0];
|
|
667
|
+
const match = lead && lead.type === 'text' && inlineTok.content.match(DC_ALERT_PATTERN);
|
|
667
668
|
if (!match) { newTokens.push(tok); continue; }
|
|
668
669
|
|
|
669
670
|
const alertType = match[1].toUpperCase();
|
|
@@ -680,7 +681,8 @@ function dcAlertsTransform(state) {
|
|
|
680
681
|
newTokens.push(openTok);
|
|
681
682
|
|
|
682
683
|
// Strip [!TYPE] prefix from first inline; suppress its paragraph wrapper if empty.
|
|
683
|
-
const
|
|
684
|
+
const markerPrefix = /^\[![A-Z_]+\][ \t]*/i;
|
|
685
|
+
const prefixMatch = inlineTok.content.match(markerPrefix);
|
|
684
686
|
const stripped = prefixMatch
|
|
685
687
|
? inlineTok.content.slice(prefixMatch[0].length).trim()
|
|
686
688
|
: inlineTok.content;
|
|
@@ -697,11 +699,18 @@ function dcAlertsTransform(state) {
|
|
|
697
699
|
if (!t) continue;
|
|
698
700
|
if (j === firstInlineIdx) {
|
|
699
701
|
if (stripped === '') continue;
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
702
|
+
// The core rules have already typeset the children, so take the marker
|
|
703
|
+
// off the lead text (and the line break it leaves at the front) and
|
|
704
|
+
// keep the rest; re-parsing would skip replacements, smartquotes and
|
|
705
|
+
// text_join.
|
|
706
|
+
lead.content = lead.content.replace(markerPrefix, '');
|
|
707
|
+
if (lead.content === '') {
|
|
708
|
+
inlineTok.children.shift();
|
|
709
|
+
const next = inlineTok.children[0];
|
|
710
|
+
if (next && (next.type === 'softbreak' || next.type === 'hardbreak')) inlineTok.children.shift();
|
|
711
|
+
}
|
|
712
|
+
inlineTok.content = stripped;
|
|
713
|
+
newTokens.push(inlineTok);
|
|
705
714
|
continue;
|
|
706
715
|
}
|
|
707
716
|
if (stripped === '' && wrapsInParagraph) {
|
package/snippets/npc-stat.md
CHANGED
package/snippets/outcome.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
@outcome
|
|
2
2
|
|
|
3
3
|
20 | Triumph | {{triumph}}
|
|
4
|
-
11
|
|
5
|
-
6
|
|
6
|
-
2
|
|
4
|
+
11--19 | Success | {{success}}
|
|
5
|
+
6--10 | Hard Choice | {{hard-choice}}
|
|
6
|
+
2--5 | Failure | {{failure}}
|
|
7
7
|
1 | Catastrophe | {{catastrophe}}
|
|
8
8
|
|
|
9
9
|
@end-outcome
|
package/snippets/toc-page.md
CHANGED
package/snippets/toc.md
CHANGED
|
@@ -430,8 +430,8 @@ hr {
|
|
|
430
430
|
|
|
431
431
|
/* ── Specialty art full-page plate ─────────────────────────────────────────── */
|
|
432
432
|
.dc-specialty-art {
|
|
433
|
-
width: var(--page-width);
|
|
434
|
-
height: var(--page-height);
|
|
433
|
+
width: var(--gp-page-width, 8.625in);
|
|
434
|
+
height: var(--gp-page-height, 11.25in);
|
|
435
435
|
/* Its break is in page-templates.css (SPECIALTY BREAK CONTROL). */
|
|
436
436
|
margin: 0;
|
|
437
437
|
overflow: hidden;
|
package/styles/dc-palette.css
CHANGED
|
@@ -170,9 +170,10 @@
|
|
|
170
170
|
--outer-margin: 0.625in; /* outer (non-binding) page margin */
|
|
171
171
|
--sidebar-width: 3.05in;
|
|
172
172
|
|
|
173
|
-
/* ── Page Geometry ──────────────────────────────────────────────────────
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
/* ── Page Geometry ──────────────────────────────────────────────────────
|
|
174
|
+
The sheet is the book's (its manifest's preset or page size); a rule that
|
|
175
|
+
needs its size reads Gutterpress's --gp-page-width / --gp-page-height
|
|
176
|
+
(0.11.23 on), with the dtrpg sheet as the fallback for 0.11.22. */
|
|
176
177
|
--binding-margin: 0.5in;
|
|
177
178
|
|
|
178
179
|
/* ── Shapes ───────────────────────────────────────────────────────────── */
|
package/styles/page-rules.css
CHANGED
|
@@ -49,14 +49,12 @@
|
|
|
49
49
|
Default page template — Letter+bleed for DTRPG (8.625 x 11.25)
|
|
50
50
|
--------------------------------------------------------------------------- */
|
|
51
51
|
|
|
52
|
-
/*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
--page-height in dc-palette.css: change both together. */
|
|
52
|
+
/* The sheet size comes from the book's manifest: Gutterpress 0.11.23 writes
|
|
53
|
+
`@page { size }` after every stylesheet, so a `size` here is ignored and
|
|
54
|
+
reported. A rule that needs the sheet's size reads --gp-page-width /
|
|
55
|
+
--gp-page-height, which Gutterpress publishes from what it prints (0.11.23
|
|
56
|
+
on; the rules fall back to the dtrpg sheet on 0.11.22). */
|
|
58
57
|
@page {
|
|
59
|
-
size: 8.625in 11.25in;
|
|
60
58
|
margin: var(--page-margin) var(--outer-margin) var(--bottom-margin);
|
|
61
59
|
background-color: var(--bg);
|
|
62
60
|
}
|
|
@@ -93,10 +93,10 @@
|
|
|
93
93
|
/* Empty full-bleed pages need explicit geometry so the engine allocates a page.
|
|
94
94
|
The height is core's published content box for THIS page's context
|
|
95
95
|
(core's `gp-page-full-bleed` is margin: 0, so its content box IS the sheet)
|
|
96
|
-
rather than
|
|
96
|
+
rather than the sheet's height: a non-zero margin on that page would
|
|
97
97
|
push the plate past the page box with nothing to catch it. */
|
|
98
98
|
:is(.dc-full-page, .gp-page-full-bleed) {
|
|
99
|
-
width: var(--page-width);
|
|
99
|
+
width: var(--gp-page-width, 8.625in);
|
|
100
100
|
height: var(--gp-content-h, 11.25in);
|
|
101
101
|
background-color: var(--bg);
|
|
102
102
|
break-before: page;
|