@domandigital/craft 0.18.1 → 0.19.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 +12 -0
- package/CHARACTER.md +93 -6
- package/dist/{audit-4SFSLCKY.js → audit-X7LGATAQ.js} +2 -2
- 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-O5B5ELJH.js → chunk-GNVZGG3E.js} +12 -11
- package/dist/{chunk-WFB6F3BN.js → chunk-IHT6CJOM.js} +106 -8
- package/dist/{chunk-DARKHE6A.js → chunk-J35UYAVV.js} +18 -7
- package/dist/{chunk-RJVG5KA6.js → chunk-LWKMGJSW.js} +38 -10
- package/dist/{chunk-ZUYERAFM.js → chunk-NCBCZFDY.js} +4 -4
- package/dist/{chunk-NTIPJ5U7.js → chunk-OKVHWXYV.js} +3 -3
- package/dist/{chunk-6TSDYETQ.js → chunk-RNHV2SXC.js} +28 -1
- package/dist/{chunk-SL5VZJ2J.js → chunk-W7PMRSDG.js} +3 -2
- package/dist/{cli-BN4IT6N2.js → cli-3WWHRJRG.js} +3 -3
- package/dist/{cli-Y7Y5IROK.js → cli-DKI37OXK.js} +4 -4
- package/dist/{cli-V44QEVS6.js → cli-KXVJJDN5.js} +9 -9
- package/dist/{cli-GXIW7F3E.js → cli-U7WEVPZL.js} +5 -5
- package/dist/{cli-MDW7JTEF.js → cli-YD3VN52R.js} +5 -5
- package/dist/{cli-JZRQBCD4.js → cli-ZGB6MUN2.js} +5 -5
- package/dist/cli.js +2 -2
- package/dist/index.cjs +186 -13
- package/dist/index.d.cts +111 -10
- package/dist/index.d.ts +111 -10
- package/dist/index.js +174 -13
- package/licences.json +27 -0
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -914,6 +914,8 @@ interface SnapshotImage {
|
|
|
914
914
|
width: number;
|
|
915
915
|
height: number;
|
|
916
916
|
top: number;
|
|
917
|
+
/** Version 2, craft 0.19 and later: distance from the viewport's left edge, so a hero can say which side its picture sits. */
|
|
918
|
+
left?: number;
|
|
917
919
|
role: ImageRole;
|
|
918
920
|
alt: string | null;
|
|
919
921
|
/** Empty alt, `aria-hidden` or `role="presentation"`. */
|
|
@@ -2228,8 +2230,14 @@ declare function visualMeasures(img: RgbaImage, maxSamples?: number): SnapshotVi
|
|
|
2228
2230
|
* comparison involving it uses `layout` exactly as version 1 did, so the null
|
|
2229
2231
|
* models and the estate register compare as they were calibrated until they
|
|
2230
2232
|
* are re-snapshotted.
|
|
2233
|
+
*
|
|
2234
|
+
* 3 adds `hero` (the headline's size and where the hero's picture sits).
|
|
2235
|
+
* Rhythm, the sequence of light and dark bands, is read from the version 2
|
|
2236
|
+
* `sections`, so a version 2 fingerprint measures it without a fresh
|
|
2237
|
+
* snapshot. A part neither side carries is left out of the distance rather
|
|
2238
|
+
* than counted as different (see `fingerprintDistance`).
|
|
2231
2239
|
*/
|
|
2232
|
-
declare const FINGERPRINT_VERSION =
|
|
2240
|
+
declare const FINGERPRINT_VERSION = 3;
|
|
2233
2241
|
/** One section as layout comparison sees it. */
|
|
2234
2242
|
interface FingerprintSection {
|
|
2235
2243
|
role: SectionRole;
|
|
@@ -2253,8 +2261,26 @@ interface FingerprintSection {
|
|
|
2253
2261
|
/** Large standalone figures. */
|
|
2254
2262
|
figures?: number;
|
|
2255
2263
|
}
|
|
2264
|
+
/** Where the hero's largest picture sits, relative to the headline. */
|
|
2265
|
+
type HeroImage = "left" | "right" | "full" | "none";
|
|
2266
|
+
/** The hero's composition: the first thing two sites are compared on by eye. */
|
|
2267
|
+
interface FingerprintHero {
|
|
2268
|
+
/** The headline (the first h1 inside the hero), or null when the hero has none. */
|
|
2269
|
+
headline: {
|
|
2270
|
+
sizePx: number;
|
|
2271
|
+
weight: number;
|
|
2272
|
+
class: FontClass;
|
|
2273
|
+
italic: boolean;
|
|
2274
|
+
} | null;
|
|
2275
|
+
/**
|
|
2276
|
+
* The largest photo or illustration in the hero: beside the text (left or
|
|
2277
|
+
* right of the viewport's centre line), `full` when it spans the width,
|
|
2278
|
+
* `none` without one. Absent when the snapshot predates image positions.
|
|
2279
|
+
*/
|
|
2280
|
+
image?: HeroImage;
|
|
2281
|
+
}
|
|
2256
2282
|
interface Fingerprint {
|
|
2257
|
-
version: 1 | 2;
|
|
2283
|
+
version: 1 | 2 | 3;
|
|
2258
2284
|
/** The most prominent chromatic colour: button fills first, then painted area, then text. */
|
|
2259
2285
|
accent: Oklch | null;
|
|
2260
2286
|
ground: Oklch;
|
|
@@ -2276,10 +2302,29 @@ interface Fingerprint {
|
|
|
2276
2302
|
layout: SectionKind[];
|
|
2277
2303
|
/** Version 2: present when every section carries a role and geometry. */
|
|
2278
2304
|
sections?: FingerprintSection[];
|
|
2305
|
+
/** Version 3: present when the page has a hero section. */
|
|
2306
|
+
hero?: FingerprintHero;
|
|
2279
2307
|
}
|
|
2280
2308
|
declare function fingerprint(s: Snapshot): Fingerprint;
|
|
2309
|
+
/**
|
|
2310
|
+
* Chroma at which a ground's tint is unmistakable. RMP's cream sits at 0.010
|
|
2311
|
+
* and Bellerose's stone at 0.007, both plainly warm paper; Bellerose's
|
|
2312
|
+
* porcelain (#F1F3F4) at 0.003 is a cool hint. A page ground is the largest
|
|
2313
|
+
* area on the page and the eye adapts to it, so a tint far below what reads
|
|
2314
|
+
* as a difference between two buttons still reads as warm or cool paper.
|
|
2315
|
+
*/
|
|
2316
|
+
declare const TEMPERATURE_FULL = 0.006;
|
|
2317
|
+
/** A ground is named warm or cool from this temperature, about chroma 0.0024. Below it, the name stays neutral. */
|
|
2318
|
+
declare const TEMPERATURE_NAMED = 0.4;
|
|
2319
|
+
/**
|
|
2320
|
+
* How warm or cool a colour reads, -1 (fully cool) through 0 (neutral) to 1
|
|
2321
|
+
* (fully warm): the chroma over `TEMPERATURE_FULL`, signed by the hue.
|
|
2322
|
+
*/
|
|
2323
|
+
declare function groundTemperature(o: Oklch): number;
|
|
2324
|
+
type Temperature = "warm" | "neutral" | "cool";
|
|
2325
|
+
declare function temperatureName(o: Oklch): Temperature;
|
|
2281
2326
|
interface FingerprintDistance {
|
|
2282
|
-
/** 0 identical, 1 nothing in common. A weighted mean of the parts. */
|
|
2327
|
+
/** 0 identical, 1 nothing in common. A weighted mean of the parts both sides measure. */
|
|
2283
2328
|
total: number;
|
|
2284
2329
|
parts: {
|
|
2285
2330
|
accent: number;
|
|
@@ -2289,34 +2334,78 @@ interface FingerprintDistance {
|
|
|
2289
2334
|
motion: number;
|
|
2290
2335
|
effects: number;
|
|
2291
2336
|
layout: number;
|
|
2337
|
+
/** Null when either side has no sections (version 1). */
|
|
2338
|
+
rhythm: number | null;
|
|
2339
|
+
/** Null when either side has no hero. */
|
|
2340
|
+
hero: number | null;
|
|
2292
2341
|
};
|
|
2293
2342
|
}
|
|
2294
2343
|
/**
|
|
2295
2344
|
* How much each part counts. Accent and type are where a model's defaults
|
|
2296
2345
|
* show first and where a real business has something of its own, so they
|
|
2297
|
-
* carry
|
|
2346
|
+
* carry the most. Structure (the running order, the rhythm of light and dark
|
|
2347
|
+
* bands, and the hero's composition) carries a quarter between its three
|
|
2348
|
+
* parts: two sites that open the same way read as the same site before any
|
|
2349
|
+
* colour is compared. A part only one side measures is left out and the
|
|
2350
|
+
* rest are weighed over what remains.
|
|
2298
2351
|
*/
|
|
2299
2352
|
declare const DISTANCE_WEIGHTS: {
|
|
2300
|
-
readonly accent: 0.
|
|
2301
|
-
readonly type: 0.
|
|
2353
|
+
readonly accent: 0.2;
|
|
2354
|
+
readonly type: 0.2;
|
|
2302
2355
|
readonly ground: 0.1;
|
|
2303
2356
|
readonly shape: 0.1;
|
|
2304
|
-
readonly motion: 0.
|
|
2357
|
+
readonly motion: 0.05;
|
|
2305
2358
|
readonly effects: 0.1;
|
|
2306
2359
|
readonly layout: 0.1;
|
|
2360
|
+
readonly rhythm: 0.1;
|
|
2361
|
+
readonly hero: 0.05;
|
|
2307
2362
|
};
|
|
2308
2363
|
/** Layout distance, 0 to 1: by role and geometry when both have them, else by kind as in version 1. */
|
|
2309
2364
|
declare function layoutDistance(a: Fingerprint, b: Fingerprint): number;
|
|
2365
|
+
/** A section's band by the lightness of what it is painted on. */
|
|
2366
|
+
type LightnessBand = "light" | "mid" | "dark";
|
|
2367
|
+
declare function bandOf(l: number): LightnessBand;
|
|
2368
|
+
/**
|
|
2369
|
+
* The page's rhythm: its bands of light and dark in running order, each run
|
|
2370
|
+
* of same-lightness sections merged into one. "Light hero, white logo strip,
|
|
2371
|
+
* near-black band, light features" is light, dark, light: the strip is part
|
|
2372
|
+
* of the light opening, which is how a visitor sees it. Null for a version 1
|
|
2373
|
+
* fingerprint, which has no section backgrounds.
|
|
2374
|
+
*/
|
|
2375
|
+
declare function rhythmOf(fp: Fingerprint): LightnessBand[] | null;
|
|
2376
|
+
/** The first bands count double: the opening is what two sites are compared on before anyone scrolls. */
|
|
2377
|
+
declare const OPENING_BANDS = 3;
|
|
2378
|
+
/**
|
|
2379
|
+
* Rhythm distance, 0 to 1: the edit distance over the opening bands and over
|
|
2380
|
+
* the whole sequence, averaged. Null when either side has no sections.
|
|
2381
|
+
*/
|
|
2382
|
+
declare function rhythmDistance(a: Fingerprint, b: Fingerprint): number | null;
|
|
2383
|
+
/**
|
|
2384
|
+
* Hero distance, 0 to 1, over the parts both sides measure: where the text
|
|
2385
|
+
* sits (centred or left), how wide it runs, the headline's class and size,
|
|
2386
|
+
* and which side the picture is on. Null when either side has no hero.
|
|
2387
|
+
*/
|
|
2388
|
+
declare function heroDistance(a: Fingerprint, b: Fingerprint): number | null;
|
|
2310
2389
|
/** ΔE in OKLab. 0.02 is barely visible; by 0.3 two accents read as different colours. */
|
|
2311
2390
|
declare const ACCENT_SCALE = 0.3;
|
|
2312
2391
|
/** Grounds sit near white, where a smaller step already reads as a different paper. */
|
|
2313
2392
|
declare const GROUND_SCALE = 0.15;
|
|
2393
|
+
/**
|
|
2394
|
+
* How much a difference in temperature adds to the ground distance, on top
|
|
2395
|
+
* of ΔE. Cream against porcelain is ΔE 0.013, a tenth of `GROUND_SCALE`, and
|
|
2396
|
+
* nobody takes them for the same paper: the temperature carries what ΔE
|
|
2397
|
+
* cannot at this chroma. Warm against cool adds 0.6; warm against neutral
|
|
2398
|
+
* white adds 0.3; two warm papers add nothing.
|
|
2399
|
+
*/
|
|
2400
|
+
declare const TEMPERATURE_WEIGHT = 0.6;
|
|
2314
2401
|
/** A part at or below this distance counts as shared between two sites. */
|
|
2315
2402
|
declare const SHARED_PART = 0.2;
|
|
2316
2403
|
/** Two accents within this ΔE_OK read as the same colour family: about 6 on the familiar ΔE scale. */
|
|
2317
2404
|
declare const ACCENT_SHARED: number;
|
|
2318
2405
|
/** Two grounds within this ΔE_OK read as the same paper. */
|
|
2319
2406
|
declare const GROUND_SHARED: number;
|
|
2407
|
+
/** Ground distance, 0 to 1: ΔE over `GROUND_SCALE`, plus the temperature gap. */
|
|
2408
|
+
declare function groundDistance(a: Oklch, b: Oklch): number;
|
|
2320
2409
|
declare function fingerprintDistance(a: Fingerprint, b: Fingerprint): FingerprintDistance;
|
|
2321
2410
|
/**
|
|
2322
2411
|
* The nearest neighbours of a fingerprint in a set, closest first. Typicality
|
|
@@ -2582,8 +2671,9 @@ declare function emptyEstate(): EstateRegister;
|
|
|
2582
2671
|
declare function addSite(register: EstateRegister, site: EstateSite): EstateRegister;
|
|
2583
2672
|
/**
|
|
2584
2673
|
* What two fingerprints effectively share, named the way a person would see
|
|
2585
|
-
* it: "Fraunces headline", "no accent", "pill buttons"
|
|
2586
|
-
*
|
|
2674
|
+
* it: "Fraunces headline", "no accent", "pill buttons", "cream ground",
|
|
2675
|
+
* "light hero then dark band". A part counts when its distance is
|
|
2676
|
+
* `SHARED_PART` or less; a part neither side measures never counts.
|
|
2587
2677
|
*/
|
|
2588
2678
|
declare function sharedParts(a: Fingerprint, b: Fingerprint, d?: FingerprintDistance): string[];
|
|
2589
2679
|
interface EstateMatch {
|
|
@@ -2703,7 +2793,18 @@ interface Typicality {
|
|
|
2703
2793
|
*/
|
|
2704
2794
|
declare function typicality(target: Fingerprint, runs: NullRun[], k?: number): Typicality;
|
|
2705
2795
|
declare function hueName(o: Oklch | null): string;
|
|
2796
|
+
/**
|
|
2797
|
+
* The coarse name the null's choice counts use ("white", "cream"), kept
|
|
2798
|
+
* stable so a harvest compares with earlier runs. `groundLabel` is the one a
|
|
2799
|
+
* person reads.
|
|
2800
|
+
*/
|
|
2706
2801
|
declare function groundName(o: Oklch): string;
|
|
2802
|
+
/**
|
|
2803
|
+
* The ground as a person would name it, with its temperature: "cream",
|
|
2804
|
+
* "cool grey", "warm white", "cool dark". Every light neutral page used to be
|
|
2805
|
+
* "grey", which put RMP's cream and Bellerose's porcelain under one word.
|
|
2806
|
+
*/
|
|
2807
|
+
declare function groundLabel(o: Oklch): string;
|
|
2707
2808
|
declare function shapeName(roundness: number | null): string;
|
|
2708
2809
|
/** The discrete choices a fingerprint makes, as part → value. What a person would name. */
|
|
2709
2810
|
declare function choicesOf(fp: Fingerprint): Record<string, string[]>;
|
|
@@ -3345,4 +3446,4 @@ declare function characterReport(input: CharacterInputs, copyTells?: Set<string>
|
|
|
3345
3446
|
|
|
3346
3447
|
declare function retrofitPlan(report: CharacterReport, direction?: ArtDirection | null): string;
|
|
3347
3448
|
|
|
3348
|
-
export { ACCENT_SCALE, ACCENT_SHARED, AI_PHRASES, AI_SOURCE_TYPES, AI_VIOLET, AI_WORDS, type AccentFork, type AccentForkOptions, type Action, type ActionPosition, type Area, type ArtDirection, BASELINE_VERSION, BUZZWORDS, type Band, type Baseline, type BaselineEntry, CATALOGUE, CATALOGUE_VERSION, CHOICE_KEYS, COMPONENT_ROLES, CONSIDERATION, CONTENT_FEATURES, CONVENTION, CUSTOMER_KINDS, type Calibration, type CandidateKind, type CharacterInputs, type CharacterReport, type CheckOptions, type CheckReport, type CheckRestraintInput, type ChoiceKey, type Claim, type ClaimsReport, type CompetitorComparison, type ComponentPair, type ComponentTypicality, type Consideration, type ContrastCheck, type ContrastReport, type CopySide, type CopyTell, type CraftConfig, type CraftTokensInput, type CraftTokensResult, type CustomerKind, DEFAULT_IGNORE, DENSITIES, DENSITY_NAMES, DIRECTION_VERSION, DIRECTION_VERSIONS, DISTANCE_WEIGHTS, DURATION_MS, DURATION_S, type DensityCssOptions, type DensityName, type DirectionChoice, type DirectionComparison, type DirectionMatch, type DirectionProblem, type DirectionReport, type DirectionSource, type DirectionSummary, type DurationName, EASE, EASE_TUPLE, EDGE_STEP, ESTATE_VERSION, EXIT_RATIO, type EaseName, type EmitCssOptions, type EstateMatch, type EstatePair, type EstateRegister, type EstateSite, FINGERPRINT_VERSION, FLAGGED_TARGET, FUNCTION_WORDS, type Fact, type FactComparison, type FactKind, type Finding, type Fingerprint, type FingerprintDistance, type FingerprintSection, type FluidSpaceOptions, type FluidTypeOptions, type FluidTypeResult, type FontClass, GROUND_SCALE, GROUND_SHARED, type Gamut, type Generation, type GradientContrast, HIERARCHY_FIELDS, HOME_FILE, HOME_URL, HOUSE, HOUSE_BUDGET, HOUSE_LOCKED, HOUSE_TYPE, HUMAN_TYPICAL_TARGET, type HarvestCandidate, type HarvestOptions, type Hit, type HouseRule, type HouseTier, IMAGERY_TELLS, type ImageProvenance, type ImageRole, JSON_SCHEMA_VERSION, type JobContext, type JobMap, type JobPart, LABELS, LEXICAL_FEATURES, LICENCES, LIGHTNESS_CURVE, type Label, type LabelSummary, type LexicalFeatures, type LicenceEntry, type LicenceSubject, MIN_DECIDED, MIN_PARAGRAPHS, MIN_RUNS, MOOD, type MeasuredPage, type MotionDecision, type MotionKind, type MultiClient, NEGATIVE_REASSURANCE, NULL_VERSION, type NullModel, type NullRun, type Oklch, type OklchToHexOptions, PAGE_TYPES, PILL_LIMIT, PLAINER_WORDS, PREFERENCE, PROFILE, PROFILE_MEASURED, PROFILE_PARAGRAPHS, PROMO_BADGE, PROOF_NAMES, PROPOSED, PROVENANCE_SCAN_BYTES, type PageCopy, type PageHierarchy, type PageResult, type PageType, type PaletteColour, type PhotoReviewOptions, type PhotoReviewResult, type Proposal, type ProposeInput, RAMP_STEPS, READABLE_SNAPSHOT_VERSIONS, REFLEX_FONTS_1, REFLEX_FONTS_2, REGISTERS, REGISTER_BASELINE, REGISTER_FEATURES, REGISTER_IDS, RENDERED_PATHS, RENDERED_TELLS, REVEAL_LIMIT, REVIEW_PHRASES, type Ramp, type RampFromAnchorsOptions, type RampOptions, type RampStep, type ReasonInput, type Register, type RegisterCheck, type RegisterFeatures, type RegisterId, type RegisterProfile, type RenderedTell, type ResearchInput, type RestraintBudget, type RestraintReport, type RestraintSeverity, type RestraintViolation, type Rgb, type RgbaImage, SAMPLES_PER_SEGMENT, SCALE, SECTION_ROLES, SHADCN_LIMIT, SHADCN_PRIMITIVES, SHARED_PART, SIBLING_AT, SNAPSHOT_VERSION, SOURCE_KINDS, SPACE_STEPS, SPECIFICITY_COPY_TELLS, SPECIFICITY_RENDERED_TELLS, SPRING, STANDING_CLAIM, STOCK_AVATAR_HOSTS, STOCK_FIGURES, STOCK_PHOTO_HOSTS, STOCK_PHRASES, STUDY_WORDS, type SarifOptions, type SarifTell, type SectionGeometry, type SectionKind, type SectionRhythmOptions, type SectionRole, type SemanticInput, type SemanticResult, type Severity, type SeverityLevel, type SeverityOverride, type ShapeFeatures, type ShouldAnimateInput, type SignalResult, type Snapshot, type SnapshotColour, type SnapshotControl, type SnapshotEffects, type SnapshotFont, type SnapshotGradient, type SnapshotHeading, type SnapshotImage, type SnapshotMotion, type SnapshotPatch, type SnapshotSection, type SnapshotVisual, type SourceFile, type SourceKind, type SourceTell, type SpaceStep, type Specific, type SpecificKind, type Specificity, type StudyWord, type Surface, TELL_HEAVY, TRADE_NOUNS, TYPE_STEPS, TYPICAL_AT, type TailwindPreset, type TargetCheck, type Tell, type TellException, type TellRate, type Tricolon, type TypeStep, type Typicality, type UnmeasuredPage, VAGUE_WORDS, type ValidateContext, type Verdict, accentFork, addSite, apcaContrast, applyBaseline, applyHouseGate, applySeverity, auditSnapshot, briefTerms, calibrate, catalogueTable, characterReport, checkCopy, checkOrder, checkPair, checkPhotoReview, checkReason, checkRegister, checkRestraint, choicesOf, clauseDepth, closestComponents, compareCompetitor, compareDirections, compareFacts, compareToDeclared, compareToEstate, componentDistance, componentShared, componentTypicalities, componentTypicality, componentsOf, contentWords, countWords, craftTokens, createBaseline, cv, deltaEOk, deltaEOkHex, densityCss, densityTokens, designTells, documentParagraphs, emitCss, emptyEstate, estateComponentPairs, estatePairs, exitDuration, extractHtml, faceLicence, featureLabel, findClaims, findColours, findingKey, fingerprint, fingerprintDistance, fluidClamp, fluidSpace, fluidType, fontClass, formatCalibration, formatClaims, formatComparison, formatCompetitor, formatDirectionMatches, formatHex, formatReport, getRegister, globToRegExp, gradientContrast, gradientStops, groundName, harvest, hedgeCount, hedgedClose, hexToOklch, holdHouseBlocks, houseRule, hueName, hueSwatch, ignoreMatcher, inP3Gamut, inSrgbGamut, initDirection, isAiViolet, isBlurb, isCategoryLabel, isCream, isFlagged, jobWords, layoutDistance, lexicalOf, licencesJson, makeSnapshot, motionTokens, namedSources, nearest, nominalisations, normaliseFamily, nullPrompt, oklchToHex, oklchToRgb, pageCopy, paletteFromPixels, paragraphUniformity, parseBaseline, parseColour, parseCraftConfig, parseHex, participialClauses, phrasalCoordinations, propose, protectedFacts, ramp, rampFromAnchors, readSnapshot, registerBrief, registerOf, registersDoc, renderedOrder, researchPrompt, retrofitPlan, runTell, scanProvenance, scanSource, sectionRhythm, semantic, sentencesOf, severityExceptions, shapeMoves, shapeName, shapeOf, words as shapeWords, sharedParts, shouldAnimate, siblingLine, skeleton, skeletonRepeat, specificity, specifics, splitSentences, stackedConditional, stockAvatarSource, stockSource, summariseDirection, tailwindV3Preset, tailwindV4Theme, tellById, toGamut, toJson, toSarif, tradeOf, tricolons, typeFeatureTokens, typicality, unprovenClaims, validateDirection, validateHierarchy, validateJob, visibleText, visualMeasures, vocabulary, vocabularyCounts, wcagContrast, wordListsJson };
|
|
3449
|
+
export { ACCENT_SCALE, ACCENT_SHARED, AI_PHRASES, AI_SOURCE_TYPES, AI_VIOLET, AI_WORDS, type AccentFork, type AccentForkOptions, type Action, type ActionPosition, type Area, type ArtDirection, BASELINE_VERSION, BUZZWORDS, type Band, type Baseline, type BaselineEntry, CATALOGUE, CATALOGUE_VERSION, CHOICE_KEYS, COMPONENT_ROLES, CONSIDERATION, CONTENT_FEATURES, CONVENTION, CUSTOMER_KINDS, type Calibration, type CandidateKind, type CharacterInputs, type CharacterReport, type CheckOptions, type CheckReport, type CheckRestraintInput, type ChoiceKey, type Claim, type ClaimsReport, type CompetitorComparison, type ComponentPair, type ComponentTypicality, type Consideration, type ContrastCheck, type ContrastReport, type CopySide, type CopyTell, type CraftConfig, type CraftTokensInput, type CraftTokensResult, type CustomerKind, DEFAULT_IGNORE, DENSITIES, DENSITY_NAMES, DIRECTION_VERSION, DIRECTION_VERSIONS, DISTANCE_WEIGHTS, DURATION_MS, DURATION_S, type DensityCssOptions, type DensityName, type DirectionChoice, type DirectionComparison, type DirectionMatch, type DirectionProblem, type DirectionReport, type DirectionSource, type DirectionSummary, type DurationName, EASE, EASE_TUPLE, EDGE_STEP, ESTATE_VERSION, EXIT_RATIO, type EaseName, type EmitCssOptions, type EstateMatch, type EstatePair, type EstateRegister, type EstateSite, FINGERPRINT_VERSION, FLAGGED_TARGET, FUNCTION_WORDS, type Fact, type FactComparison, type FactKind, type Finding, type Fingerprint, type FingerprintDistance, type FingerprintHero, type FingerprintSection, type FluidSpaceOptions, type FluidTypeOptions, type FluidTypeResult, type FontClass, GROUND_SCALE, GROUND_SHARED, type Gamut, type Generation, type GradientContrast, HIERARCHY_FIELDS, HOME_FILE, HOME_URL, HOUSE, HOUSE_BUDGET, HOUSE_LOCKED, HOUSE_TYPE, HUMAN_TYPICAL_TARGET, type HarvestCandidate, type HarvestOptions, type HeroImage, type Hit, type HouseRule, type HouseTier, IMAGERY_TELLS, type ImageProvenance, type ImageRole, JSON_SCHEMA_VERSION, type JobContext, type JobMap, type JobPart, LABELS, LEXICAL_FEATURES, LICENCES, LIGHTNESS_CURVE, type Label, type LabelSummary, type LexicalFeatures, type LicenceEntry, type LicenceSubject, type LightnessBand, MIN_DECIDED, MIN_PARAGRAPHS, MIN_RUNS, MOOD, type MeasuredPage, type MotionDecision, type MotionKind, type MultiClient, NEGATIVE_REASSURANCE, NULL_VERSION, type NullModel, type NullRun, OPENING_BANDS, type Oklch, type OklchToHexOptions, PAGE_TYPES, PILL_LIMIT, PLAINER_WORDS, PREFERENCE, PROFILE, PROFILE_MEASURED, PROFILE_PARAGRAPHS, PROMO_BADGE, PROOF_NAMES, PROPOSED, PROVENANCE_SCAN_BYTES, type PageCopy, type PageHierarchy, type PageResult, type PageType, type PaletteColour, type PhotoReviewOptions, type PhotoReviewResult, type Proposal, type ProposeInput, RAMP_STEPS, READABLE_SNAPSHOT_VERSIONS, REFLEX_FONTS_1, REFLEX_FONTS_2, REGISTERS, REGISTER_BASELINE, REGISTER_FEATURES, REGISTER_IDS, RENDERED_PATHS, RENDERED_TELLS, REVEAL_LIMIT, REVIEW_PHRASES, type Ramp, type RampFromAnchorsOptions, type RampOptions, type RampStep, type ReasonInput, type Register, type RegisterCheck, type RegisterFeatures, type RegisterId, type RegisterProfile, type RenderedTell, type ResearchInput, type RestraintBudget, type RestraintReport, type RestraintSeverity, type RestraintViolation, type Rgb, type RgbaImage, SAMPLES_PER_SEGMENT, SCALE, SECTION_ROLES, SHADCN_LIMIT, SHADCN_PRIMITIVES, SHARED_PART, SIBLING_AT, SNAPSHOT_VERSION, SOURCE_KINDS, SPACE_STEPS, SPECIFICITY_COPY_TELLS, SPECIFICITY_RENDERED_TELLS, SPRING, STANDING_CLAIM, STOCK_AVATAR_HOSTS, STOCK_FIGURES, STOCK_PHOTO_HOSTS, STOCK_PHRASES, STUDY_WORDS, type SarifOptions, type SarifTell, type SectionGeometry, type SectionKind, type SectionRhythmOptions, type SectionRole, type SemanticInput, type SemanticResult, type Severity, type SeverityLevel, type SeverityOverride, type ShapeFeatures, type ShouldAnimateInput, type SignalResult, type Snapshot, type SnapshotColour, type SnapshotControl, type SnapshotEffects, type SnapshotFont, type SnapshotGradient, type SnapshotHeading, type SnapshotImage, type SnapshotMotion, type SnapshotPatch, type SnapshotSection, type SnapshotVisual, type SourceFile, type SourceKind, type SourceTell, type SpaceStep, type Specific, type SpecificKind, type Specificity, type StudyWord, type Surface, TELL_HEAVY, TEMPERATURE_FULL, TEMPERATURE_NAMED, TEMPERATURE_WEIGHT, TRADE_NOUNS, TYPE_STEPS, TYPICAL_AT, type TailwindPreset, type TargetCheck, type Tell, type TellException, type TellRate, type Temperature, type Tricolon, type TypeStep, type Typicality, type UnmeasuredPage, VAGUE_WORDS, type ValidateContext, type Verdict, accentFork, addSite, apcaContrast, applyBaseline, applyHouseGate, applySeverity, auditSnapshot, bandOf, briefTerms, calibrate, catalogueTable, characterReport, checkCopy, checkOrder, checkPair, checkPhotoReview, checkReason, checkRegister, checkRestraint, choicesOf, clauseDepth, closestComponents, compareCompetitor, compareDirections, compareFacts, compareToDeclared, compareToEstate, componentDistance, componentShared, componentTypicalities, componentTypicality, componentsOf, contentWords, countWords, craftTokens, createBaseline, cv, deltaEOk, deltaEOkHex, densityCss, densityTokens, designTells, documentParagraphs, emitCss, emptyEstate, estateComponentPairs, estatePairs, exitDuration, extractHtml, faceLicence, featureLabel, findClaims, findColours, findingKey, fingerprint, fingerprintDistance, fluidClamp, fluidSpace, fluidType, fontClass, formatCalibration, formatClaims, formatComparison, formatCompetitor, formatDirectionMatches, formatHex, formatReport, getRegister, globToRegExp, gradientContrast, gradientStops, groundDistance, groundLabel, groundName, groundTemperature, harvest, hedgeCount, hedgedClose, heroDistance, hexToOklch, holdHouseBlocks, houseRule, hueName, hueSwatch, ignoreMatcher, inP3Gamut, inSrgbGamut, initDirection, isAiViolet, isBlurb, isCategoryLabel, isCream, isFlagged, jobWords, layoutDistance, lexicalOf, licencesJson, makeSnapshot, motionTokens, namedSources, nearest, nominalisations, normaliseFamily, nullPrompt, oklchToHex, oklchToRgb, pageCopy, paletteFromPixels, paragraphUniformity, parseBaseline, parseColour, parseCraftConfig, parseHex, participialClauses, phrasalCoordinations, propose, protectedFacts, ramp, rampFromAnchors, readSnapshot, registerBrief, registerOf, registersDoc, renderedOrder, researchPrompt, retrofitPlan, rhythmDistance, rhythmOf, runTell, scanProvenance, scanSource, sectionRhythm, semantic, sentencesOf, severityExceptions, shapeMoves, shapeName, shapeOf, words as shapeWords, sharedParts, shouldAnimate, siblingLine, skeleton, skeletonRepeat, specificity, specifics, splitSentences, stackedConditional, stockAvatarSource, stockSource, summariseDirection, tailwindV3Preset, tailwindV4Theme, tellById, temperatureName, toGamut, toJson, toSarif, tradeOf, tricolons, typeFeatureTokens, typicality, unprovenClaims, validateDirection, validateHierarchy, validateJob, visibleText, visualMeasures, vocabulary, vocabularyCounts, wcagContrast, wordListsJson };
|
package/dist/index.js
CHANGED
|
@@ -5031,7 +5031,7 @@ var RENDERED_PATHS = {
|
|
|
5031
5031
|
};
|
|
5032
5032
|
|
|
5033
5033
|
// src/fingerprint/index.ts
|
|
5034
|
-
var FINGERPRINT_VERSION =
|
|
5034
|
+
var FINGERPRINT_VERSION = 3;
|
|
5035
5035
|
var CHROMATIC = 0.03;
|
|
5036
5036
|
var MIN_ACCENT_AREA = 2e4;
|
|
5037
5037
|
var oklch = (value) => {
|
|
@@ -5067,6 +5067,24 @@ function median(values) {
|
|
|
5067
5067
|
const mid = Math.floor(sorted.length / 2);
|
|
5068
5068
|
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
5069
5069
|
}
|
|
5070
|
+
var FULL_WIDTH_IMAGE = 0.8;
|
|
5071
|
+
function heroOf(s) {
|
|
5072
|
+
const h1 = s.headings.find((h) => h.level === 1);
|
|
5073
|
+
const inside = (top, x) => top >= x.top && top < x.top + x.height;
|
|
5074
|
+
const index = (() => {
|
|
5075
|
+
const withH1 = h1 ? s.sections.findIndex((x) => x.kind === "hero" && inside(h1.top, x)) : -1;
|
|
5076
|
+
return withH1 >= 0 ? withH1 : s.sections.findIndex((x) => x.kind === "hero");
|
|
5077
|
+
})();
|
|
5078
|
+
if (index < 0) return void 0;
|
|
5079
|
+
const section = s.sections[index];
|
|
5080
|
+
const headline = h1 && inside(h1.top, section) ? { sizePx: h1.sizePx, weight: h1.weight, class: fontClass(normaliseFamily(h1.family)), italic: h1.italic || h1.italicPart } : null;
|
|
5081
|
+
if (!s.images) return { headline };
|
|
5082
|
+
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];
|
|
5083
|
+
if (!picture2) return { headline, image: "none" };
|
|
5084
|
+
if (picture2.left === void 0) return { headline };
|
|
5085
|
+
const image = picture2.width >= FULL_WIDTH_IMAGE * s.viewport.width ? "full" : picture2.left + picture2.width / 2 < s.viewport.width / 2 ? "left" : "right";
|
|
5086
|
+
return { headline, image };
|
|
5087
|
+
}
|
|
5070
5088
|
function fingerprint(s) {
|
|
5071
5089
|
const effects = [];
|
|
5072
5090
|
if (s.effects.glass > 0) effects.push("glass-panel");
|
|
@@ -5078,6 +5096,7 @@ function fingerprint(s) {
|
|
|
5078
5096
|
if (s.effects.eyebrowChip) effects.push("hero-eyebrow-chip");
|
|
5079
5097
|
if (s.motion.introOverlay) effects.push("intro-cinematic");
|
|
5080
5098
|
const below = s.sections.filter((x) => x.top > s.viewport.height).length;
|
|
5099
|
+
const hero = heroOf(s);
|
|
5081
5100
|
return {
|
|
5082
5101
|
version: FINGERPRINT_VERSION,
|
|
5083
5102
|
accent: accentOf(s),
|
|
@@ -5101,10 +5120,28 @@ function fingerprint(s) {
|
|
|
5101
5120
|
carousel: x.carousel ?? false,
|
|
5102
5121
|
figures: x.figures ?? 0
|
|
5103
5122
|
}))
|
|
5104
|
-
} : {}
|
|
5123
|
+
} : {},
|
|
5124
|
+
...hero ? { hero } : {}
|
|
5105
5125
|
};
|
|
5106
5126
|
}
|
|
5107
|
-
var
|
|
5127
|
+
var WARM_HUE = [
|
|
5128
|
+
[330, 360],
|
|
5129
|
+
[0, 130]
|
|
5130
|
+
];
|
|
5131
|
+
var COOL_HUE = [[160, 310]];
|
|
5132
|
+
var TEMPERATURE_FULL = 6e-3;
|
|
5133
|
+
var TEMPERATURE_NAMED = 0.4;
|
|
5134
|
+
function groundTemperature(o) {
|
|
5135
|
+
const h = (o.h % 360 + 360) % 360;
|
|
5136
|
+
const within = (bands) => bands.some(([lo, hi]) => h >= lo && h < hi);
|
|
5137
|
+
const strength = Math.min(1, o.c / TEMPERATURE_FULL);
|
|
5138
|
+
return within(WARM_HUE) ? strength : within(COOL_HUE) ? -strength : 0;
|
|
5139
|
+
}
|
|
5140
|
+
function temperatureName(o) {
|
|
5141
|
+
const t = groundTemperature(o);
|
|
5142
|
+
return t >= TEMPERATURE_NAMED ? "warm" : t <= -TEMPERATURE_NAMED ? "cool" : "neutral";
|
|
5143
|
+
}
|
|
5144
|
+
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
5145
|
function levenshtein(a, b, cost = (x, y) => x === y ? 0 : 1) {
|
|
5109
5146
|
const row = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
5110
5147
|
for (let i = 1; i <= a.length; i += 1) {
|
|
@@ -5131,18 +5168,62 @@ function layoutDistance(a, b) {
|
|
|
5131
5168
|
return longest === 0 ? 0 : levenshtein(a.layout, b.layout) / longest;
|
|
5132
5169
|
}
|
|
5133
5170
|
var clamp = (n) => Math.max(0, Math.min(1, n));
|
|
5171
|
+
function bandOf(l) {
|
|
5172
|
+
return l < 0.4 ? "dark" : l >= 0.75 ? "light" : "mid";
|
|
5173
|
+
}
|
|
5174
|
+
function rhythmOf(fp) {
|
|
5175
|
+
if (!fp.sections) return null;
|
|
5176
|
+
const out = [];
|
|
5177
|
+
for (const s of fp.sections) {
|
|
5178
|
+
if (s.background === void 0) return null;
|
|
5179
|
+
const band = bandOf((s.background ?? fp.ground).l);
|
|
5180
|
+
if (out[out.length - 1] !== band) out.push(band);
|
|
5181
|
+
}
|
|
5182
|
+
return out;
|
|
5183
|
+
}
|
|
5184
|
+
var OPENING_BANDS = 3;
|
|
5185
|
+
function rhythmDistance(a, b) {
|
|
5186
|
+
const ra = rhythmOf(a);
|
|
5187
|
+
const rb = rhythmOf(b);
|
|
5188
|
+
if (!ra || !rb) return null;
|
|
5189
|
+
const over = (x, y) => {
|
|
5190
|
+
const longest = Math.max(x.length, y.length);
|
|
5191
|
+
return longest === 0 ? 0 : levenshtein(x, y) / longest;
|
|
5192
|
+
};
|
|
5193
|
+
return (over(ra.slice(0, OPENING_BANDS), rb.slice(0, OPENING_BANDS)) + over(ra, rb)) / 2;
|
|
5194
|
+
}
|
|
5195
|
+
var HEADLINE_OCTAVES = 1;
|
|
5196
|
+
function heroSection(fp) {
|
|
5197
|
+
return fp.sections?.find((s) => s.role === "hero");
|
|
5198
|
+
}
|
|
5199
|
+
function heroDistance(a, b) {
|
|
5200
|
+
const sa = heroSection(a);
|
|
5201
|
+
const sb = heroSection(b);
|
|
5202
|
+
if (!sa || !sb) return null;
|
|
5203
|
+
const parts2 = [Math.abs(sa.centred - sb.centred), clamp(Math.abs(sa.width - sb.width) / 0.5)];
|
|
5204
|
+
const ha = a.hero?.headline;
|
|
5205
|
+
const hb = b.hero?.headline;
|
|
5206
|
+
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));
|
|
5207
|
+
else if (a.hero && b.hero && (ha || hb)) parts2.push(1);
|
|
5208
|
+
if (a.hero?.image && b.hero?.image) parts2.push(a.hero.image === b.hero.image ? 0 : 1);
|
|
5209
|
+
return parts2.reduce((s, p) => s + p, 0) / parts2.length;
|
|
5210
|
+
}
|
|
5134
5211
|
function faceDistance(a, b) {
|
|
5135
5212
|
if (a.family.toLowerCase() === b.family.toLowerCase()) return 0;
|
|
5136
5213
|
return a.class === b.class ? 0.5 : 1;
|
|
5137
5214
|
}
|
|
5138
5215
|
var ACCENT_SCALE = 0.3;
|
|
5139
5216
|
var GROUND_SCALE = 0.15;
|
|
5217
|
+
var TEMPERATURE_WEIGHT = 0.6;
|
|
5140
5218
|
var SHARED_PART = 0.2;
|
|
5141
5219
|
var ACCENT_SHARED = ACCENT_SCALE * SHARED_PART;
|
|
5142
5220
|
var GROUND_SHARED = GROUND_SCALE * SHARED_PART;
|
|
5221
|
+
function groundDistance(a, b) {
|
|
5222
|
+
return clamp(deltaEOk(a, b) / GROUND_SCALE + TEMPERATURE_WEIGHT * Math.abs(groundTemperature(a) - groundTemperature(b)) / 2);
|
|
5223
|
+
}
|
|
5143
5224
|
function fingerprintDistance(a, b) {
|
|
5144
5225
|
const accent = a.accent && b.accent ? clamp(deltaEOk(a.accent, b.accent) / ACCENT_SCALE) : a.accent || b.accent ? 1 : 0;
|
|
5145
|
-
const ground =
|
|
5226
|
+
const ground = groundDistance(a.ground, b.ground);
|
|
5146
5227
|
const type = 0.6 * faceDistance(a.display, b.display) + 0.4 * faceDistance(a.body, b.body);
|
|
5147
5228
|
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
5229
|
const motion = clamp(Math.abs(a.motion - b.motion));
|
|
@@ -5150,9 +5231,18 @@ function fingerprintDistance(a, b) {
|
|
|
5150
5231
|
const shared = a.effects.filter((e) => b.effects.includes(e)).length;
|
|
5151
5232
|
const effects = union.size === 0 ? 0 : 1 - shared / union.size;
|
|
5152
5233
|
const layout = layoutDistance(a, b);
|
|
5153
|
-
const
|
|
5154
|
-
const
|
|
5155
|
-
|
|
5234
|
+
const rhythm = rhythmDistance(a, b);
|
|
5235
|
+
const hero = heroDistance(a, b);
|
|
5236
|
+
const parts2 = { accent, ground, type, shape, motion, effects, layout, rhythm, hero };
|
|
5237
|
+
let sum = 0;
|
|
5238
|
+
let weight = 0;
|
|
5239
|
+
for (const k of Object.keys(DISTANCE_WEIGHTS)) {
|
|
5240
|
+
const p = parts2[k];
|
|
5241
|
+
if (p === null) continue;
|
|
5242
|
+
sum += DISTANCE_WEIGHTS[k] * p;
|
|
5243
|
+
weight += DISTANCE_WEIGHTS[k];
|
|
5244
|
+
}
|
|
5245
|
+
return { total: Math.round(sum / weight * 1e3) / 1e3, parts: parts2 };
|
|
5156
5246
|
}
|
|
5157
5247
|
function nearest(target2, set, k = set.length) {
|
|
5158
5248
|
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 +5320,12 @@ function groundName(o) {
|
|
|
5230
5320
|
if (o.l >= 0.97 && o.c < 0.012) return "white";
|
|
5231
5321
|
return o.c < 0.02 ? "grey" : "tinted";
|
|
5232
5322
|
}
|
|
5323
|
+
function groundLabel(o) {
|
|
5324
|
+
const name = groundName(o);
|
|
5325
|
+
if (name === "cream" || name === "tinted") return name;
|
|
5326
|
+
const temperature = temperatureName(o);
|
|
5327
|
+
return temperature === "neutral" ? name : `${temperature} ${name}`;
|
|
5328
|
+
}
|
|
5233
5329
|
function shapeName(roundness) {
|
|
5234
5330
|
if (roundness === null) return "no buttons";
|
|
5235
5331
|
if (roundness >= 0.45) return "pill";
|
|
@@ -8504,6 +8600,33 @@ var LICENCES = [
|
|
|
8504
8600
|
checked: "2026-09-24",
|
|
8505
8601
|
source: "https://iconscout.com/licenses",
|
|
8506
8602
|
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."
|
|
8603
|
+
},
|
|
8604
|
+
{
|
|
8605
|
+
name: "Saira Semi Condensed",
|
|
8606
|
+
subject: "face",
|
|
8607
|
+
licence: "OFL-1.1",
|
|
8608
|
+
multiClient: "yes",
|
|
8609
|
+
checked: "2026-10-09",
|
|
8610
|
+
source: "https://github.com/google/fonts/blob/main/ofl/sairasemicondensed/OFL.txt",
|
|
8611
|
+
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)."
|
|
8612
|
+
},
|
|
8613
|
+
{
|
|
8614
|
+
name: "Public Sans",
|
|
8615
|
+
subject: "face",
|
|
8616
|
+
licence: "OFL-1.1",
|
|
8617
|
+
multiClient: "yes",
|
|
8618
|
+
checked: "2026-10-09",
|
|
8619
|
+
source: "https://github.com/google/fonts/blob/main/ofl/publicsans/OFL.txt",
|
|
8620
|
+
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)."
|
|
8621
|
+
},
|
|
8622
|
+
{
|
|
8623
|
+
name: "Martian Mono",
|
|
8624
|
+
subject: "face",
|
|
8625
|
+
licence: "OFL-1.1",
|
|
8626
|
+
multiClient: "yes",
|
|
8627
|
+
checked: "2026-10-09",
|
|
8628
|
+
source: "https://github.com/google/fonts/blob/main/ofl/martianmono/OFL.txt",
|
|
8629
|
+
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
8630
|
}
|
|
8508
8631
|
];
|
|
8509
8632
|
function faceLicence(family) {
|
|
@@ -8870,7 +8993,7 @@ var PART_AREA = {
|
|
|
8870
8993
|
effects: { area: "effects", choice: "motif" },
|
|
8871
8994
|
motion: { area: "motion", choice: "signature" }
|
|
8872
8995
|
};
|
|
8873
|
-
var DEFAULTS = /^(?:ground )?(?:white|grey)(?: ground)?$|no scroll reveals|no reveals|accent (?:none|neutral)|^no buttons|shape no buttons
|
|
8996
|
+
var DEFAULTS = /^(?:ground )?(?:white|grey|light)(?: ground)?$|no scroll reveals|no reveals|accent (?:none|neutral)|^no buttons|shape no buttons|^light page throughout$/;
|
|
8874
8997
|
function designFindings(findings, copyTells) {
|
|
8875
8998
|
return (findings?.findings ?? []).filter((f4) => !copyTells.has(f4.tell));
|
|
8876
8999
|
}
|
|
@@ -8977,7 +9100,7 @@ function areaOfShared(part) {
|
|
|
8977
9100
|
if (/accent|ground/.test(part)) return "colour";
|
|
8978
9101
|
if (/buttons/.test(part)) return "shape";
|
|
8979
9102
|
if (/reveal/.test(part)) return "motion";
|
|
8980
|
-
if (/running order/.test(part)) return "layout";
|
|
9103
|
+
if (/running order|hero|page throughout/.test(part)) return "layout";
|
|
8981
9104
|
return "effects";
|
|
8982
9105
|
}
|
|
8983
9106
|
function choiceOfShared(part) {
|
|
@@ -8987,7 +9110,7 @@ function choiceOfShared(part) {
|
|
|
8987
9110
|
if (/ground/.test(part)) return "ground";
|
|
8988
9111
|
if (/buttons/.test(part)) return "shape";
|
|
8989
9112
|
if (/reveal/.test(part)) return "signature";
|
|
8990
|
-
return /running order/.test(part) ? void 0 : "motif";
|
|
9113
|
+
return /running order|hero|page throughout/.test(part) ? void 0 : "motif";
|
|
8991
9114
|
}
|
|
8992
9115
|
|
|
8993
9116
|
// src/calibrate/index.ts
|
|
@@ -9094,19 +9217,45 @@ function addSite(register, site) {
|
|
|
9094
9217
|
const sites = [...register.sites.filter((s) => s.id !== site.id), site].sort((a, b) => a.id.localeCompare(b.id));
|
|
9095
9218
|
return { version: ESTATE_VERSION, sites };
|
|
9096
9219
|
}
|
|
9220
|
+
function sharedGround(a, b) {
|
|
9221
|
+
const [x, y] = [groundLabel(a.ground), groundLabel(b.ground)];
|
|
9222
|
+
if (x === y) return `${x} ground`;
|
|
9223
|
+
const temperature = temperatureName(a.ground);
|
|
9224
|
+
if (temperature !== "neutral" && temperature === temperatureName(b.ground)) return `${temperature} ground`;
|
|
9225
|
+
return `${a.ground.l < 0.3 ? "dark" : "light"} ground`;
|
|
9226
|
+
}
|
|
9227
|
+
function sharedRhythm(a, b) {
|
|
9228
|
+
const bands = rhythmOf(a) ?? [];
|
|
9229
|
+
const word = (band) => band;
|
|
9230
|
+
if (bands.length <= 1) return `${bands[0] ? word(bands[0]) : "light"} page throughout`;
|
|
9231
|
+
const second = bands[1] === "mid" ? "mid-tone band" : `${word(bands[1])} band`;
|
|
9232
|
+
return `${word(bands[0])} hero then ${second}`;
|
|
9233
|
+
}
|
|
9234
|
+
function sharedHero(a, b) {
|
|
9235
|
+
const hero = a.sections?.find((s) => s.role === "hero");
|
|
9236
|
+
const placement = hero && hero.centred >= 0.5 ? "centred" : "left-aligned";
|
|
9237
|
+
const headline = a.hero?.headline && b.hero?.headline && a.hero.headline.class === b.hero.headline.class ? `${a.hero.headline.class} ` : "";
|
|
9238
|
+
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}`}` : "";
|
|
9239
|
+
return `${placement} ${headline}hero${image}`;
|
|
9240
|
+
}
|
|
9097
9241
|
function sharedParts(a, b, d = fingerprintDistance(a, b)) {
|
|
9098
9242
|
const out = [];
|
|
9099
|
-
const close = (k) =>
|
|
9243
|
+
const close = (k) => {
|
|
9244
|
+
const p = d.parts[k];
|
|
9245
|
+
return p !== null && p <= SHARED_PART;
|
|
9246
|
+
};
|
|
9100
9247
|
if (close("accent")) out.push(a.accent || b.accent ? `${hueName(a.accent)} accent` : "no accent");
|
|
9101
9248
|
if (close("type")) {
|
|
9102
9249
|
if (a.display.family === b.display.family) out.push(`${a.display.family} headline`);
|
|
9103
9250
|
if (a.body.family === b.body.family) out.push(`${a.body.family} body`);
|
|
9104
9251
|
}
|
|
9105
|
-
if (close("ground")) out.push(
|
|
9252
|
+
if (close("ground")) out.push(sharedGround(a, b));
|
|
9106
9253
|
if (close("shape")) out.push(`${shapeName(a.roundness)} buttons`);
|
|
9107
9254
|
if (close("motion")) out.push(a.motion > 0 || b.motion > 0 ? "scroll reveals" : "no reveals");
|
|
9108
9255
|
if (close("effects") && a.effects.length) out.push(a.effects.filter((e) => b.effects.includes(e)).join(", "));
|
|
9109
|
-
if (close("
|
|
9256
|
+
if (close("hero")) out.push(sharedHero(a, b));
|
|
9257
|
+
if (close("rhythm")) out.push(sharedRhythm(a, b));
|
|
9258
|
+
if (close("layout")) out.push("same running order");
|
|
9110
9259
|
return out;
|
|
9111
9260
|
}
|
|
9112
9261
|
function compareToEstate(target2, register, options = {}) {
|
|
@@ -9245,6 +9394,7 @@ export {
|
|
|
9245
9394
|
MOOD,
|
|
9246
9395
|
NEGATIVE_REASSURANCE,
|
|
9247
9396
|
NULL_VERSION,
|
|
9397
|
+
OPENING_BANDS,
|
|
9248
9398
|
PAGE_TYPES,
|
|
9249
9399
|
PILL_LIMIT,
|
|
9250
9400
|
PLAINER_WORDS,
|
|
@@ -9288,6 +9438,9 @@ export {
|
|
|
9288
9438
|
STOCK_PHRASES,
|
|
9289
9439
|
STUDY_WORDS,
|
|
9290
9440
|
TELL_HEAVY,
|
|
9441
|
+
TEMPERATURE_FULL,
|
|
9442
|
+
TEMPERATURE_NAMED,
|
|
9443
|
+
TEMPERATURE_WEIGHT,
|
|
9291
9444
|
TRADE_NOUNS,
|
|
9292
9445
|
TYPE_STEPS,
|
|
9293
9446
|
TYPICAL_AT,
|
|
@@ -9299,6 +9452,7 @@ export {
|
|
|
9299
9452
|
applyHouseGate,
|
|
9300
9453
|
applySeverity,
|
|
9301
9454
|
auditSnapshot,
|
|
9455
|
+
bandOf,
|
|
9302
9456
|
briefTerms,
|
|
9303
9457
|
calibrate,
|
|
9304
9458
|
catalogueTable,
|
|
@@ -9362,10 +9516,14 @@ export {
|
|
|
9362
9516
|
globToRegExp,
|
|
9363
9517
|
gradientContrast,
|
|
9364
9518
|
gradientStops,
|
|
9519
|
+
groundDistance,
|
|
9520
|
+
groundLabel,
|
|
9365
9521
|
groundName,
|
|
9522
|
+
groundTemperature,
|
|
9366
9523
|
harvest,
|
|
9367
9524
|
hedgeCount,
|
|
9368
9525
|
hedgedClose,
|
|
9526
|
+
heroDistance,
|
|
9369
9527
|
hexToOklch,
|
|
9370
9528
|
holdHouseBlocks,
|
|
9371
9529
|
houseRule,
|
|
@@ -9413,6 +9571,8 @@ export {
|
|
|
9413
9571
|
renderedOrder,
|
|
9414
9572
|
researchPrompt,
|
|
9415
9573
|
retrofitPlan,
|
|
9574
|
+
rhythmDistance,
|
|
9575
|
+
rhythmOf,
|
|
9416
9576
|
runTell,
|
|
9417
9577
|
scanProvenance,
|
|
9418
9578
|
scanSource,
|
|
@@ -9439,6 +9599,7 @@ export {
|
|
|
9439
9599
|
tailwindV3Preset,
|
|
9440
9600
|
tailwindV4Theme,
|
|
9441
9601
|
tellById,
|
|
9602
|
+
temperatureName,
|
|
9442
9603
|
toGamut,
|
|
9443
9604
|
toJson,
|
|
9444
9605
|
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.0",
|
|
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",
|
|
@@ -56,9 +56,10 @@
|
|
|
56
56
|
"dist"
|
|
57
57
|
],
|
|
58
58
|
"devDependencies": {
|
|
59
|
+
"@types/node": "^20.19.43",
|
|
59
60
|
"tsup": "^8.3.5",
|
|
60
61
|
"typescript": "^5.6.3",
|
|
61
|
-
"vitest": "^
|
|
62
|
+
"vitest": "^4.0.0"
|
|
62
63
|
},
|
|
63
64
|
"engines": {
|
|
64
65
|
"node": ">=22.12"
|