@docentjs/core 0.5.2 → 0.7.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/dist/index.cjs +36 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -8
- package/dist/index.d.ts +38 -8
- package/dist/index.js +36 -2
- package/dist/index.js.map +1 -1
- package/dist/validate.cjs +861 -0
- package/dist/validate.cjs.map +1 -0
- package/dist/validate.d.cts +57 -0
- package/dist/validate.d.ts +57 -0
- package/dist/validate.js +847 -0
- package/dist/validate.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","names":[],"sources":["../src/schema/spec.ts","../src/schema/json-schema.ts","../src/schema/validate.ts"],"sourcesContent":["/**\n * A description of the tour schema as data.\n *\n * The types in `tour.ts` are the contract for TypeScript users; this is the\n * same contract in a form code can walk, so one source drives both\n * `validateTour` and the published JSON Schema. Keep the two in step: a test\n * checks the generated schema against the file the docs site serves.\n */\n\n/** Named specs that `{ kind: 'ref' }` can point at, so conditions can nest. */\nexport type SpecName = 'tour' | 'step' | 'target' | 'advance' | 'trigger' | 'condition' | 'theme'\n\nexport type Spec =\n | { kind: 'string'; doc?: string }\n | { kind: 'number'; min?: number; max?: number; doc?: string }\n | { kind: 'boolean'; doc?: string }\n | { kind: 'enum'; values: readonly string[]; doc?: string }\n /** Anything JSON: extension bags and trait values. */\n | { kind: 'any'; doc?: string }\n | { kind: 'array'; items: Spec; doc?: string }\n | { kind: 'record'; values: Spec; doc?: string }\n | { kind: 'object'; fields: Fields; doc?: string }\n | { kind: 'union'; of: readonly Spec[]; by?: string; doc?: string }\n | { kind: 'ref'; name: SpecName; doc?: string }\n\nexport interface Field {\n spec: Spec\n required?: boolean\n doc?: string\n /** Set when a field still works but something else is preferred. */\n deprecated?: string\n}\n\nexport type Fields = Record<string, Field>\n\nconst field = (spec: Spec, doc?: string, extra: Partial<Field> = {}): Field => ({\n spec,\n ...(doc === undefined ? {} : { doc }),\n ...extra,\n})\nconst required = (spec: Spec, doc?: string): Field => field(spec, doc, { required: true })\nconst ref = (name: SpecName): Spec => ({ kind: 'ref', name })\nconst str: Spec = { kind: 'string' }\nconst num: Spec = { kind: 'number' }\nconst bool: Spec = { kind: 'boolean' }\nconst enums = (...values: string[]): Spec => ({ kind: 'enum', values })\n/** A size, time or opacity token: a CSS string, or a number in the token's unit. */\nconst themeValue: Spec = { kind: 'union', of: [str, num] }\n\nexport const ARROW_STYLES = [\n 'caret',\n 'none',\n 'line',\n 'dashed',\n 'dotted',\n 'curve',\n 'curve-dashed',\n 'squiggle',\n 'loop',\n 'elbow',\n 'sketch',\n 'pin',\n] as const\nexport const SPOTLIGHT_SHAPES = ['rounded', 'rect', 'pill', 'circle'] as const\nexport const SPOTLIGHT_RINGS = ['hairline', 'none', 'glow', 'pulse', 'dashed', 'solid'] as const\nexport const OVERLAY_STYLES = ['dim', 'blur', 'vignette', 'none'] as const\nexport const THEME_NAMES = ['light', 'dark', 'minimal', 'contrast'] as const\nexport const PLACEMENTS = [\n 'auto',\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-start',\n 'top-end',\n 'right-start',\n 'right-end',\n 'bottom-start',\n 'bottom-end',\n 'left-start',\n 'left-end',\n] as const\nexport const TRAIT_OPERATORS = [\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'nin',\n 'contains',\n 'exists',\n 'missing',\n] as const\nexport const TOUR_STATES = ['not-started', 'in-progress', 'completed', 'skipped'] as const\n\nconst target: Spec = {\n kind: 'union',\n of: [\n { kind: 'string', doc: 'A CSS selector.' },\n {\n kind: 'object',\n fields: {\n name: field(str, 'Logical name, matching `data-docent=\"<name>\"`. The sturdiest anchor.'),\n selectors: field({ kind: 'array', items: str }, 'CSS fallbacks, tried in order.'),\n native: field(str, 'Native identifier, when it differs from the name.'),\n within: field(str, 'Selector of a container to search inside.'),\n nth: field(num, 'Which match to use, counting from 0.'),\n },\n },\n ],\n}\n\nconst advance: Spec = {\n kind: 'union',\n by: 'on',\n of: [\n { kind: 'enum', values: ['button'], doc: 'The reader presses Next (the default).' },\n {\n kind: 'object',\n doc: 'The reader clicks the target.',\n fields: { on: required(enums('click')), target: field(ref('target')) },\n },\n {\n kind: 'object',\n doc: 'What the reader types matches a regular expression.',\n fields: {\n on: required(enums('input')),\n target: field(ref('target')),\n match: field(str, 'Regular expression the value must match.'),\n },\n },\n {\n kind: 'object',\n doc: 'Your code reports a named event.',\n fields: { on: required(enums('event')), name: required(str) },\n },\n {\n kind: 'object',\n doc: 'An element appears on the page.',\n fields: { on: required(enums('element')), target: required(ref('target')) },\n },\n {\n kind: 'object',\n doc: 'After a delay.',\n fields: { on: required(enums('delay')), ms: required({ kind: 'number', min: 0 }) },\n },\n ],\n}\n\nconst trigger: Spec = {\n kind: 'union',\n by: 'type',\n of: [\n { kind: 'object', doc: 'Only starts from code.', fields: { type: required(enums('manual')) } },\n {\n kind: 'object',\n doc: 'When the page loads.',\n fields: { type: required(enums('auto')), delay: field({ kind: 'number', min: 0 }) },\n },\n {\n kind: 'object',\n doc: 'On a matching path.',\n fields: {\n type: required(enums('route')),\n pattern: required(str, 'Path pattern, such as `/invoices/**`.'),\n delay: field({ kind: 'number', min: 0 }),\n },\n },\n {\n kind: 'object',\n doc: 'When an element appears.',\n fields: {\n type: required(enums('element')),\n target: required(ref('target')),\n delay: field({ kind: 'number', min: 0 }),\n },\n },\n {\n kind: 'object',\n doc: 'When your code reports an event.',\n fields: { type: required(enums('event')), name: required(str) },\n },\n ],\n}\n\nconst traitValue: Spec = {\n kind: 'union',\n of: [str, num, bool, { kind: 'array', items: str }],\n}\n\nconst condition: Spec = {\n kind: 'union',\n by: 'type',\n of: [\n {\n kind: 'object',\n doc: \"Compare one of the user's traits.\",\n fields: {\n type: required(enums('trait')),\n key: required(str),\n op: required({ kind: 'enum', values: TRAIT_OPERATORS }),\n value: field(traitValue),\n },\n },\n {\n kind: 'object',\n doc: 'The current path matches.',\n fields: { type: required(enums('route')), pattern: required(str) },\n },\n {\n kind: 'object',\n doc: 'An element is, or is not, on the page.',\n fields: {\n type: required(enums('element')),\n target: required(ref('target')),\n exists: field(bool, 'Set false to require the element to be absent.'),\n },\n },\n {\n kind: 'object',\n doc: \"Another tour's progress for this user.\",\n fields: {\n type: required(enums('tour')),\n id: required(str),\n state: required({ kind: 'enum', values: TOUR_STATES }),\n },\n },\n {\n kind: 'object',\n doc: 'Every condition holds.',\n fields: {\n type: required(enums('all')),\n conditions: required({ kind: 'array', items: ref('condition') }),\n },\n },\n {\n kind: 'object',\n doc: 'At least one condition holds.',\n fields: {\n type: required(enums('any')),\n conditions: required({ kind: 'array', items: ref('condition') }),\n },\n },\n {\n kind: 'object',\n doc: 'The inner condition does not hold.',\n fields: { type: required(enums('not')), condition: required(ref('condition')) },\n },\n {\n kind: 'object',\n doc: 'A predicate your app registered by name.',\n fields: {\n type: required(enums('custom')),\n name: required(str),\n args: field({ kind: 'record', values: traitValue }),\n },\n },\n ],\n}\n\nconst theme: Spec = {\n kind: 'object',\n doc: 'Visual tokens. Each becomes a `--docent-*` custom property.',\n fields: {\n preset: field(\n { kind: 'enum', values: THEME_NAMES },\n 'Start from a built-in preset, then override tokens below.',\n ),\n background: field(str),\n foreground: field(str),\n muted: field(str, 'Secondary text.'),\n accent: field(str, 'The Next button. Its text colour is chosen for you unless you set one.'),\n accentForeground: field(str),\n connector: field(str, 'Colour of drawn arrows.'),\n ring: field(str, 'Colour of the spotlight ring.'),\n radius: field(themeValue, 'Popover corners. A number means px.'),\n shadow: field(str),\n font: field(str, \"Defaults to the page's own font.\"),\n width: field(themeValue, 'Popover width. A number means px.'),\n overlay: field(str, 'Backdrop colour.', { deprecated: 'Prefer `options.overlay.color`.' }),\n overlayOpacity: field(themeValue, 'Backdrop opacity, 0 to 1.', {\n deprecated: 'Prefer `options.overlay.opacity`.',\n }),\n duration: field(themeValue, 'Transition time. A number means ms.'),\n zIndex: field(themeValue),\n },\n}\n\nconst themeSpec: Spec = {\n kind: 'union',\n of: [{ kind: 'enum', values: THEME_NAMES, doc: 'A built-in preset by name.' }, theme],\n}\n\nconst spotlight: Spec = {\n kind: 'object',\n fields: {\n padding: field(num, 'Space around the target, in px.'),\n radius: field(num, 'Corner radius of the cutout, in px.'),\n shape: field({ kind: 'enum', values: SPOTLIGHT_SHAPES }),\n ring: field({ kind: 'enum', values: SPOTLIGHT_RINGS }),\n animate: field(bool, 'Animate the cutout as it moves between steps.'),\n },\n}\n\nconst overlay: Spec = {\n kind: 'object',\n fields: {\n style: field({ kind: 'enum', values: OVERLAY_STYLES }),\n color: field(str),\n opacity: field({ kind: 'number', min: 0, max: 1 }),\n blur: field({ kind: 'number', min: 0 }, 'Blur radius for the `blur` style, in px.'),\n },\n}\n\nconst scroll: Spec = {\n kind: 'object',\n fields: {\n enabled: field(bool),\n behavior: field(enums('auto', 'smooth')),\n block: field(enums('start', 'center', 'end', 'nearest')),\n },\n}\n\nconst labels: Spec = {\n kind: 'object',\n fields: {\n next: field(str),\n back: field(str),\n skip: field(str),\n done: field(str),\n close: field(str),\n progress: field(str, 'Supports `{current}` and `{total}`.'),\n },\n}\n\nconst options: Spec = {\n kind: 'object',\n fields: {\n persist: field(bool, 'Remember the current step so `resume()` can continue.'),\n frequency: field(enums('once', 'until-completed', 'always')),\n showProgress: field(bool),\n allowClose: field(bool, 'Allow Escape and the close button.'),\n closeOnOverlayClick: field(bool),\n keyboard: field(bool, 'Arrow-key navigation.'),\n arrow: field({ kind: 'enum', values: ARROW_STYLES }),\n spotlight: field(spotlight),\n overlay: field(overlay),\n scroll: field(scroll),\n labels: field(labels),\n theme: field(themeSpec),\n appearance: field(\n enums('light', 'dark', 'auto'),\n \"`auto` follows the reader's system setting.\",\n ),\n template: field(\n str,\n \"A built-in look ('spotlight', 'hint' or 'announcement') or a template the app registered.\",\n ),\n },\n}\n\nconst step: Spec = {\n kind: 'object',\n fields: {\n id: required(str, 'Unique within the tour. Keep it stable once shipped.'),\n target: field(ref('target'), 'Leave out for a centred card.'),\n title: field(str),\n body: field(str),\n format: field(enums('text', 'markdown'), 'Markdown is a safe subset; HTML is never injected.'),\n media: field({\n kind: 'object',\n fields: {\n type: required(enums('image', 'video')),\n src: required(str),\n alt: field(str),\n },\n }),\n placement: field({ kind: 'enum', values: PLACEMENTS }),\n arrow: field({ kind: 'enum', values: ARROW_STYLES }),\n spotlight: field(spotlight),\n overlay: field(overlay),\n advance: field(advance, 'How the step finishes.'),\n interaction: field(enums('block', 'allow'), 'Whether the target can be used during the step.'),\n condition: field(ref('condition'), 'Skip this step when the condition is false.'),\n onMissing: field(enums('skip', 'wait', 'abort'), 'When the target is not on the page.'),\n waitFor: field({ kind: 'number', min: 0 }, 'How long to wait for the target, in ms.'),\n route: field(str, 'Path pattern this step belongs to.'),\n buttons: field({\n kind: 'object',\n fields: { back: field(bool), next: field(bool), skip: field(bool), close: field(bool) },\n }),\n scroll: field(scroll),\n meta: field({ kind: 'record', values: { kind: 'any' } }),\n },\n}\n\nconst tour: Spec = {\n kind: 'object',\n doc: 'A guided tour: what to show, to whom, and when.',\n fields: {\n $schema: field(\n str,\n 'Optional link to this schema, for editors: https://docentjs.dev/schema/tour-v1.json',\n ),\n schemaVersion: field({ kind: 'number', min: 1, max: 1 }, '`defineTour` sets this for you.'),\n id: required(str, 'Stable identifier, used for progress and analytics.'),\n version: field(num, 'Bump to show the tour again to people who saw an older one.'),\n name: field(str),\n description: field(str),\n steps: required({ kind: 'array', items: ref('step') }),\n trigger: field(ref('trigger'), 'What starts the tour. Without one, only code can.'),\n conditions: field({ kind: 'array', items: ref('condition') }, 'All must hold.'),\n options: field(options),\n meta: field({ kind: 'record', values: { kind: 'any' } }),\n },\n}\n\nexport const SPECS: Record<SpecName, Spec> = {\n tour,\n step,\n target,\n advance,\n trigger,\n condition,\n theme,\n}\n","/**\n * The tour schema as JSON Schema, generated from the same spec the validator\n * walks. The docs site serves it, so editors can complete and check\n * `.tour.json` files, and tools that write tours have something to check against.\n */\n\nimport type { Spec, SpecName } from './spec'\nimport { SPECS } from './spec'\n\nexport const SCHEMA_ID = 'https://docentjs.dev/schema/tour-v1.json'\n\ntype Json = Record<string, unknown>\n\n/** The whole schema document, ready to write to a file. */\nexport function tourJsonSchema(): Json {\n const definitions: Json = {}\n for (const name of Object.keys(SPECS) as SpecName[]) {\n if (name === 'tour') continue\n definitions[name] = convert(SPECS[name])\n }\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: SCHEMA_ID,\n title: 'Docent tour',\n description: 'A guided product tour. See https://docentjs.dev/reference/schema/.',\n ...convert(SPECS.tour),\n $defs: definitions,\n }\n}\n\nfunction convert(spec: Spec): Json {\n const doc = spec.doc ? { description: spec.doc } : {}\n switch (spec.kind) {\n case 'ref':\n return { $ref: `#/$defs/${spec.name}`, ...doc }\n case 'any':\n return { ...doc }\n case 'string':\n return { type: 'string', ...doc }\n case 'boolean':\n return { type: 'boolean', ...doc }\n case 'number':\n return {\n type: 'number',\n ...(spec.min === undefined ? {} : { minimum: spec.min }),\n ...(spec.max === undefined ? {} : { maximum: spec.max }),\n ...doc,\n }\n case 'enum':\n return { enum: [...spec.values], ...doc }\n case 'array':\n return { type: 'array', items: convert(spec.items), ...doc }\n case 'record':\n return { type: 'object', additionalProperties: convert(spec.values), ...doc }\n case 'union':\n return { anyOf: spec.of.map(convert), ...doc }\n case 'object': {\n const properties: Json = {}\n const requiredKeys: string[] = []\n for (const [key, field] of Object.entries(spec.fields)) {\n const description = field.deprecated\n ? `${field.doc ? `${field.doc} ` : ''}${field.deprecated}`\n : field.doc\n properties[key] = {\n ...convert(field.spec),\n ...(description ? { description } : {}),\n ...(field.deprecated ? { deprecated: true } : {}),\n }\n if (field.required) requiredKeys.push(key)\n }\n return {\n type: 'object',\n properties,\n ...(requiredKeys.length > 0 ? { required: requiredKeys } : {}),\n ...doc,\n }\n }\n }\n}\n","/**\n * Check a tour against the schema and say what is wrong in plain words.\n *\n * Tours are data, often written by hand or by a tool, so mistakes are easy to\n * make and used to fail silently: an unknown arrow style simply drew nothing.\n * This walks the spec in `spec.ts` and reports each problem with its path and,\n * where it can, the value that was probably meant.\n */\n\nimport type { Field, Spec, SpecName } from './spec'\nimport { SPECS } from './spec'\n\nexport type IssueLevel = 'error' | 'warning'\n\nexport interface TourIssue {\n level: IssueLevel\n /** Where the problem is, such as `steps[2].arrow`. */\n path: string\n message: string\n /** The value that was probably meant, when one is obvious. */\n suggestion?: string\n}\n\nexport interface ValidateOptions {\n /** Report unknown fields, which are usually typos. Default true. */\n unknownFields?: boolean\n}\n\n/**\n * Check a tour. An empty result means it matches the schema; it does not mean\n * the targets exist on the page, which the devtools Audit tab checks.\n */\nexport function validateTour(tour: unknown, options: ValidateOptions = {}): TourIssue[] {\n const issues: TourIssue[] = []\n check(tour, { kind: 'ref', name: 'tour' }, '', issues, options.unknownFields !== false)\n if (isObject(tour) && Array.isArray(tour.steps)) {\n const seen = new Set<string>()\n tour.steps.forEach((step: unknown, i: number) => {\n const id = isObject(step) ? step.id : undefined\n if (typeof id !== 'string') return\n if (seen.has(id)) {\n issues.push({\n level: 'error',\n path: `steps[${i}].id`,\n message: `Duplicate step id \"${id}\". Ids must be unique within a tour.`,\n })\n }\n seen.add(id)\n })\n }\n return issues\n}\n\n/** True when the tour matches the schema. */\nexport function isValidTour(tour: unknown): boolean {\n return validateTour(tour).every((issue) => issue.level !== 'error')\n}\n\n/** One line per issue, for a console warning or a CI log. */\nexport function formatIssues(issues: TourIssue[]): string {\n return issues\n .map((issue) => {\n const where = issue.path === '' ? 'tour' : issue.path\n const hint = issue.suggestion ? ` Did you mean \"${issue.suggestion}\"?` : ''\n return `${issue.level === 'error' ? '✗' : '!'} ${where}: ${issue.message}${hint}`\n })\n .join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n\nfunction check(\n value: unknown,\n spec: Spec,\n path: string,\n issues: TourIssue[],\n unknownFields: boolean,\n): void {\n switch (spec.kind) {\n case 'ref':\n check(value, SPECS[spec.name as SpecName], path, issues, unknownFields)\n return\n case 'any':\n return\n case 'string':\n if (typeof value !== 'string') issues.push(wrongType(path, 'a string', value))\n return\n case 'boolean':\n if (typeof value !== 'boolean') issues.push(wrongType(path, 'true or false', value))\n return\n case 'number': {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n issues.push(wrongType(path, 'a number', value))\n return\n }\n if (spec.min !== undefined && value < spec.min) {\n issues.push({ level: 'error', path, message: `${value} is below the minimum ${spec.min}.` })\n }\n if (spec.max !== undefined && value > spec.max) {\n issues.push({ level: 'error', path, message: `${value} is above the maximum ${spec.max}.` })\n }\n return\n }\n case 'enum': {\n if (typeof value === 'string' && spec.values.includes(value)) return\n const near = typeof value === 'string' ? nearest(value, spec.values) : undefined\n issues.push({\n level: 'error',\n path,\n message: `${show(value)} is not one of: ${spec.values.join(', ')}.`,\n ...(near ? { suggestion: near } : {}),\n })\n return\n }\n case 'array': {\n if (!Array.isArray(value)) {\n issues.push(wrongType(path, 'a list', value))\n return\n }\n value.forEach((item, i) => {\n check(item, spec.items, `${path}[${i}]`, issues, unknownFields)\n })\n return\n }\n case 'record': {\n if (!isObject(value)) {\n issues.push(wrongType(path, 'an object', value))\n return\n }\n for (const [key, item] of Object.entries(value)) {\n check(item, spec.values, join(path, key), issues, unknownFields)\n }\n return\n }\n case 'object': {\n if (!isObject(value)) {\n issues.push(wrongType(path, 'an object', value))\n return\n }\n checkFields(value, spec.fields, path, issues, unknownFields)\n return\n }\n case 'union': {\n const branch = pickBranch(value, spec, path, issues)\n if (branch) check(value, branch, path, issues, unknownFields)\n return\n }\n }\n}\n\nfunction checkFields(\n value: Record<string, unknown>,\n fields: Record<string, Field>,\n path: string,\n issues: TourIssue[],\n unknownFields: boolean,\n): void {\n for (const [key, field] of Object.entries(fields)) {\n const item = value[key]\n if (item === undefined) {\n if (field.required) {\n issues.push({\n level: 'error',\n path: join(path, key),\n message: 'Required field is missing.',\n })\n }\n continue\n }\n if (field.deprecated) {\n issues.push({ level: 'warning', path: join(path, key), message: field.deprecated })\n }\n check(item, field.spec, join(path, key), issues, unknownFields)\n }\n if (!unknownFields) return\n const known = Object.keys(fields)\n for (const key of Object.keys(value)) {\n if (known.includes(key)) continue\n const near = nearest(key, known)\n issues.push({\n level: 'warning',\n path: join(path, key),\n message: 'Unknown field, which Docent will ignore.',\n ...(near ? { suggestion: near } : {}),\n })\n }\n}\n\n/** Choose the branch of a union, using its discriminator when it has one. */\nfunction pickBranch(\n value: unknown,\n spec: Extract<Spec, { kind: 'union' }>,\n path: string,\n issues: TourIssue[],\n): Spec | undefined {\n const objects = spec.of.filter((s) => s.kind === 'object')\n const others = spec.of.filter((s) => s.kind !== 'object')\n if (!isObject(value)) {\n // A plain value: accept it if any non-object branch does.\n if (others.some((s) => matches(value, s))) return undefined\n const names = spec.of.map(describe).join(', or ')\n const near =\n typeof value === 'string'\n ? nearest(\n value,\n others.flatMap((s) => (s.kind === 'enum' ? [...s.values] : [])),\n )\n : undefined\n issues.push({\n level: 'error',\n path,\n message: `${show(value)} is not valid here. Expected ${names}.`,\n ...(near ? { suggestion: near } : {}),\n })\n return undefined\n }\n if (objects.length === 1) return objects[0]\n const by = spec.by\n if (!by) return objects.find((s) => matches(value, s)) ?? objects[0]\n const tag = value[by]\n const tags = objects.flatMap((s) => {\n const f = s.kind === 'object' ? s.fields[by]?.spec : undefined\n return f?.kind === 'enum' ? [...f.values] : []\n })\n const found = objects.find((s) => {\n const f = s.kind === 'object' ? s.fields[by]?.spec : undefined\n return f?.kind === 'enum' && typeof tag === 'string' && f.values.includes(tag)\n })\n if (found) return found\n const near = typeof tag === 'string' ? nearest(tag, tags) : undefined\n issues.push({\n level: 'error',\n path: join(path, by),\n message:\n tag === undefined\n ? `Required field is missing. Expected one of: ${tags.join(', ')}.`\n : `${show(tag)} is not one of: ${tags.join(', ')}.`,\n ...(near ? { suggestion: near } : {}),\n })\n return undefined\n}\n\n/** A quick shape test, without collecting issues. */\nfunction matches(value: unknown, spec: Spec): boolean {\n const issues: TourIssue[] = []\n check(value, spec, '', issues, false)\n return issues.every((i) => i.level !== 'error')\n}\n\nfunction describe(spec: Spec): string {\n switch (spec.kind) {\n case 'string':\n return 'a string'\n case 'number':\n return 'a number'\n case 'boolean':\n return 'true or false'\n case 'enum':\n return `one of: ${spec.values.join(', ')}`\n case 'array':\n return 'a list'\n case 'object':\n case 'record':\n return 'an object'\n default:\n return 'a value'\n }\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst join = (path: string, key: string) => (path === '' ? key : `${path}.${key}`)\n\nfunction wrongType(path: string, expected: string, value: unknown): TourIssue {\n return { level: 'error', path, message: `Expected ${expected}, found ${show(value)}.` }\n}\n\nfunction show(value: unknown): string {\n if (typeof value === 'string') return `\"${value}\"`\n if (value === undefined) return 'nothing'\n if (Array.isArray(value)) return 'a list'\n if (typeof value === 'object' && value !== null) return 'an object'\n return String(value)\n}\n\n/** The closest option, when one is close enough to be worth suggesting. */\nexport function nearest(value: string, options: readonly string[]): string | undefined {\n let best: string | undefined\n let bestDistance = Number.POSITIVE_INFINITY\n for (const option of options) {\n const d = distance(value.toLowerCase(), option.toLowerCase())\n if (d < bestDistance) {\n bestDistance = d\n best = option\n }\n }\n // Roughly a third of the word: enough for a typo or two swapped letters.\n const allowed = Math.max(1, Math.round(value.length / 3))\n return best !== undefined && bestDistance <= allowed ? best : undefined\n}\n\n/** Levenshtein distance, two rows at a time. */\nfunction distance(a: string, b: string): number {\n if (a === b) return 0\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i)\n for (let i = 1; i <= a.length; i++) {\n const current = [i]\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n current[j] = Math.min(\n (current[j - 1] ?? 0) + 1,\n (previous[j] ?? 0) + 1,\n (previous[j - 1] ?? 0) + cost,\n )\n }\n previous = current\n }\n return previous[b.length] ?? 0\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docentjs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Platform-agnostic tour engine: schema, state machine, triggers, persistence, events. No DOM access.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,6 +37,16 @@
|
|
|
37
37
|
"default": "./dist/index.cjs"
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
|
+
"./validate": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/validate.d.ts",
|
|
43
|
+
"default": "./dist/validate.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/validate.d.cts",
|
|
47
|
+
"default": "./dist/validate.cjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
40
50
|
"./package.json": "./package.json"
|
|
41
51
|
},
|
|
42
52
|
"files": [
|