snoop-ui 0.0.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/LICENSE +21 -0
- package/README.md +61 -0
- package/package.json +95 -0
- package/packages/adapter-vite/dist/vite.d.ts +29 -0
- package/packages/adapter-vite/dist/vite.js +281 -0
- package/packages/adapter-vite/dist/vite.js.map +1 -0
- package/packages/cli/dist/cli.d.ts +1 -0
- package/packages/cli/dist/cli.js +136 -0
- package/packages/cli/dist/cli.js.map +1 -0
- package/packages/core/dist/index.d.ts +607 -0
- package/packages/core/dist/index.js +2421 -0
- package/packages/core/dist/index.js.map +1 -0
- package/packages/runtime/dist/agent.js +751 -0
- package/packages/runtime/dist/agent.js.map +1 -0
- package/schemas/config.v1.json +99 -0
- package/schemas/diagnostics.v1.json +132 -0
- package/schemas/manifest.v1.json +207 -0
- package/schemas/styles.v1.json +231 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","names":["round"],"sources":["../../core/src/styles/selector.ts","../../core/src/runtime/measure.ts","../../core/src/runtime/overlay.ts","../../core/src/runtime/protocol.ts","../src/agent.ts"],"sourcesContent":["/**\n * Selector helpers shared by the static CSS parser and the dashboard. They are\n * deliberately dependency-free so they can run in the browser dashboard and in\n * the Node tests without pulling PostCSS into the client bundle.\n */\nexport interface Specificity {\n id: number;\n class: number;\n type: number;\n}\n\n/**\n * Normalize a selector list for lookup. Whitespace and spaces around\n * combinators are insignificant, but the contents of strings, attribute\n * selectors, and pseudo-class arguments are preserved.\n */\nexport function normalizeSelector(selector: string): string {\n return splitSelectorList(selector)\n .map(normalizeComplexSelector)\n .filter((part) => part.length > 0)\n .join(', ');\n}\n\n/** Split a selector list on top-level commas, ignoring commas in functions. */\nexport function splitSelectorList(selector: string): string[] {\n const parts: string[] = [];\n let current = '';\n let quote: string | undefined;\n let brackets = 0;\n let parentheses = 0;\n\n for (let index = 0; index < selector.length; index += 1) {\n const character = selector[index] as string;\n\n if (quote) {\n current += character;\n if (character === '\\\\') {\n const next = selector[index + 1];\n if (next !== undefined) {\n current += next;\n index += 1;\n }\n } else if (character === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n current += character;\n continue;\n }\n\n if (character === '[') {\n brackets += 1;\n } else if (character === ']') {\n brackets = Math.max(0, brackets - 1);\n } else if (character === '(') {\n parentheses += 1;\n } else if (character === ')') {\n parentheses = Math.max(0, parentheses - 1);\n }\n\n if (character === ',' && brackets === 0 && parentheses === 0) {\n parts.push(current);\n current = '';\n continue;\n }\n\n current += character;\n }\n\n parts.push(current);\n return parts;\n}\n\nfunction normalizeComplexSelector(selector: string): string {\n let output = '';\n let quote: string | undefined;\n let brackets = 0;\n let parentheses = 0;\n let pendingSpace = false;\n\n const flushSpace = () => {\n if (pendingSpace && output.length > 0 && !/[\\s>+~|]$/.test(output)) {\n output += ' ';\n }\n pendingSpace = false;\n };\n\n for (let index = 0; index < selector.length; index += 1) {\n const character = selector[index] as string;\n\n if (quote) {\n output += character;\n if (character === '\\\\') {\n const next = selector[index + 1];\n if (next !== undefined) {\n output += next;\n index += 1;\n }\n } else if (character === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n flushSpace();\n quote = character;\n output += character;\n continue;\n }\n\n if (character === '[') {\n flushSpace();\n brackets += 1;\n output += character;\n continue;\n }\n\n if (character === ']') {\n brackets = Math.max(0, brackets - 1);\n output += character;\n continue;\n }\n\n if (character === '(') {\n flushSpace();\n parentheses += 1;\n output += character;\n continue;\n }\n\n if (character === ')') {\n parentheses = Math.max(0, parentheses - 1);\n output += character;\n continue;\n }\n\n if (brackets > 0 || parentheses > 0) {\n output += character;\n continue;\n }\n\n if (/\\s/.test(character)) {\n pendingSpace = true;\n continue;\n }\n\n if (character === '>' || character === '+' || character === '~') {\n output = output.replace(/\\s+$/, '');\n output += character;\n pendingSpace = false;\n continue;\n }\n\n if (character === '|' && selector[index + 1] === '|') {\n output = output.replace(/\\s+$/, '');\n output += '||';\n pendingSpace = false;\n index += 1;\n continue;\n }\n\n flushSpace();\n output += character;\n }\n\n return output.trim();\n}\n\nconst LEGACY_PSEUDO_ELEMENTS = new Set(['before', 'after', 'first-line', 'first-letter']);\n\n/**\n * Compute selector specificity with a small, dependency-free parser. The\n * cascade only needs the values to be ordered correctly; this follows the\n * Selectors Level 4 rules for `:is`, `:not`, `:has`, `:where`, and\n * `:nth-child(… of …)`.\n */\nexport function specificityOf(selector: string): Specificity {\n let best: Specificity = { id: 0, class: 0, type: 0 };\n\n for (const part of splitSelectorList(selector)) {\n const value = specificityOfComplexSelector(part);\n if (compareSpecificity(value, best) > 0) {\n best = value;\n }\n }\n\n return best;\n}\n\nexport function compareSpecificity(a: Specificity, b: Specificity): number {\n return a.id - b.id || a.class - b.class || a.type - b.type;\n}\n\nfunction specificityOfComplexSelector(selector: string): Specificity {\n const result: Specificity = { id: 0, class: 0, type: 0 };\n let index = 0;\n\n while (index < selector.length) {\n const character = selector[index] as string;\n\n if (/\\s/.test(character) || character === '>' || character === '+' || character === '~') {\n index += 1;\n continue;\n }\n\n if (character === ',' || character === '*') {\n index += 1;\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n index = skipString(selector, index);\n continue;\n }\n\n if (character === '[') {\n result.class += 1;\n index = skipBalanced(selector, index, '[', ']');\n continue;\n }\n\n if (character === '#') {\n result.id += 1;\n index = skipIdentifier(selector, index + 1);\n continue;\n }\n\n if (character === '.') {\n result.class += 1;\n index = skipIdentifier(selector, index + 1);\n continue;\n }\n\n if (character === ':') {\n const doubleColon = selector[index + 1] === ':';\n const nameStart = index + (doubleColon ? 2 : 1);\n const nameEnd = skipIdentifier(selector, nameStart);\n const name = selector.slice(nameStart, nameEnd).toLowerCase();\n\n if (doubleColon || LEGACY_PSEUDO_ELEMENTS.has(name)) {\n result.type += 1;\n index = nameEnd;\n if (selector[index] === '(') {\n index = skipBalanced(selector, index, '(', ')');\n }\n continue;\n }\n\n if (selector[nameEnd] === '(') {\n const argumentEnd = skipBalanced(selector, nameEnd, '(', ')');\n const argument = selector.slice(nameEnd + 1, argumentEnd - 1);\n\n if (name === 'where') {\n // Zero specificity, including the arguments.\n } else if (name === 'is' || name === 'not' || name === 'has') {\n addInPlace(result, maxSpecificity(argument));\n } else if (name === 'nth-child' || name === 'nth-last-child') {\n result.class += 1;\n const ofIndex = findNthOf(argument);\n if (ofIndex >= 0) {\n addInPlace(result, maxSpecificity(argument.slice(ofIndex)));\n }\n } else {\n result.class += 1;\n }\n\n index = argumentEnd;\n continue;\n }\n\n result.class += 1;\n index = nameEnd;\n continue;\n }\n\n if (character === '\\\\') {\n result.type += 1;\n index = skipIdentifier(selector, index);\n continue;\n }\n\n if (character === '&') {\n index += 1;\n continue;\n }\n\n if (isIdentifierStart(character)) {\n const end = skipIdentifier(selector, index);\n // A namespace prefix (`svg|rect`) is not an element of its own.\n if (selector[end] === '|' && selector[end + 1] !== '|') {\n index = end + 1;\n continue;\n }\n\n result.type += 1;\n index = end;\n continue;\n }\n\n index += 1;\n }\n\n return result;\n}\n\nfunction maxSpecificity(selectorList: string): Specificity {\n let best: Specificity = { id: 0, class: 0, type: 0 };\n\n for (const part of splitSelectorList(selectorList)) {\n const value = specificityOfComplexSelector(part);\n if (compareSpecificity(value, best) > 0) {\n best = value;\n }\n }\n\n return best;\n}\n\nfunction addInPlace(target: Specificity, value: Specificity): void {\n target.id += value.id;\n target.class += value.class;\n target.type += value.type;\n}\n\n/** Find the top-level `of` keyword in an `:nth-child(… of …)` argument. */\nfunction findNthOf(argument: string): number {\n let quote: string | undefined;\n let brackets = 0;\n let parentheses = 0;\n\n for (let index = 0; index < argument.length; index += 1) {\n const character = argument[index] as string;\n\n if (quote) {\n if (character === '\\\\') {\n index += 1;\n } else if (character === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '[') {\n brackets += 1;\n } else if (character === ']') {\n brackets = Math.max(0, brackets - 1);\n } else if (character === '(') {\n parentheses += 1;\n } else if (character === ')') {\n parentheses = Math.max(0, parentheses - 1);\n } else if (\n brackets === 0 &&\n parentheses === 0 &&\n character.toLowerCase() === 'o' &&\n argument[index + 1]?.toLowerCase() === 'f' &&\n /\\s/.test(argument[index - 1] ?? ' ') &&\n /[\\s.:#[]/.test(argument[index + 2] ?? ' ')\n ) {\n return index + 2;\n }\n }\n\n return -1;\n}\n\nfunction skipString(value: string, start: number): number {\n const quote = value[start];\n let index = start + 1;\n\n while (index < value.length) {\n if (value[index] === '\\\\') {\n index += 2;\n continue;\n }\n\n if (value[index] === quote) {\n return index + 1;\n }\n\n index += 1;\n }\n\n return value.length;\n}\n\nfunction skipBalanced(value: string, start: number, open: string, close: string): number {\n let depth = 0;\n let quote: string | undefined;\n\n for (let index = start; index < value.length; index += 1) {\n const character = value[index] as string;\n\n if (quote) {\n if (character === '\\\\') {\n index += 1;\n } else if (character === quote) {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === open) {\n depth += 1;\n } else if (character === close) {\n depth -= 1;\n if (depth === 0) {\n return index + 1;\n }\n }\n }\n\n return value.length;\n}\n\nfunction skipIdentifier(value: string, start: number): number {\n let index = start;\n\n while (index < value.length) {\n const character = value[index] as string;\n\n if (character === '\\\\') {\n index += 2;\n continue;\n }\n\n if (!isIdentifierCharacter(character)) {\n return index;\n }\n\n index += 1;\n }\n\n return index;\n}\n\nfunction isIdentifierStart(character: string): boolean {\n return /[a-zA-Z_\\u0080-\\uffff-]/.test(character);\n}\n\nfunction isIdentifierCharacter(character: string): boolean {\n return /[a-zA-Z0-9_\\u0080-\\uffff-]/.test(character);\n}\n","import type {\n ElementDetail,\n MatchedDeclaration,\n MatchedRule,\n MeasuredElement,\n Rect,\n} from './protocol.js';\nimport { splitSelectorList } from '../styles/selector.js';\n\n/**\n * Computed style properties captured for the selected element. The list is\n * deliberately small: the agent sends full style detail for one element at a\n * time, and the style resolver (M4) adds provenance on top of these values.\n */\nexport const STYLE_PROPERTIES = [\n 'display',\n 'position',\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'width',\n 'height',\n 'min-width',\n 'min-height',\n 'max-width',\n 'max-height',\n 'margin-top',\n 'margin-right',\n 'margin-bottom',\n 'margin-left',\n 'padding-top',\n 'padding-right',\n 'padding-bottom',\n 'padding-left',\n 'border-top-width',\n 'border-right-width',\n 'border-bottom-width',\n 'border-left-width',\n 'border-radius',\n 'border-top-left-radius',\n 'border-top-right-radius',\n 'border-bottom-right-radius',\n 'border-bottom-left-radius',\n 'box-sizing',\n 'overflow',\n 'z-index',\n 'opacity',\n 'color',\n 'background-color',\n 'box-shadow',\n 'font-family',\n 'font-size',\n 'font-weight',\n 'line-height',\n 'letter-spacing',\n 'text-align',\n 'text-transform',\n 'white-space',\n 'flex-direction',\n 'flex-wrap',\n 'justify-content',\n 'align-items',\n 'gap',\n 'grid-template-columns',\n 'grid-template-rows',\n 'transform',\n] as const;\n\n/**\n * Collect the geometry of every tagged element that is currently rendered.\n *\n * Only visible elements are measured: the agent runs inside the host app and\n * must stay cheap.\n */\nexport function collectMeasuredElements(doc: Document, view: Window): MeasuredElement[] {\n const elements = doc.querySelectorAll('[data-snoop-src]');\n const measured: MeasuredElement[] = [];\n\n for (const element of elements) {\n const src = element.getAttribute('data-snoop-src');\n if (!src || !isVisible(element, view)) {\n continue;\n }\n\n measured.push({\n src,\n tag: element.tagName.toLowerCase(),\n rect: toRect(element.getBoundingClientRect()),\n });\n }\n\n return measured;\n}\n\nexport const MAX_MATCHED_RULES = 250;\n\n/** Capture the full detail of a single element. */\nexport function describeElement(element: Element, view: Window): ElementDetail | undefined {\n const src = element.getAttribute('data-snoop-src');\n if (!src) {\n return undefined;\n }\n\n const computed = view.getComputedStyle(element);\n const style: Record<string, string> = {};\n\n for (const property of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(property);\n if (value) {\n style[property] = value;\n }\n }\n\n return {\n src,\n tag: element.tagName.toLowerCase(),\n rect: toRect(element.getBoundingClientRect()),\n style,\n classes: classNames(element),\n inlineStyle: collectInlineStyle(element),\n matchedRules: collectMatchedRules(element, documentOf(element, view)),\n };\n}\n\n/**\n * Read every stylesheet rule that matches the element. The browser CSSOM is the\n * source of truth; the static index only labels where the winning rule lives.\n */\nexport function collectMatchedRules(element: Element, doc: Document | undefined): MatchedRule[] {\n if (!doc?.styleSheets) {\n return [];\n }\n\n const matched: MatchedRule[] = [];\n let order = 0;\n\n const walk = (rules: CSSRuleList | undefined, atRules: string[]): void => {\n if (!rules) {\n return;\n }\n\n for (const rule of Array.from(rules)) {\n if (matched.length >= MAX_MATCHED_RULES) {\n return;\n }\n\n const styleRule = rule as CSSStyleRule;\n\n if (typeof styleRule.selectorText === 'string' && styleRule.style) {\n const currentOrder = order;\n order += 1;\n\n if (!matchesAny(element, styleRule.selectorText)) {\n continue;\n }\n\n const declarations = matchedDeclarations(styleRule.style);\n\n if (declarations.length > 0) {\n matched.push({\n selector: styleRule.selectorText,\n declarations,\n order: currentOrder,\n atRules,\n });\n }\n\n continue;\n }\n\n const grouping = rule as CSSGroupingRule;\n\n if (grouping.cssRules) {\n const label = groupingLabel(rule);\n walk(grouping.cssRules, label ? [...atRules, label] : atRules);\n }\n }\n };\n\n for (const sheet of Array.from(doc.styleSheets)) {\n if (sheet.disabled) {\n continue;\n }\n\n let rules: CSSRuleList | undefined;\n\n try {\n rules = sheet.cssRules;\n } catch {\n // Cross-origin sheets cannot be inspected. They are out of scope.\n continue;\n }\n\n walk(rules, []);\n }\n\n return matched;\n}\n\nfunction matchedDeclarations(style: CSSStyleDeclaration): MatchedDeclaration[] {\n const declarations: MatchedDeclaration[] = [];\n\n for (const property of STYLE_PROPERTIES) {\n const value = style.getPropertyValue(property);\n\n if (!value) {\n continue;\n }\n\n declarations.push({\n property,\n value,\n important: style.getPropertyPriority(property) === 'important',\n });\n }\n\n return declarations;\n}\n\nfunction collectInlineStyle(element: Element): Record<string, string> {\n const style = (element as Element & { style?: CSSStyleDeclaration }).style;\n\n if (!style || typeof style.getPropertyValue !== 'function') {\n return {};\n }\n\n const declarations: Record<string, string> = {};\n\n for (const property of STYLE_PROPERTIES) {\n const value = style.getPropertyValue(property);\n\n if (value) {\n declarations[property] = value;\n }\n }\n\n return declarations;\n}\n\nfunction matchesAny(element: Element, selector: string): boolean {\n for (const part of splitSelectorList(selector)) {\n const candidate = part.trim();\n\n if (!candidate) {\n continue;\n }\n\n try {\n if (element.matches(candidate)) {\n return true;\n }\n } catch {\n // A selector the browser cannot match (for example a pseudo-element) is\n // not a reason to drop the rest of the stylesheet.\n }\n }\n\n return false;\n}\n\nfunction groupingLabel(rule: CSSRule): string | undefined {\n const media = (rule as CSSMediaRule).media;\n\n if (media && typeof media.mediaText === 'string') {\n return `@media ${media.mediaText}`;\n }\n\n const condition = (rule as CSSSupportsRule).conditionText;\n\n if (typeof condition === 'string') {\n const name = rule.constructor?.name ?? '';\n return name.includes('Container') ? `@container ${condition}` : `@supports ${condition}`;\n }\n\n const layer = (rule as CSSLayerBlockRule).name;\n\n if (typeof layer === 'string' && layer.length > 0) {\n return `@layer ${layer}`;\n }\n\n return undefined;\n}\n\nfunction classNames(element: Element): string[] {\n const value = element.getAttribute('class');\n return value ? value.split(/\\s+/).filter(Boolean) : [];\n}\n\nfunction documentOf(element: Element, view: Window): Document | undefined {\n return (element as Element & { ownerDocument?: Document }).ownerDocument ?? view.document;\n}\n\n/** An element counts as rendered when it has a box and is not hidden. */\nexport function isVisible(element: Element, view: Window): boolean {\n const rect = element.getBoundingClientRect();\n\n if (rect.width <= 0 || rect.height <= 0) {\n return false;\n }\n\n const computed = view.getComputedStyle(element);\n\n if (computed.getPropertyValue('display') === 'none') {\n return false;\n }\n\n const visibility = computed.getPropertyValue('visibility');\n if (visibility === 'hidden' || visibility === 'collapse') {\n return false;\n }\n\n if (computed.getPropertyValue('opacity') === '0') {\n return false;\n }\n\n return true;\n}\n\n/** Walk up from an event target to the closest tagged element. */\nexport function findSourceElement(target: EventTarget | null): Element | undefined {\n let current = target as (Element & { parentElement?: Element | null }) | null;\n\n while (current && typeof current.getAttribute === 'function') {\n if (current.getAttribute('data-snoop-src')) {\n return current;\n }\n\n current = current.parentElement ?? null;\n }\n\n return undefined;\n}\n\nexport function toRect(rect: DOMRect): Rect {\n return {\n x: round(rect.x),\n y: round(rect.y),\n width: round(rect.width),\n height: round(rect.height),\n top: round(rect.top),\n left: round(rect.left),\n right: round(rect.right),\n bottom: round(rect.bottom),\n };\n}\n\nfunction round(value: number): number {\n return Math.round(value * 100) / 100;\n}\n","import type { Rect } from './protocol.js';\n\nexport interface OverlayItem {\n rect: Rect;\n label: string;\n}\n\nexport interface Overlay {\n showHover(item: OverlayItem | undefined): void;\n showSelected(items: OverlayItem[]): void;\n /**\n * Isolated view: cover everything except the selection with an opaque\n * backdrop and drop the selection outlines. The page itself is not changed,\n * so measurement and inspection keep working.\n */\n setIsolated(isolated: boolean): void;\n clearHover(): void;\n clearSelected(): void;\n destroy(): void;\n}\n\nconst HOVER_COLOR = '#6366f1';\nconst SELECTED_COLOR = '#16a34a';\nconst FOCUS_DIM = 'rgba(17, 17, 41, 0.55)';\nconst ISOLATE_BACKDROP = '#f4f2fb';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst DIM_MASK_ID = 'snoop-dim-mask';\n\ninterface Dim {\n svg: SVGSVGElement;\n update(rects: Rect[], fill: string): void;\n}\n\n/**\n * A layer over the whole viewport with the selected rectangles cut out. A mask\n * is used instead of per-box shadows because overlapping or nested selections\n * must stay clear.\n */\nfunction createDim(doc: Document): Dim {\n const svg = doc.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('aria-hidden', 'true');\n svg.style.cssText = [\n 'position:fixed',\n 'top:0',\n 'left:0',\n 'width:100vw',\n 'height:100vh',\n 'display:none',\n 'pointer-events:none',\n ].join(';');\n\n const defs = doc.createElementNS(SVG_NS, 'defs');\n const mask = doc.createElementNS(SVG_NS, 'mask');\n mask.setAttribute('id', DIM_MASK_ID);\n mask.setAttribute('maskUnits', 'userSpaceOnUse');\n mask.setAttribute('x', '0');\n mask.setAttribute('y', '0');\n mask.setAttribute('width', '100%');\n mask.setAttribute('height', '100%');\n\n const visible = doc.createElementNS(SVG_NS, 'rect');\n visible.setAttribute('width', '100%');\n visible.setAttribute('height', '100%');\n visible.setAttribute('fill', '#fff');\n\n const holes = doc.createElementNS(SVG_NS, 'g');\n holes.setAttribute('fill', '#000');\n\n mask.append(visible, holes);\n defs.append(mask);\n\n const layer = doc.createElementNS(SVG_NS, 'rect');\n layer.setAttribute('width', '100%');\n layer.setAttribute('height', '100%');\n layer.setAttribute('mask', `url(#${DIM_MASK_ID})`);\n\n svg.append(defs, layer);\n\n return {\n svg,\n update(rects, fill) {\n holes.replaceChildren();\n\n for (const rect of rects) {\n const hole = doc.createElementNS(SVG_NS, 'rect');\n hole.setAttribute('x', String(rect.left));\n hole.setAttribute('y', String(rect.top));\n hole.setAttribute('width', String(rect.width));\n hole.setAttribute('height', String(rect.height));\n holes.append(hole);\n }\n\n layer.setAttribute('fill', fill);\n svg.style.display = rects.length > 0 ? 'block' : 'none';\n },\n };\n}\n\n/**\n * Draw the inspection overlay inside the host app document.\n *\n * The overlay never receives pointer events, so the app stays usable while it\n * is shown. Clicks are intercepted separately by the agent when inspect mode\n * is on.\n */\nexport function createOverlay(doc: Document): Overlay {\n const root = doc.createElement('div');\n root.setAttribute('data-snoop-overlay', '');\n root.setAttribute('aria-hidden', 'true');\n root.style.cssText = [\n 'position:fixed',\n 'top:0',\n 'left:0',\n 'width:0',\n 'height:0',\n 'z-index:2147483647',\n 'pointer-events:none',\n 'contain:layout style size',\n ].join(';');\n\n const dim = createDim(doc);\n const hover = createMarker(doc, HOVER_COLOR);\n const selected: Marker[] = [];\n let items: OverlayItem[] = [];\n let isolated = false;\n\n // The dim layer goes first so the markers draw on top of it.\n root.append(dim.svg, hover.box, hover.label);\n doc.body?.append(root);\n\n function place(marker: Marker, rect: Rect, label: string): void {\n marker.box.style.top = `${rect.top}px`;\n marker.box.style.left = `${rect.left}px`;\n marker.box.style.width = `${rect.width}px`;\n marker.box.style.height = `${rect.height}px`;\n marker.box.style.display = 'block';\n\n marker.label.textContent = label;\n marker.label.style.display = 'block';\n\n const labelTop = rect.top - 20 < 0 ? rect.top + 2 : rect.top - 20;\n marker.label.style.top = `${labelTop}px`;\n marker.label.style.left = `${rect.left}px`;\n }\n\n function hide(marker: Marker): void {\n marker.box.style.display = 'none';\n marker.label.style.display = 'none';\n }\n\n function removeMarkers(): void {\n for (const marker of selected) {\n hide(marker);\n marker.box.remove();\n marker.label.remove();\n }\n\n selected.length = 0;\n }\n\n function render(): void {\n removeMarkers();\n\n // Outlines are noise in the isolated view; the backdrop frames the selection.\n if (!isolated) {\n for (const item of items) {\n const marker = createMarker(doc, SELECTED_COLOR);\n root.append(marker.box, marker.label);\n selected.push(marker);\n place(marker, item.rect, item.label);\n }\n }\n\n dim.update(\n items.map((item) => item.rect),\n isolated ? ISOLATE_BACKDROP : FOCUS_DIM,\n );\n }\n\n function clearSelected(): void {\n items = [];\n render();\n }\n\n return {\n showHover(item) {\n if (!item) {\n hide(hover);\n return;\n }\n\n place(hover, item.rect, item.label);\n },\n\n showSelected(next) {\n items = next;\n render();\n },\n\n setIsolated(next) {\n isolated = next;\n render();\n },\n\n clearHover() {\n hide(hover);\n },\n\n clearSelected,\n\n destroy() {\n removeMarkers();\n hover.box.remove();\n hover.label.remove();\n dim.svg.remove();\n root.remove();\n },\n };\n}\n\ninterface Marker {\n box: HTMLElement;\n label: HTMLElement;\n}\n\nfunction createMarker(doc: Document, color: string): Marker {\n const box = doc.createElement('div');\n box.style.cssText = [\n 'position:fixed',\n 'display:none',\n 'box-sizing:border-box',\n 'pointer-events:none',\n `border:2px solid ${color}`,\n `background:${color}1f`,\n 'border-radius:2px',\n ].join(';');\n\n const label = doc.createElement('div');\n label.style.cssText = [\n 'position:fixed',\n 'display:none',\n 'pointer-events:none',\n 'white-space:nowrap',\n 'font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace',\n `background:${color}`,\n 'color:#ffffff',\n 'padding:2px 5px',\n 'border-radius:4px',\n 'max-width:60vw',\n 'overflow:hidden',\n 'text-overflow:ellipsis',\n ].join(';');\n\n return { box, label };\n}\n","/**\n * Wire protocol shared by the dashboard, the runtime agent, and the dev-server\n * bridge.\n *\n * The bridge is a relay: dashboard messages travel to agents, agent messages\n * travel to dashboards. The server never interprets the payload, so both sides\n * can evolve without changing the server.\n */\n\nexport type BridgeRole = 'agent' | 'dashboard';\n\nexport const AGENT_ROLE: BridgeRole = 'agent';\nexport const DASHBOARD_ROLE: BridgeRole = 'dashboard';\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n top: number;\n left: number;\n right: number;\n bottom: number;\n}\n\nexport interface MeasuredElement {\n /** `file:line:col` taken from the `data-snoop-src` attribute. */\n src: string;\n tag: string;\n rect: Rect;\n}\n\nexport interface MatchedDeclaration {\n property: string;\n /** The declaration as written, before the browser resolves variables. */\n value: string;\n important: boolean;\n}\n\nexport interface MatchedRule {\n /** Selector text from the browser CSSOM. */\n selector: string;\n declarations: MatchedDeclaration[];\n /** Source order across the document's stylesheets. */\n order: number;\n /** Enclosing conditional at-rules, outermost first. */\n atRules: string[];\n}\n\nexport interface ElementDetail {\n src: string;\n tag: string;\n rect: Rect;\n /** Curated computed-style values for the selected element only. */\n style: Record<string, string>;\n /** Class names currently on the element. */\n classes: string[];\n /** Inline declarations, limited to the curated style properties. */\n inlineStyle: Record<string, string>;\n /** Stylesheet rules that match the element, in document order. */\n matchedRules: MatchedRule[];\n}\n\n/** Messages sent by the runtime agent to the dashboard. */\nexport type AgentMessage =\n | { kind: 'ready' }\n | { kind: 'presence'; connected: boolean }\n | { kind: 'elements'; elements: MeasuredElement[] }\n | { kind: 'detail'; detail: ElementDetail }\n | { kind: 'click'; src: string }\n | { kind: 'hover'; src: string | null };\n\n/** Messages sent by the dashboard to the runtime agent. */\nexport type DashboardMessage =\n | { kind: 'measure'; enabled: boolean }\n | { kind: 'inspect'; enabled: boolean }\n | { kind: 'isolate'; enabled: boolean }\n | {\n kind: 'select';\n srcs: string[];\n /** Scroll the first source to the centre of the viewport. */\n reveal?: boolean;\n }\n | { kind: 'sync' };\n\nexport type RelayPayload = AgentMessage | DashboardMessage;\n\nexport interface RelayEnvelope {\n type: 'relay';\n payload: RelayPayload;\n}\n\nexport function isAgentMessage(value: unknown): value is AgentMessage {\n if (!isRecord(value) || typeof value.kind !== 'string') {\n return false;\n }\n\n switch (value.kind) {\n case 'ready':\n case 'presence':\n case 'elements':\n case 'detail':\n case 'click':\n case 'hover':\n return true;\n default:\n return false;\n }\n}\n\nexport function isDashboardMessage(value: unknown): value is DashboardMessage {\n if (!isRecord(value) || typeof value.kind !== 'string') {\n return false;\n }\n\n switch (value.kind) {\n case 'measure':\n case 'inspect':\n case 'isolate':\n case 'select':\n case 'sync':\n return true;\n default:\n return false;\n }\n}\n\nexport function isRelayEnvelope(value: unknown): value is RelayEnvelope {\n return (\n isRecord(value) &&\n value.type === 'relay' &&\n isRecord(value.payload) &&\n typeof value.payload.kind === 'string'\n );\n}\n\nexport function parseRole(value: string | null | undefined): BridgeRole {\n return value === AGENT_ROLE ? AGENT_ROLE : DASHBOARD_ROLE;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","import { collectMeasuredElements, describeElement, findSourceElement, toRect, isVisible } from '@snoop-ui/core/runtime/measure.js';\nimport { createOverlay, type Overlay, type OverlayItem } from '@snoop-ui/core/runtime/overlay.js';\nimport {\n isDashboardMessage,\n type AgentMessage,\n type DashboardMessage,\n type MeasuredElement,\n} from '@snoop-ui/core/runtime/protocol.js';\n\nconst SESSION_ENDPOINT = '/__snoop/session';\nconst WS_ENDPOINT = '/__snoop/ws';\nconst MEASURE_DEBOUNCE = 120;\nconst RECONNECT_DELAY = 2000;\n\nexport interface AgentOptions {\n sessionEndpoint?: string;\n websocketEndpoint?: string;\n}\n\n/**\n * Start the runtime agent inside the host app.\n *\n * The agent is injected by the Vite plugin in dev mode only. It stays idle\n * until the dashboard asks for measurements, so a dev server without an open\n * dashboard costs one WebSocket and nothing else.\n */\nexport function startAgent(options: AgentOptions = {}): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n void run(options);\n}\n\nasync function run(options: AgentOptions): Promise<void> {\n const sessionEndpoint = options.sessionEndpoint ?? SESSION_ENDPOINT;\n const websocketEndpoint = options.websocketEndpoint ?? WS_ENDPOINT;\n\n const token = await fetchToken(sessionEndpoint);\n if (!token) {\n return;\n }\n\n const sessionToken = token;\n\n const state: State = {\n socket: null,\n overlay: null,\n measureEnabled: false,\n inspectEnabled: false,\n selectedSrcs: [],\n hoverSrc: null,\n elements: [],\n reconnectTimer: undefined,\n measureTimer: undefined,\n observer: undefined,\n listening: false,\n isolateEnabled: false,\n };\n\n function send(message: AgentMessage): void {\n const socket = state.socket;\n if (!socket || socket.readyState !== WebSocket.OPEN) {\n return;\n }\n\n socket.send(JSON.stringify({ type: 'relay', payload: message }));\n }\n\n function sendElements(): void {\n if (!state.measureEnabled) {\n return;\n }\n\n const elements = collectMeasuredElements(document, window);\n state.elements = elements;\n send({ kind: 'elements', elements });\n }\n\n function sendDetail(src: string): void {\n const element = findElementBySource(src);\n if (!element) {\n return;\n }\n\n const detail = describeElement(element, window);\n if (detail) {\n send({ kind: 'detail', detail });\n }\n }\n\n function ensureOverlay(): Overlay {\n if (!state.overlay) {\n state.overlay = createOverlay(document);\n }\n\n return state.overlay;\n }\n\n function showSelected(srcs: string[]): void {\n const items: OverlayItem[] = [];\n\n // A component rendered several times produces several elements with the\n // same source, so mark every instance, not just the first.\n for (const src of srcs) {\n for (const element of findElementsBySource(src)) {\n const rect = toOverlayRect(element);\n\n if (rect.width > 0 && rect.height > 0) {\n items.push({ rect, label: src });\n }\n }\n }\n\n ensureOverlay().showSelected(items);\n }\n\n function showHover(src: string | null): void {\n const overlay = ensureOverlay();\n\n if (!src) {\n overlay.showHover(undefined);\n return;\n }\n\n const element = findElementBySource(src);\n if (!element) {\n overlay.showHover(undefined);\n return;\n }\n\n overlay.showHover({ rect: toOverlayRect(element), label: src });\n }\n\n function reveal(src: string): void {\n const element = findElementBySource(src);\n if (!element) {\n return;\n }\n\n const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n element.scrollIntoView({\n block: 'center',\n inline: 'center',\n behavior: reduceMotion ? 'auto' : 'smooth',\n });\n }\n\n // The overlay is drawn in viewport coordinates, so it has to follow the page\n // when it scrolls or resizes.\n let refreshFrame = 0;\n function refreshSelected(): void {\n if (refreshFrame !== 0 || state.selectedSrcs.length === 0) {\n return;\n }\n\n refreshFrame = window.requestAnimationFrame(() => {\n refreshFrame = 0;\n showSelected(state.selectedSrcs);\n });\n }\n\n window.addEventListener('scroll', refreshSelected, true);\n window.addEventListener('resize', refreshSelected);\n\n function scheduleMeasure(): void {\n if (state.measureTimer !== undefined) {\n window.clearTimeout(state.measureTimer);\n }\n\n state.measureTimer = window.setTimeout(() => {\n state.measureTimer = undefined;\n sendElements();\n }, MEASURE_DEBOUNCE);\n }\n\n function startMeasureListeners(): void {\n if (state.listening) {\n return;\n }\n\n state.listening = true;\n window.addEventListener('scroll', scheduleMeasure, true);\n window.addEventListener('resize', scheduleMeasure);\n state.observer = new MutationObserver(scheduleMeasure);\n state.observer.observe(document.documentElement, {\n childList: true,\n subtree: true,\n });\n }\n\n function stopMeasureListeners(): void {\n if (!state.listening) {\n return;\n }\n\n state.listening = false;\n window.removeEventListener('scroll', scheduleMeasure, true);\n window.removeEventListener('resize', scheduleMeasure);\n state.observer?.disconnect();\n state.observer = undefined;\n }\n\n function onClick(event: MouseEvent): void {\n const element = findSourceElement(event.target);\n const src = element?.getAttribute('data-snoop-src');\n\n if (!src) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n state.selectedSrcs = [src];\n showSelected(state.selectedSrcs);\n send({ kind: 'click', src });\n }\n\n let hoverFrame = 0;\n\n function onMouseMove(event: MouseEvent): void {\n if (hoverFrame) {\n return;\n }\n\n const target = event.target;\n hoverFrame = window.requestAnimationFrame(() => {\n hoverFrame = 0;\n\n const element = findSourceElement(target);\n const src = element?.getAttribute('data-snoop-src') ?? null;\n\n if (src === state.hoverSrc) {\n return;\n }\n\n state.hoverSrc = src;\n showHover(src);\n send({ kind: 'hover', src });\n });\n }\n\n function handleDashboardMessage(message: DashboardMessage): void {\n switch (message.kind) {\n case 'measure': {\n state.measureEnabled = message.enabled;\n\n if (message.enabled) {\n startMeasureListeners();\n sendElements();\n } else {\n stopMeasureListeners();\n }\n\n break;\n }\n\n case 'inspect': {\n state.inspectEnabled = message.enabled;\n\n if (message.enabled) {\n document.addEventListener('click', onClick, true);\n document.addEventListener('mousemove', onMouseMove, true);\n } else {\n document.removeEventListener('click', onClick, true);\n document.removeEventListener('mousemove', onMouseMove, true);\n state.hoverSrc = null;\n showHover(null);\n }\n\n break;\n }\n\n case 'select': {\n state.selectedSrcs = message.srcs;\n\n const first = message.srcs[0];\n if (first) {\n showSelected(message.srcs);\n sendDetail(first);\n\n if (message.reveal) {\n reveal(first);\n }\n } else {\n ensureOverlay().showSelected([]);\n }\n\n break;\n }\n\n case 'isolate': {\n state.isolateEnabled = message.enabled;\n ensureOverlay().setIsolated(message.enabled);\n\n // Re-measure the selection, then bring it into view.\n showSelected(state.selectedSrcs);\n\n const first = state.selectedSrcs[0];\n if (message.enabled && first) {\n reveal(first);\n }\n\n break;\n }\n\n case 'sync': {\n send({ kind: 'ready' });\n sendElements();\n\n const first = state.selectedSrcs[0];\n if (first) {\n sendDetail(first);\n }\n\n break;\n }\n }\n }\n\n function connect(): void {\n const url = new URL(websocketEndpoint, window.location.href);\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n url.searchParams.set('token', sessionToken);\n url.searchParams.set('role', 'agent');\n\n const socket = new WebSocket(url);\n state.socket = socket;\n\n socket.addEventListener('open', () => {\n send({ kind: 'ready' });\n sendElements();\n });\n\n socket.addEventListener('message', (event) => {\n let payload: unknown;\n\n try {\n payload = JSON.parse(String(event.data));\n } catch {\n return;\n }\n\n if (\n typeof payload === 'object' &&\n payload !== null &&\n (payload as { type?: unknown }).type === 'relay' &&\n isDashboardMessage((payload as { payload?: unknown }).payload)\n ) {\n handleDashboardMessage((payload as { payload: DashboardMessage }).payload);\n }\n });\n\n socket.addEventListener('close', () => {\n state.socket = null;\n state.reconnectTimer = window.setTimeout(connect, RECONNECT_DELAY);\n });\n }\n\n connect();\n}\n\ninterface State {\n socket: WebSocket | null;\n overlay: Overlay | null;\n measureEnabled: boolean;\n inspectEnabled: boolean;\n selectedSrcs: string[];\n hoverSrc: string | null;\n elements: MeasuredElement[];\n reconnectTimer: number | undefined;\n measureTimer: number | undefined;\n observer: MutationObserver | undefined;\n listening: boolean;\n isolateEnabled: boolean;\n}\n\nasync function fetchToken(endpoint: string): Promise<string | undefined> {\n try {\n const response = await fetch(endpoint, {\n headers: { Accept: 'application/json' },\n cache: 'no-store',\n });\n\n if (!response.ok) {\n return undefined;\n }\n\n const session = (await response.json()) as { token?: unknown };\n return typeof session.token === 'string' ? session.token : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction findElementBySource(src: string): Element | undefined {\n const elements = document.querySelectorAll('[data-snoop-src]');\n\n for (const element of elements) {\n if (element.getAttribute('data-snoop-src') === src) {\n return element;\n }\n }\n\n return undefined;\n}\n\nfunction findElementsBySource(src: string): Element[] {\n return Array.from(document.querySelectorAll('[data-snoop-src]')).filter(\n (element) => element.getAttribute('data-snoop-src') === src,\n );\n}\n\nfunction toOverlayRect(element: Element): OverlayItem['rect'] {\n const rect = element.getBoundingClientRect();\n\n return {\n x: round(rect.x),\n y: round(rect.y),\n width: round(rect.width),\n height: round(rect.height),\n top: round(rect.top),\n left: round(rect.left),\n right: round(rect.right),\n bottom: round(rect.bottom),\n };\n}\n\nfunction round(value: number): number {\n return Math.round(value * 100) / 100;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"include": {
|
|
6
|
+
"default": [
|
|
7
|
+
"src/**/*.{jsx,tsx}"
|
|
8
|
+
],
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"exclude": {
|
|
15
|
+
"default": [
|
|
16
|
+
"**/node_modules/**",
|
|
17
|
+
"**/dist/**",
|
|
18
|
+
"**/build/**",
|
|
19
|
+
"**/*.test.{js,jsx,ts,tsx}",
|
|
20
|
+
"**/*.spec.{js,jsx,ts,tsx}",
|
|
21
|
+
"**/*.stories.{js,jsx,ts,tsx}"
|
|
22
|
+
],
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"tokens": {
|
|
29
|
+
"default": [],
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "string"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"providers": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"tolerance": {
|
|
39
|
+
"default": {
|
|
40
|
+
"px": 1
|
|
41
|
+
},
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"px": {
|
|
45
|
+
"type": "number",
|
|
46
|
+
"minimum": 0
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"required": [
|
|
50
|
+
"px"
|
|
51
|
+
],
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
},
|
|
54
|
+
"baseline": {
|
|
55
|
+
"default": ".snoop/baseline.json",
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"basePath": {
|
|
59
|
+
"default": "/ui",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"format": "starts_with",
|
|
62
|
+
"pattern": "^\\/.*"
|
|
63
|
+
},
|
|
64
|
+
"appUrl": {
|
|
65
|
+
"default": "/",
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
68
|
+
"rules": {
|
|
69
|
+
"default": {},
|
|
70
|
+
"type": "object",
|
|
71
|
+
"propertyNames": {
|
|
72
|
+
"type": "string"
|
|
73
|
+
},
|
|
74
|
+
"additionalProperties": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"enum": [
|
|
77
|
+
"off",
|
|
78
|
+
"info",
|
|
79
|
+
"warning",
|
|
80
|
+
"error"
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"editor": {
|
|
85
|
+
"type": "string"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"required": [
|
|
89
|
+
"include",
|
|
90
|
+
"exclude",
|
|
91
|
+
"tokens",
|
|
92
|
+
"tolerance",
|
|
93
|
+
"baseline",
|
|
94
|
+
"basePath",
|
|
95
|
+
"appUrl",
|
|
96
|
+
"rules"
|
|
97
|
+
],
|
|
98
|
+
"additionalProperties": false
|
|
99
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"version": {
|
|
6
|
+
"type": "number",
|
|
7
|
+
"const": 1
|
|
8
|
+
},
|
|
9
|
+
"diagnostics": {
|
|
10
|
+
"default": [],
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"code": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1
|
|
18
|
+
},
|
|
19
|
+
"severity": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": [
|
|
22
|
+
"info",
|
|
23
|
+
"warning",
|
|
24
|
+
"error"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"confidence": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": [
|
|
30
|
+
"EXTRACTED",
|
|
31
|
+
"INFERRED"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"file": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"minLength": 1
|
|
37
|
+
},
|
|
38
|
+
"range": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"properties": {
|
|
41
|
+
"start": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"line": {
|
|
45
|
+
"type": "integer",
|
|
46
|
+
"exclusiveMinimum": 0,
|
|
47
|
+
"maximum": 9007199254740991
|
|
48
|
+
},
|
|
49
|
+
"col": {
|
|
50
|
+
"type": "integer",
|
|
51
|
+
"exclusiveMinimum": 0,
|
|
52
|
+
"maximum": 9007199254740991
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"line",
|
|
57
|
+
"col"
|
|
58
|
+
],
|
|
59
|
+
"additionalProperties": false
|
|
60
|
+
},
|
|
61
|
+
"end": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"line": {
|
|
65
|
+
"type": "integer",
|
|
66
|
+
"exclusiveMinimum": 0,
|
|
67
|
+
"maximum": 9007199254740991
|
|
68
|
+
},
|
|
69
|
+
"col": {
|
|
70
|
+
"type": "integer",
|
|
71
|
+
"exclusiveMinimum": 0,
|
|
72
|
+
"maximum": 9007199254740991
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"required": [
|
|
76
|
+
"line",
|
|
77
|
+
"col"
|
|
78
|
+
],
|
|
79
|
+
"additionalProperties": false
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": [
|
|
83
|
+
"start",
|
|
84
|
+
"end"
|
|
85
|
+
],
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
},
|
|
88
|
+
"message": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"minLength": 1
|
|
91
|
+
},
|
|
92
|
+
"fix": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"kind": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"const": "replace"
|
|
98
|
+
},
|
|
99
|
+
"text": {
|
|
100
|
+
"type": "string"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"required": [
|
|
104
|
+
"kind",
|
|
105
|
+
"text"
|
|
106
|
+
],
|
|
107
|
+
"additionalProperties": false
|
|
108
|
+
},
|
|
109
|
+
"fingerprint": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"minLength": 1
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"required": [
|
|
115
|
+
"code",
|
|
116
|
+
"severity",
|
|
117
|
+
"confidence",
|
|
118
|
+
"file",
|
|
119
|
+
"range",
|
|
120
|
+
"message",
|
|
121
|
+
"fingerprint"
|
|
122
|
+
],
|
|
123
|
+
"additionalProperties": false
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": [
|
|
128
|
+
"version",
|
|
129
|
+
"diagnostics"
|
|
130
|
+
],
|
|
131
|
+
"additionalProperties": false
|
|
132
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"version": {
|
|
6
|
+
"type": "number",
|
|
7
|
+
"const": 1
|
|
8
|
+
},
|
|
9
|
+
"tokens": {
|
|
10
|
+
"default": {},
|
|
11
|
+
"type": "object",
|
|
12
|
+
"propertyNames": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"additionalProperties": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"nodes": {
|
|
20
|
+
"default": [],
|
|
21
|
+
"type": "array",
|
|
22
|
+
"items": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"properties": {
|
|
25
|
+
"id": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1
|
|
28
|
+
},
|
|
29
|
+
"kind": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"const": "component"
|
|
32
|
+
},
|
|
33
|
+
"name": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"file": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
},
|
|
41
|
+
"exportName": {
|
|
42
|
+
"type": "string"
|
|
43
|
+
},
|
|
44
|
+
"loc": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"properties": {
|
|
47
|
+
"start": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"properties": {
|
|
50
|
+
"line": {
|
|
51
|
+
"type": "integer",
|
|
52
|
+
"exclusiveMinimum": 0,
|
|
53
|
+
"maximum": 9007199254740991
|
|
54
|
+
},
|
|
55
|
+
"col": {
|
|
56
|
+
"type": "integer",
|
|
57
|
+
"exclusiveMinimum": 0,
|
|
58
|
+
"maximum": 9007199254740991
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"required": [
|
|
62
|
+
"line",
|
|
63
|
+
"col"
|
|
64
|
+
],
|
|
65
|
+
"additionalProperties": false
|
|
66
|
+
},
|
|
67
|
+
"end": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"line": {
|
|
71
|
+
"type": "integer",
|
|
72
|
+
"exclusiveMinimum": 0,
|
|
73
|
+
"maximum": 9007199254740991
|
|
74
|
+
},
|
|
75
|
+
"col": {
|
|
76
|
+
"type": "integer",
|
|
77
|
+
"exclusiveMinimum": 0,
|
|
78
|
+
"maximum": 9007199254740991
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"required": [
|
|
82
|
+
"line",
|
|
83
|
+
"col"
|
|
84
|
+
],
|
|
85
|
+
"additionalProperties": false
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"required": [
|
|
89
|
+
"start",
|
|
90
|
+
"end"
|
|
91
|
+
],
|
|
92
|
+
"additionalProperties": false
|
|
93
|
+
},
|
|
94
|
+
"props": {
|
|
95
|
+
"default": [],
|
|
96
|
+
"type": "array",
|
|
97
|
+
"items": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"name": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"minLength": 1
|
|
103
|
+
},
|
|
104
|
+
"type": {
|
|
105
|
+
"type": "string"
|
|
106
|
+
},
|
|
107
|
+
"required": {
|
|
108
|
+
"default": false,
|
|
109
|
+
"type": "boolean"
|
|
110
|
+
},
|
|
111
|
+
"defaultValue": {
|
|
112
|
+
"type": "string"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"required": [
|
|
116
|
+
"name",
|
|
117
|
+
"required"
|
|
118
|
+
],
|
|
119
|
+
"additionalProperties": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"required": [
|
|
124
|
+
"id",
|
|
125
|
+
"kind",
|
|
126
|
+
"name",
|
|
127
|
+
"file",
|
|
128
|
+
"props"
|
|
129
|
+
],
|
|
130
|
+
"additionalProperties": false
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"edges": {
|
|
134
|
+
"default": [],
|
|
135
|
+
"type": "array",
|
|
136
|
+
"items": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"properties": {
|
|
139
|
+
"from": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"minLength": 1
|
|
142
|
+
},
|
|
143
|
+
"to": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"minLength": 1
|
|
146
|
+
},
|
|
147
|
+
"relation": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"enum": [
|
|
150
|
+
"renders",
|
|
151
|
+
"imports"
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
"confidence": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"enum": [
|
|
157
|
+
"EXTRACTED",
|
|
158
|
+
"INFERRED"
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"required": [
|
|
163
|
+
"from",
|
|
164
|
+
"to",
|
|
165
|
+
"relation",
|
|
166
|
+
"confidence"
|
|
167
|
+
],
|
|
168
|
+
"additionalProperties": false
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
"errors": {
|
|
172
|
+
"default": [],
|
|
173
|
+
"type": "array",
|
|
174
|
+
"items": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"properties": {
|
|
177
|
+
"code": {
|
|
178
|
+
"type": "string",
|
|
179
|
+
"minLength": 1
|
|
180
|
+
},
|
|
181
|
+
"file": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"minLength": 1
|
|
184
|
+
},
|
|
185
|
+
"message": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"minLength": 1
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"required": [
|
|
191
|
+
"code",
|
|
192
|
+
"file",
|
|
193
|
+
"message"
|
|
194
|
+
],
|
|
195
|
+
"additionalProperties": false
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"required": [
|
|
200
|
+
"version",
|
|
201
|
+
"tokens",
|
|
202
|
+
"nodes",
|
|
203
|
+
"edges",
|
|
204
|
+
"errors"
|
|
205
|
+
],
|
|
206
|
+
"additionalProperties": false
|
|
207
|
+
}
|