@domandigital/craft 0.18.2 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/CHARACTER.md +77 -6
- package/README.md +1 -1
- package/STANDARD.md +48 -18
- package/dist/{audit-4SFSLCKY.js → audit-43PC4LMS.js} +3 -3
- package/dist/audit.cjs +24 -3
- package/dist/audit.d.cts +30 -1
- package/dist/audit.d.ts +30 -1
- package/dist/audit.js +24 -3
- package/dist/{chunk-DARKHE6A.js → chunk-37ARRJAD.js} +18 -7
- package/dist/{chunk-6TSDYETQ.js → chunk-4LJFZH2I.js} +29 -2
- package/dist/{chunk-4QWEAL4G.js → chunk-CZ7KT452.js} +93 -1
- package/dist/{chunk-O5B5ELJH.js → chunk-DUUDGR56.js} +14 -13
- package/dist/{chunk-NTIPJ5U7.js → chunk-OKVHWXYV.js} +3 -3
- package/dist/{chunk-ZUYERAFM.js → chunk-ORFILP5L.js} +5 -5
- package/dist/{chunk-RJVG5KA6.js → chunk-P37LLKL4.js} +38 -10
- package/dist/{chunk-SL5VZJ2J.js → chunk-VDUIIWG7.js} +3 -2
- package/dist/{chunk-WFB6F3BN.js → chunk-WK2WMWTH.js} +107 -9
- package/dist/{cli-GXIW7F3E.js → cli-3P44X6E3.js} +6 -6
- package/dist/{cli-JZRQBCD4.js → cli-4D7Q5BCE.js} +6 -6
- package/dist/{cli-MDW7JTEF.js → cli-7OUA6ZSE.js} +6 -6
- package/dist/{cli-V44QEVS6.js → cli-AACBHRUG.js} +10 -10
- package/dist/{cli-BN4IT6N2.js → cli-L3VGKWZH.js} +4 -4
- package/dist/{cli-Y7Y5IROK.js → cli-TH76ATN3.js} +5 -5
- package/dist/{cli-JB4X5LAG.js → cli-VPARW6FY.js} +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.cjs +279 -14
- package/dist/index.d.cts +111 -10
- package/dist/index.d.ts +111 -10
- package/dist/index.js +267 -14
- package/licences.json +27 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4042,8 +4042,100 @@ function markupParts(file) {
|
|
|
4042
4042
|
function textNodeIsProse(body) {
|
|
4043
4043
|
return /[a-zA-Z]{2,}/.test(body) && /\s/.test(body.trim()) || /[a-zA-Z]{4,}[.!?]/.test(body);
|
|
4044
4044
|
}
|
|
4045
|
+
var FRONT_MATTER_PROSE = /* @__PURE__ */ new Set(["title", "description"]);
|
|
4046
|
+
var KEY_LINE = /^(\s*)(?:-\s+)?([A-Za-z][\w-]*)[ \t]*:[ \t]*/;
|
|
4047
|
+
var BLOCK_SCALAR = /^(?:[|>][+-]?\d*|[|>]\d+[+-]?)$/;
|
|
4048
|
+
function readFrontKey(line) {
|
|
4049
|
+
const m = KEY_LINE.exec(line);
|
|
4050
|
+
if (!m) return null;
|
|
4051
|
+
return { indent: m[1].length, name: m[2], valueAt: m[0].length, value: line.slice(m[0].length) };
|
|
4052
|
+
}
|
|
4053
|
+
function indentOf(line) {
|
|
4054
|
+
let i = 0;
|
|
4055
|
+
while (i < line.length && (line[i] === " " || line[i] === " ")) i += 1;
|
|
4056
|
+
return i;
|
|
4057
|
+
}
|
|
4058
|
+
function commentAt(value) {
|
|
4059
|
+
if (value.startsWith("#")) return 0;
|
|
4060
|
+
const found = /[ \t]+#/.exec(value);
|
|
4061
|
+
return found ? found.index : -1;
|
|
4062
|
+
}
|
|
4063
|
+
function keepSpan(line, from, to) {
|
|
4064
|
+
const start = Math.max(0, Math.min(from, line.length));
|
|
4065
|
+
const end = Math.max(start, Math.min(to, line.length));
|
|
4066
|
+
return " ".repeat(start) + line.slice(start, end) + " ".repeat(line.length - end);
|
|
4067
|
+
}
|
|
4068
|
+
function quoteEnd(line, from, quote) {
|
|
4069
|
+
for (let i = from; i < line.length; i += 1) {
|
|
4070
|
+
if (quote === '"' && line[i] === "\\") {
|
|
4071
|
+
i += 1;
|
|
4072
|
+
continue;
|
|
4073
|
+
}
|
|
4074
|
+
if (quote === "'" && line[i] === "'" && line[i + 1] === "'") {
|
|
4075
|
+
i += 1;
|
|
4076
|
+
continue;
|
|
4077
|
+
}
|
|
4078
|
+
if (line[i] === quote) return i;
|
|
4079
|
+
}
|
|
4080
|
+
return -1;
|
|
4081
|
+
}
|
|
4082
|
+
function maskFrontMatter(block) {
|
|
4083
|
+
const lines = block.split("\n");
|
|
4084
|
+
const out = lines.map((line) => blank(line));
|
|
4085
|
+
for (let i = 1; i < lines.length; ) {
|
|
4086
|
+
const line = lines[i];
|
|
4087
|
+
if (line === "---" || line === "...") break;
|
|
4088
|
+
const key = readFrontKey(line);
|
|
4089
|
+
if (!key || !FRONT_MATTER_PROSE.has(key.name.toLowerCase())) {
|
|
4090
|
+
i += 1;
|
|
4091
|
+
continue;
|
|
4092
|
+
}
|
|
4093
|
+
const quote = key.value.startsWith('"') ? '"' : key.value.startsWith("'") ? "'" : "";
|
|
4094
|
+
if (quote) {
|
|
4095
|
+
let cursor = key.valueAt + 1;
|
|
4096
|
+
while (i < lines.length && lines[i] !== "---" && lines[i] !== "...") {
|
|
4097
|
+
const current = lines[i];
|
|
4098
|
+
const end = quoteEnd(current, cursor, quote);
|
|
4099
|
+
out[i] = keepSpan(current, cursor, end === -1 ? current.length : end);
|
|
4100
|
+
i += 1;
|
|
4101
|
+
cursor = 0;
|
|
4102
|
+
if (end !== -1) break;
|
|
4103
|
+
}
|
|
4104
|
+
continue;
|
|
4105
|
+
}
|
|
4106
|
+
const hash = commentAt(key.value);
|
|
4107
|
+
const body = (hash === -1 ? key.value : key.value.slice(0, hash)).trim();
|
|
4108
|
+
if (BLOCK_SCALAR.test(body)) {
|
|
4109
|
+
i += 1;
|
|
4110
|
+
while (i < lines.length && lines[i] !== "---" && lines[i] !== "...") {
|
|
4111
|
+
const current = lines[i];
|
|
4112
|
+
if (current.trim() !== "" && indentOf(current) <= key.indent) break;
|
|
4113
|
+
if (current.trim()) out[i] = current;
|
|
4114
|
+
i += 1;
|
|
4115
|
+
}
|
|
4116
|
+
continue;
|
|
4117
|
+
}
|
|
4118
|
+
if (body === "" || body === "~" || /^null$/i.test(body) || body.startsWith("[") || body.startsWith("{")) {
|
|
4119
|
+
i += 1;
|
|
4120
|
+
continue;
|
|
4121
|
+
}
|
|
4122
|
+
out[i] = keepSpan(line, key.valueAt, hash === -1 ? line.length : key.valueAt + hash);
|
|
4123
|
+
i += 1;
|
|
4124
|
+
while (i < lines.length && lines[i] !== "---" && lines[i] !== "...") {
|
|
4125
|
+
const current = lines[i];
|
|
4126
|
+
if (current.trim() === "" || indentOf(current) <= key.indent) break;
|
|
4127
|
+
if (!/^\s*#/.test(current)) {
|
|
4128
|
+
const cut = commentAt(current);
|
|
4129
|
+
out[i] = cut === -1 ? current : keepSpan(current, 0, cut);
|
|
4130
|
+
}
|
|
4131
|
+
i += 1;
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
const masked = out.join("\n");
|
|
4135
|
+
return masked.length === block.length ? masked : blank(block);
|
|
4136
|
+
}
|
|
4045
4137
|
function proseBlocks(file) {
|
|
4046
|
-
const masked = file.text.replace(/^(```|~~~)[\s\S]*?^\1/gm, blank).replace(/`[^`\n]*`/g, (m) => " ".repeat(m.length)).replace(/^---\n[\s\S]*?\n---\n/,
|
|
4138
|
+
const masked = file.text.replace(/^(```|~~~)[\s\S]*?^\1/gm, blank).replace(/`[^`\n]*`/g, (m) => " ".repeat(m.length)).replace(/^---\n[\s\S]*?\n---\n/, (block) => maskFrontMatter(block)).replace(/<!--[\s\S]*?-->/g, blank);
|
|
4047
4139
|
return [{ path: file.path, text: masked, offset: 0 }];
|
|
4048
4140
|
}
|
|
4049
4141
|
function isData(path) {
|
|
@@ -5031,7 +5123,7 @@ var RENDERED_PATHS = {
|
|
|
5031
5123
|
};
|
|
5032
5124
|
|
|
5033
5125
|
// src/fingerprint/index.ts
|
|
5034
|
-
var FINGERPRINT_VERSION =
|
|
5126
|
+
var FINGERPRINT_VERSION = 3;
|
|
5035
5127
|
var CHROMATIC = 0.03;
|
|
5036
5128
|
var MIN_ACCENT_AREA = 2e4;
|
|
5037
5129
|
var oklch = (value) => {
|
|
@@ -5067,6 +5159,24 @@ function median(values) {
|
|
|
5067
5159
|
const mid = Math.floor(sorted.length / 2);
|
|
5068
5160
|
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
5069
5161
|
}
|
|
5162
|
+
var FULL_WIDTH_IMAGE = 0.8;
|
|
5163
|
+
function heroOf(s) {
|
|
5164
|
+
const h1 = s.headings.find((h) => h.level === 1);
|
|
5165
|
+
const inside = (top, x) => top >= x.top && top < x.top + x.height;
|
|
5166
|
+
const index = (() => {
|
|
5167
|
+
const withH1 = h1 ? s.sections.findIndex((x) => x.kind === "hero" && inside(h1.top, x)) : -1;
|
|
5168
|
+
return withH1 >= 0 ? withH1 : s.sections.findIndex((x) => x.kind === "hero");
|
|
5169
|
+
})();
|
|
5170
|
+
if (index < 0) return void 0;
|
|
5171
|
+
const section = s.sections[index];
|
|
5172
|
+
const headline = h1 && inside(h1.top, section) ? { sizePx: h1.sizePx, weight: h1.weight, class: fontClass(normaliseFamily(h1.family)), italic: h1.italic || h1.italicPart } : null;
|
|
5173
|
+
if (!s.images) return { headline };
|
|
5174
|
+
const picture2 = s.images.filter((i) => (i.role === "photo" || i.role === "illustration") && (i.section === index || i.section === null && inside(i.top, section))).sort((a, b) => b.width * b.height - a.width * a.height)[0];
|
|
5175
|
+
if (!picture2) return { headline, image: "none" };
|
|
5176
|
+
if (picture2.left === void 0) return { headline };
|
|
5177
|
+
const image = picture2.width >= FULL_WIDTH_IMAGE * s.viewport.width ? "full" : picture2.left + picture2.width / 2 < s.viewport.width / 2 ? "left" : "right";
|
|
5178
|
+
return { headline, image };
|
|
5179
|
+
}
|
|
5070
5180
|
function fingerprint(s) {
|
|
5071
5181
|
const effects = [];
|
|
5072
5182
|
if (s.effects.glass > 0) effects.push("glass-panel");
|
|
@@ -5078,6 +5188,7 @@ function fingerprint(s) {
|
|
|
5078
5188
|
if (s.effects.eyebrowChip) effects.push("hero-eyebrow-chip");
|
|
5079
5189
|
if (s.motion.introOverlay) effects.push("intro-cinematic");
|
|
5080
5190
|
const below = s.sections.filter((x) => x.top > s.viewport.height).length;
|
|
5191
|
+
const hero = heroOf(s);
|
|
5081
5192
|
return {
|
|
5082
5193
|
version: FINGERPRINT_VERSION,
|
|
5083
5194
|
accent: accentOf(s),
|
|
@@ -5101,10 +5212,28 @@ function fingerprint(s) {
|
|
|
5101
5212
|
carousel: x.carousel ?? false,
|
|
5102
5213
|
figures: x.figures ?? 0
|
|
5103
5214
|
}))
|
|
5104
|
-
} : {}
|
|
5215
|
+
} : {},
|
|
5216
|
+
...hero ? { hero } : {}
|
|
5105
5217
|
};
|
|
5106
5218
|
}
|
|
5107
|
-
var
|
|
5219
|
+
var WARM_HUE = [
|
|
5220
|
+
[330, 360],
|
|
5221
|
+
[0, 130]
|
|
5222
|
+
];
|
|
5223
|
+
var COOL_HUE = [[160, 310]];
|
|
5224
|
+
var TEMPERATURE_FULL = 6e-3;
|
|
5225
|
+
var TEMPERATURE_NAMED = 0.4;
|
|
5226
|
+
function groundTemperature(o) {
|
|
5227
|
+
const h = (o.h % 360 + 360) % 360;
|
|
5228
|
+
const within = (bands) => bands.some(([lo, hi]) => h >= lo && h < hi);
|
|
5229
|
+
const strength = Math.min(1, o.c / TEMPERATURE_FULL);
|
|
5230
|
+
return within(WARM_HUE) ? strength : within(COOL_HUE) ? -strength : 0;
|
|
5231
|
+
}
|
|
5232
|
+
function temperatureName(o) {
|
|
5233
|
+
const t = groundTemperature(o);
|
|
5234
|
+
return t >= TEMPERATURE_NAMED ? "warm" : t <= -TEMPERATURE_NAMED ? "cool" : "neutral";
|
|
5235
|
+
}
|
|
5236
|
+
var DISTANCE_WEIGHTS = { accent: 0.2, type: 0.2, ground: 0.1, shape: 0.1, motion: 0.05, effects: 0.1, layout: 0.1, rhythm: 0.1, hero: 0.05 };
|
|
5108
5237
|
function levenshtein(a, b, cost = (x, y) => x === y ? 0 : 1) {
|
|
5109
5238
|
const row = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
5110
5239
|
for (let i = 1; i <= a.length; i += 1) {
|
|
@@ -5131,18 +5260,62 @@ function layoutDistance(a, b) {
|
|
|
5131
5260
|
return longest === 0 ? 0 : levenshtein(a.layout, b.layout) / longest;
|
|
5132
5261
|
}
|
|
5133
5262
|
var clamp = (n) => Math.max(0, Math.min(1, n));
|
|
5263
|
+
function bandOf(l) {
|
|
5264
|
+
return l < 0.4 ? "dark" : l >= 0.75 ? "light" : "mid";
|
|
5265
|
+
}
|
|
5266
|
+
function rhythmOf(fp) {
|
|
5267
|
+
if (!fp.sections) return null;
|
|
5268
|
+
const out = [];
|
|
5269
|
+
for (const s of fp.sections) {
|
|
5270
|
+
if (s.background === void 0) return null;
|
|
5271
|
+
const band = bandOf((s.background ?? fp.ground).l);
|
|
5272
|
+
if (out[out.length - 1] !== band) out.push(band);
|
|
5273
|
+
}
|
|
5274
|
+
return out;
|
|
5275
|
+
}
|
|
5276
|
+
var OPENING_BANDS = 3;
|
|
5277
|
+
function rhythmDistance(a, b) {
|
|
5278
|
+
const ra = rhythmOf(a);
|
|
5279
|
+
const rb = rhythmOf(b);
|
|
5280
|
+
if (!ra || !rb) return null;
|
|
5281
|
+
const over = (x, y) => {
|
|
5282
|
+
const longest = Math.max(x.length, y.length);
|
|
5283
|
+
return longest === 0 ? 0 : levenshtein(x, y) / longest;
|
|
5284
|
+
};
|
|
5285
|
+
return (over(ra.slice(0, OPENING_BANDS), rb.slice(0, OPENING_BANDS)) + over(ra, rb)) / 2;
|
|
5286
|
+
}
|
|
5287
|
+
var HEADLINE_OCTAVES = 1;
|
|
5288
|
+
function heroSection(fp) {
|
|
5289
|
+
return fp.sections?.find((s) => s.role === "hero");
|
|
5290
|
+
}
|
|
5291
|
+
function heroDistance(a, b) {
|
|
5292
|
+
const sa = heroSection(a);
|
|
5293
|
+
const sb = heroSection(b);
|
|
5294
|
+
if (!sa || !sb) return null;
|
|
5295
|
+
const parts2 = [Math.abs(sa.centred - sb.centred), clamp(Math.abs(sa.width - sb.width) / 0.5)];
|
|
5296
|
+
const ha = a.hero?.headline;
|
|
5297
|
+
const hb = b.hero?.headline;
|
|
5298
|
+
if (ha && hb) parts2.push(0.5 * (ha.class === hb.class ? 0 : 1) + 0.5 * clamp(Math.abs(Math.log2(ha.sizePx / hb.sizePx)) / HEADLINE_OCTAVES));
|
|
5299
|
+
else if (a.hero && b.hero && (ha || hb)) parts2.push(1);
|
|
5300
|
+
if (a.hero?.image && b.hero?.image) parts2.push(a.hero.image === b.hero.image ? 0 : 1);
|
|
5301
|
+
return parts2.reduce((s, p) => s + p, 0) / parts2.length;
|
|
5302
|
+
}
|
|
5134
5303
|
function faceDistance(a, b) {
|
|
5135
5304
|
if (a.family.toLowerCase() === b.family.toLowerCase()) return 0;
|
|
5136
5305
|
return a.class === b.class ? 0.5 : 1;
|
|
5137
5306
|
}
|
|
5138
5307
|
var ACCENT_SCALE = 0.3;
|
|
5139
5308
|
var GROUND_SCALE = 0.15;
|
|
5309
|
+
var TEMPERATURE_WEIGHT = 0.6;
|
|
5140
5310
|
var SHARED_PART = 0.2;
|
|
5141
5311
|
var ACCENT_SHARED = ACCENT_SCALE * SHARED_PART;
|
|
5142
5312
|
var GROUND_SHARED = GROUND_SCALE * SHARED_PART;
|
|
5313
|
+
function groundDistance(a, b) {
|
|
5314
|
+
return clamp(deltaEOk(a, b) / GROUND_SCALE + TEMPERATURE_WEIGHT * Math.abs(groundTemperature(a) - groundTemperature(b)) / 2);
|
|
5315
|
+
}
|
|
5143
5316
|
function fingerprintDistance(a, b) {
|
|
5144
5317
|
const accent = a.accent && b.accent ? clamp(deltaEOk(a.accent, b.accent) / ACCENT_SCALE) : a.accent || b.accent ? 1 : 0;
|
|
5145
|
-
const ground =
|
|
5318
|
+
const ground = groundDistance(a.ground, b.ground);
|
|
5146
5319
|
const type = 0.6 * faceDistance(a.display, b.display) + 0.4 * faceDistance(a.body, b.body);
|
|
5147
5320
|
const shape = a.roundness === null || b.roundness === null ? a.roundness === b.roundness ? 0 : 0.5 : clamp(Math.abs(a.roundness - b.roundness) / 0.5);
|
|
5148
5321
|
const motion = clamp(Math.abs(a.motion - b.motion));
|
|
@@ -5150,9 +5323,18 @@ function fingerprintDistance(a, b) {
|
|
|
5150
5323
|
const shared = a.effects.filter((e) => b.effects.includes(e)).length;
|
|
5151
5324
|
const effects = union.size === 0 ? 0 : 1 - shared / union.size;
|
|
5152
5325
|
const layout = layoutDistance(a, b);
|
|
5153
|
-
const
|
|
5154
|
-
const
|
|
5155
|
-
|
|
5326
|
+
const rhythm = rhythmDistance(a, b);
|
|
5327
|
+
const hero = heroDistance(a, b);
|
|
5328
|
+
const parts2 = { accent, ground, type, shape, motion, effects, layout, rhythm, hero };
|
|
5329
|
+
let sum = 0;
|
|
5330
|
+
let weight = 0;
|
|
5331
|
+
for (const k of Object.keys(DISTANCE_WEIGHTS)) {
|
|
5332
|
+
const p = parts2[k];
|
|
5333
|
+
if (p === null) continue;
|
|
5334
|
+
sum += DISTANCE_WEIGHTS[k] * p;
|
|
5335
|
+
weight += DISTANCE_WEIGHTS[k];
|
|
5336
|
+
}
|
|
5337
|
+
return { total: Math.round(sum / weight * 1e3) / 1e3, parts: parts2 };
|
|
5156
5338
|
}
|
|
5157
5339
|
function nearest(target2, set, k = set.length) {
|
|
5158
5340
|
return set.map((item) => ({ id: item.id, distance: fingerprintDistance(target2, item.fingerprint) })).sort((x, y) => x.distance.total - y.distance.total).slice(0, k);
|
|
@@ -5230,6 +5412,12 @@ function groundName(o) {
|
|
|
5230
5412
|
if (o.l >= 0.97 && o.c < 0.012) return "white";
|
|
5231
5413
|
return o.c < 0.02 ? "grey" : "tinted";
|
|
5232
5414
|
}
|
|
5415
|
+
function groundLabel(o) {
|
|
5416
|
+
const name = groundName(o);
|
|
5417
|
+
if (name === "cream" || name === "tinted") return name;
|
|
5418
|
+
const temperature = temperatureName(o);
|
|
5419
|
+
return temperature === "neutral" ? name : `${temperature} ${name}`;
|
|
5420
|
+
}
|
|
5233
5421
|
function shapeName(roundness) {
|
|
5234
5422
|
if (roundness === null) return "no buttons";
|
|
5235
5423
|
if (roundness >= 0.45) return "pill";
|
|
@@ -8504,6 +8692,33 @@ var LICENCES = [
|
|
|
8504
8692
|
checked: "2026-09-24",
|
|
8505
8693
|
source: "https://iconscout.com/licenses",
|
|
8506
8694
|
note: "Each licence covers a single end product. Never in a tool, template or shared kit (create-site, craft, a house component library), even modified. Record the assets each site uses. Assets come from different contributors, so take one site's set from one contributor."
|
|
8695
|
+
},
|
|
8696
|
+
{
|
|
8697
|
+
name: "Saira Semi Condensed",
|
|
8698
|
+
subject: "face",
|
|
8699
|
+
licence: "OFL-1.1",
|
|
8700
|
+
multiClient: "yes",
|
|
8701
|
+
checked: "2026-10-09",
|
|
8702
|
+
source: "https://github.com/google/fonts/blob/main/ofl/sairasemicondensed/OFL.txt",
|
|
8703
|
+
note: "Copyright 2016 The Saira Project Authors (omnibus.type@gmail.com), reserved font name Saira. Keep the OFL notice with the font files; a modified build may not be called Saira. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
8704
|
+
},
|
|
8705
|
+
{
|
|
8706
|
+
name: "Public Sans",
|
|
8707
|
+
subject: "face",
|
|
8708
|
+
licence: "OFL-1.1",
|
|
8709
|
+
multiClient: "yes",
|
|
8710
|
+
checked: "2026-10-09",
|
|
8711
|
+
source: "https://github.com/google/fonts/blob/main/ofl/publicsans/OFL.txt",
|
|
8712
|
+
note: "Copyright 2015 The Public Sans Project Authors (https://github.com/uswds/public-sans). Keep the OFL notice with the font files. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
8713
|
+
},
|
|
8714
|
+
{
|
|
8715
|
+
name: "Martian Mono",
|
|
8716
|
+
subject: "face",
|
|
8717
|
+
licence: "OFL-1.1",
|
|
8718
|
+
multiClient: "yes",
|
|
8719
|
+
checked: "2026-10-09",
|
|
8720
|
+
source: "https://github.com/google/fonts/blob/main/ofl/martianmono/OFL.txt",
|
|
8721
|
+
note: "Copyright 2021 The Martian Mono Project Authors (https://github.com/evilmartians/mono). Keep the OFL notice with the font files. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
8507
8722
|
}
|
|
8508
8723
|
];
|
|
8509
8724
|
function faceLicence(family) {
|
|
@@ -8870,7 +9085,7 @@ var PART_AREA = {
|
|
|
8870
9085
|
effects: { area: "effects", choice: "motif" },
|
|
8871
9086
|
motion: { area: "motion", choice: "signature" }
|
|
8872
9087
|
};
|
|
8873
|
-
var DEFAULTS = /^(?:ground )?(?:white|grey)(?: ground)?$|no scroll reveals|no reveals|accent (?:none|neutral)|^no buttons|shape no buttons
|
|
9088
|
+
var DEFAULTS = /^(?:ground )?(?:white|grey|light)(?: ground)?$|no scroll reveals|no reveals|accent (?:none|neutral)|^no buttons|shape no buttons|^light page throughout$/;
|
|
8874
9089
|
function designFindings(findings, copyTells) {
|
|
8875
9090
|
return (findings?.findings ?? []).filter((f4) => !copyTells.has(f4.tell));
|
|
8876
9091
|
}
|
|
@@ -8977,7 +9192,7 @@ function areaOfShared(part) {
|
|
|
8977
9192
|
if (/accent|ground/.test(part)) return "colour";
|
|
8978
9193
|
if (/buttons/.test(part)) return "shape";
|
|
8979
9194
|
if (/reveal/.test(part)) return "motion";
|
|
8980
|
-
if (/running order/.test(part)) return "layout";
|
|
9195
|
+
if (/running order|hero|page throughout/.test(part)) return "layout";
|
|
8981
9196
|
return "effects";
|
|
8982
9197
|
}
|
|
8983
9198
|
function choiceOfShared(part) {
|
|
@@ -8987,7 +9202,7 @@ function choiceOfShared(part) {
|
|
|
8987
9202
|
if (/ground/.test(part)) return "ground";
|
|
8988
9203
|
if (/buttons/.test(part)) return "shape";
|
|
8989
9204
|
if (/reveal/.test(part)) return "signature";
|
|
8990
|
-
return /running order/.test(part) ? void 0 : "motif";
|
|
9205
|
+
return /running order|hero|page throughout/.test(part) ? void 0 : "motif";
|
|
8991
9206
|
}
|
|
8992
9207
|
|
|
8993
9208
|
// src/calibrate/index.ts
|
|
@@ -9094,19 +9309,45 @@ function addSite(register, site) {
|
|
|
9094
9309
|
const sites = [...register.sites.filter((s) => s.id !== site.id), site].sort((a, b) => a.id.localeCompare(b.id));
|
|
9095
9310
|
return { version: ESTATE_VERSION, sites };
|
|
9096
9311
|
}
|
|
9312
|
+
function sharedGround(a, b) {
|
|
9313
|
+
const [x, y] = [groundLabel(a.ground), groundLabel(b.ground)];
|
|
9314
|
+
if (x === y) return `${x} ground`;
|
|
9315
|
+
const temperature = temperatureName(a.ground);
|
|
9316
|
+
if (temperature !== "neutral" && temperature === temperatureName(b.ground)) return `${temperature} ground`;
|
|
9317
|
+
return `${a.ground.l < 0.3 ? "dark" : "light"} ground`;
|
|
9318
|
+
}
|
|
9319
|
+
function sharedRhythm(a, b) {
|
|
9320
|
+
const bands = rhythmOf(a) ?? [];
|
|
9321
|
+
const word = (band) => band;
|
|
9322
|
+
if (bands.length <= 1) return `${bands[0] ? word(bands[0]) : "light"} page throughout`;
|
|
9323
|
+
const second = bands[1] === "mid" ? "mid-tone band" : `${word(bands[1])} band`;
|
|
9324
|
+
return `${word(bands[0])} hero then ${second}`;
|
|
9325
|
+
}
|
|
9326
|
+
function sharedHero(a, b) {
|
|
9327
|
+
const hero = a.sections?.find((s) => s.role === "hero");
|
|
9328
|
+
const placement = hero && hero.centred >= 0.5 ? "centred" : "left-aligned";
|
|
9329
|
+
const headline = a.hero?.headline && b.hero?.headline && a.hero.headline.class === b.hero.headline.class ? `${a.hero.headline.class} ` : "";
|
|
9330
|
+
const image = a.hero?.image && a.hero.image === b.hero?.image && a.hero.image !== "none" ? `, ${a.hero.image === "full" ? "full-width picture" : `photo ${a.hero.image}`}` : "";
|
|
9331
|
+
return `${placement} ${headline}hero${image}`;
|
|
9332
|
+
}
|
|
9097
9333
|
function sharedParts(a, b, d = fingerprintDistance(a, b)) {
|
|
9098
9334
|
const out = [];
|
|
9099
|
-
const close = (k) =>
|
|
9335
|
+
const close = (k) => {
|
|
9336
|
+
const p = d.parts[k];
|
|
9337
|
+
return p !== null && p <= SHARED_PART;
|
|
9338
|
+
};
|
|
9100
9339
|
if (close("accent")) out.push(a.accent || b.accent ? `${hueName(a.accent)} accent` : "no accent");
|
|
9101
9340
|
if (close("type")) {
|
|
9102
9341
|
if (a.display.family === b.display.family) out.push(`${a.display.family} headline`);
|
|
9103
9342
|
if (a.body.family === b.body.family) out.push(`${a.body.family} body`);
|
|
9104
9343
|
}
|
|
9105
|
-
if (close("ground")) out.push(
|
|
9344
|
+
if (close("ground")) out.push(sharedGround(a, b));
|
|
9106
9345
|
if (close("shape")) out.push(`${shapeName(a.roundness)} buttons`);
|
|
9107
9346
|
if (close("motion")) out.push(a.motion > 0 || b.motion > 0 ? "scroll reveals" : "no reveals");
|
|
9108
9347
|
if (close("effects") && a.effects.length) out.push(a.effects.filter((e) => b.effects.includes(e)).join(", "));
|
|
9109
|
-
if (close("
|
|
9348
|
+
if (close("hero")) out.push(sharedHero(a, b));
|
|
9349
|
+
if (close("rhythm")) out.push(sharedRhythm(a, b));
|
|
9350
|
+
if (close("layout")) out.push("same running order");
|
|
9110
9351
|
return out;
|
|
9111
9352
|
}
|
|
9112
9353
|
function compareToEstate(target2, register, options = {}) {
|
|
@@ -9245,6 +9486,7 @@ export {
|
|
|
9245
9486
|
MOOD,
|
|
9246
9487
|
NEGATIVE_REASSURANCE,
|
|
9247
9488
|
NULL_VERSION,
|
|
9489
|
+
OPENING_BANDS,
|
|
9248
9490
|
PAGE_TYPES,
|
|
9249
9491
|
PILL_LIMIT,
|
|
9250
9492
|
PLAINER_WORDS,
|
|
@@ -9288,6 +9530,9 @@ export {
|
|
|
9288
9530
|
STOCK_PHRASES,
|
|
9289
9531
|
STUDY_WORDS,
|
|
9290
9532
|
TELL_HEAVY,
|
|
9533
|
+
TEMPERATURE_FULL,
|
|
9534
|
+
TEMPERATURE_NAMED,
|
|
9535
|
+
TEMPERATURE_WEIGHT,
|
|
9291
9536
|
TRADE_NOUNS,
|
|
9292
9537
|
TYPE_STEPS,
|
|
9293
9538
|
TYPICAL_AT,
|
|
@@ -9299,6 +9544,7 @@ export {
|
|
|
9299
9544
|
applyHouseGate,
|
|
9300
9545
|
applySeverity,
|
|
9301
9546
|
auditSnapshot,
|
|
9547
|
+
bandOf,
|
|
9302
9548
|
briefTerms,
|
|
9303
9549
|
calibrate,
|
|
9304
9550
|
catalogueTable,
|
|
@@ -9362,10 +9608,14 @@ export {
|
|
|
9362
9608
|
globToRegExp,
|
|
9363
9609
|
gradientContrast,
|
|
9364
9610
|
gradientStops,
|
|
9611
|
+
groundDistance,
|
|
9612
|
+
groundLabel,
|
|
9365
9613
|
groundName,
|
|
9614
|
+
groundTemperature,
|
|
9366
9615
|
harvest,
|
|
9367
9616
|
hedgeCount,
|
|
9368
9617
|
hedgedClose,
|
|
9618
|
+
heroDistance,
|
|
9369
9619
|
hexToOklch,
|
|
9370
9620
|
holdHouseBlocks,
|
|
9371
9621
|
houseRule,
|
|
@@ -9413,6 +9663,8 @@ export {
|
|
|
9413
9663
|
renderedOrder,
|
|
9414
9664
|
researchPrompt,
|
|
9415
9665
|
retrofitPlan,
|
|
9666
|
+
rhythmDistance,
|
|
9667
|
+
rhythmOf,
|
|
9416
9668
|
runTell,
|
|
9417
9669
|
scanProvenance,
|
|
9418
9670
|
scanSource,
|
|
@@ -9439,6 +9691,7 @@ export {
|
|
|
9439
9691
|
tailwindV3Preset,
|
|
9440
9692
|
tailwindV4Theme,
|
|
9441
9693
|
tellById,
|
|
9694
|
+
temperatureName,
|
|
9442
9695
|
toGamut,
|
|
9443
9696
|
toJson,
|
|
9444
9697
|
toSarif,
|
package/licences.json
CHANGED
|
@@ -99,6 +99,33 @@
|
|
|
99
99
|
"checked": "2026-09-24",
|
|
100
100
|
"source": "https://iconscout.com/licenses",
|
|
101
101
|
"note": "Each licence covers a single end product. Never in a tool, template or shared kit (create-site, craft, a house component library), even modified. Record the assets each site uses. Assets come from different contributors, so take one site's set from one contributor."
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "Saira Semi Condensed",
|
|
105
|
+
"subject": "face",
|
|
106
|
+
"licence": "OFL-1.1",
|
|
107
|
+
"multiClient": "yes",
|
|
108
|
+
"checked": "2026-10-09",
|
|
109
|
+
"source": "https://github.com/google/fonts/blob/main/ofl/sairasemicondensed/OFL.txt",
|
|
110
|
+
"note": "Copyright 2016 The Saira Project Authors (omnibus.type@gmail.com), reserved font name Saira. Keep the OFL notice with the font files; a modified build may not be called Saira. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "Public Sans",
|
|
114
|
+
"subject": "face",
|
|
115
|
+
"licence": "OFL-1.1",
|
|
116
|
+
"multiClient": "yes",
|
|
117
|
+
"checked": "2026-10-09",
|
|
118
|
+
"source": "https://github.com/google/fonts/blob/main/ofl/publicsans/OFL.txt",
|
|
119
|
+
"note": "Copyright 2015 The Public Sans Project Authors (https://github.com/uswds/public-sans). Keep the OFL notice with the font files. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "Martian Mono",
|
|
123
|
+
"subject": "face",
|
|
124
|
+
"licence": "OFL-1.1",
|
|
125
|
+
"multiClient": "yes",
|
|
126
|
+
"checked": "2026-10-09",
|
|
127
|
+
"source": "https://github.com/google/fonts/blob/main/ofl/martianmono/OFL.txt",
|
|
128
|
+
"note": "Copyright 2021 The Martian Mono Project Authors (https://github.com/evilmartians/mono). Keep the OFL notice with the font files. Chosen for Doman Digital's own site (DOM-397, 9 October 2026)."
|
|
102
129
|
}
|
|
103
130
|
]
|
|
104
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domandigital/craft",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The Doman Digital house craft standard as numbers: OKLCh colour ramps that snap to existing anchors, derived semantic tokens with measured WCAG and APCA contrast, one shared motion vocabulary for CSS and JS, and a base stylesheet. Zero dependencies.",
|
|
6
6
|
"license": "Apache-2.0",
|