{"version":3,"file":"index.cjs","names":[],"sources":["../../src/markdown/entitySpans.ts","../../src/markdown/AnalystMarkdown.tsx","../../src/markdown/AnalystMarkdown.meta.ts"],"sourcesContent":["/**\n * Entity span resolution for `AnalystMarkdown`.\n *\n * Spans arrive as offsets into the raw markdown **source**, produced by the\n * model or the enrichment service, and are resolved against the syntax tree.\n * They are never found by pattern-matching the rendered prose: a pattern that\n * finds IP addresses also finds `1.2.3.4` in \"upgrade to version 1.2.3.4\", a\n * hash pattern matches any long hex string including a commit SHA nobody can\n * pivot on, and every false positive attaches an action menu to something with\n * no entity behind it. Analyst trust does not survive the first one.\n *\n * Resolving against the source rather than the rendered text is what keeps the\n * offsets stable: every emphasis marker, link and escape would otherwise shift\n * the indices and silently attach entities to the wrong words.\n */\nimport type { EntityKind, EntityVerdict } from '@/atoms/Chip';\n\n/** The custom element the transform emits, mapped to a Chip when rendering. */\nexport const ENTITY_ELEMENT = 'octopus-entity';\n\nexport interface EntitySpan {\n  /** Start offset into the raw markdown source, inclusive. */\n  start: number;\n  /** End offset into the raw markdown source, exclusive. */\n  end: number;\n  kind: EntityKind;\n  /** Canonical full value. What a copy action yields. */\n  value: string;\n  /** Shortened text to display. Defaults to the marked source text. */\n  display?: string;\n  /** Omit when the value was never resolved. */\n  verdict?: EntityVerdict;\n  /**\n   * Enrichment facts shown in the entity menu. Kept off the rendered element\n   * and looked up by canonical value at open time, so nothing structural ends\n   * up serialised into DOM attributes.\n   */\n  attributes?: { label: string; value: string }[];\n}\n\n/** Minimal structural view of mdast, so this module needs no tree typings. */\ninterface MdNode {\n  type: string;\n  value?: string;\n  children?: MdNode[];\n  position?: { start: { offset?: number }; end: { offset?: number } };\n  data?: Record<string, unknown>;\n}\n\n/**\n * Node types whose text must never be marked.\n *\n * Code is copied verbatim as a unit and an interactive element inside it\n * corrupts that. Headings and links already own their click behaviour, so a\n * second target inside them is ambiguous. The rest carry no prose.\n */\nconst PROTECTED_TYPES: ReadonlySet<string> = new Set([\n  'code',\n  'inlineCode',\n  'heading',\n  'link',\n  'linkReference',\n  'image',\n  'imageReference',\n  'definition',\n  'footnoteDefinition',\n  'html',\n  'yaml',\n  'toml',\n]);\n\nexport interface ApplyEntitySpansOptions {\n  /**\n   * Cap on marked spans per top-level block. A summary genuinely dense with\n   * indicators wants a table underneath it, not more chips inside it.\n   */\n  maxPerBlock?: number;\n  /** Reports spans that could not be applied. Defaults to a dev-only warning. */\n  onSkipped?: (span: EntitySpan, reason: string) => void;\n}\n\nconst DEFAULT_MAX_PER_BLOCK = 8;\n\nfunction warnSkipped(span: EntitySpan, reason: string): void {\n  if (process.env.NODE_ENV === 'production') return;\n  console.warn(\n    `[Octopus UI] AnalystMarkdown skipped the entity span for \"${span.value}\" ` +\n      `at ${span.start}-${span.end}: ${reason}`,\n  );\n}\n\ninterface BlockState {\n  /** Values already marked in this block, so later mentions stay plain text. */\n  seen: Set<string>;\n  remaining: number;\n}\n\n/**\n * Rewrites text nodes in place so each applicable span becomes an entity node.\n *\n * Mutates the tree, which is what a remark transformer is expected to do.\n */\nexport function applyEntitySpans(\n  tree: MdNode,\n  spans: readonly EntitySpan[],\n  options: ApplyEntitySpansOptions = {},\n): void {\n  if (spans.length === 0) return;\n\n  const maxPerBlock = options.maxPerBlock ?? DEFAULT_MAX_PER_BLOCK;\n  const ordered = [...spans].sort((a, b) => a.start - b.start || b.end - a.end);\n\n  // A span that crosses a node boundary is examined once per text node it\n  // touches, so reporting is deduplicated here rather than at each call site --\n  // otherwise one bad span from the resolver looks like three.\n  const report = options.onSkipped ?? warnSkipped;\n  const reported = new Set<EntitySpan>();\n  const onSkipped = (span: EntitySpan, reason: string) => {\n    if (reported.has(span)) return;\n    reported.add(span);\n    report(span, reason);\n  };\n\n  // Per top-level block, so the first-mention rule and the density cap are\n  // scoped to a paragraph rather than to the whole document.\n  for (const block of tree.children ?? []) {\n    visit(block, false, ordered, { seen: new Set(), remaining: maxPerBlock }, onSkipped);\n  }\n}\n\nfunction visit(\n  node: MdNode,\n  isProtected: boolean,\n  spans: readonly EntitySpan[],\n  state: BlockState,\n  onSkipped: NonNullable<ApplyEntitySpansOptions['onSkipped']>,\n): void {\n  const protectedHere = isProtected || PROTECTED_TYPES.has(node.type);\n  const children = node.children;\n  if (!children || children.length === 0) return;\n\n  // A GFM table's first row is its header, which labels columns rather than\n  // carrying prose.\n  const headerRowIndex = node.type === 'table' ? 0 : -1;\n\n  const next: MdNode[] = [];\n  children.forEach((child, index) => {\n    const childProtected = protectedHere || index === headerRowIndex;\n\n    if (child.type === 'text' && !childProtected) {\n      next.push(...splitTextNode(child, spans, state, onSkipped));\n      return;\n    }\n\n    visit(child, childProtected, spans, state, onSkipped);\n    next.push(child);\n  });\n\n  node.children = next;\n}\n\n/**\n * Replaces one text node with an alternating run of text and entity nodes.\n * Returns the node untouched when nothing applies.\n */\nfunction splitTextNode(\n  node: MdNode,\n  spans: readonly EntitySpan[],\n  state: BlockState,\n  onSkipped: NonNullable<ApplyEntitySpansOptions['onSkipped']>,\n): MdNode[] {\n  const nodeStart = node.position?.start.offset;\n  const nodeEnd = node.position?.end.offset;\n  const text = node.value ?? '';\n\n  if (nodeStart === undefined || nodeEnd === undefined) return [node];\n\n  // If the node's text is not the same length as the source range it claims,\n  // character references or escapes were resolved during parsing and relative\n  // offsets no longer line up. Marking anyway would shift every span in this\n  // node onto neighbouring words, so the node is left alone.\n  if (text.length !== nodeEnd - nodeStart) {\n    for (const span of spans) {\n      if (span.start >= nodeStart && span.end <= nodeEnd) {\n        onSkipped(span, 'the surrounding text node was rewritten during parsing');\n      }\n    }\n    return [node];\n  }\n\n  const out: MdNode[] = [];\n  let cursor = nodeStart;\n\n  for (const span of spans) {\n    // Spans are sorted by start, so nothing later can touch this node.\n    if (span.start >= nodeEnd) break;\n    // Belongs to an earlier node, which has already dealt with it.\n    if (span.end <= nodeStart) continue;\n\n    if (span.start < nodeStart || span.end > nodeEnd) {\n      onSkipped(span, 'it crosses a markdown node boundary');\n      continue;\n    }\n    if (span.start < cursor) {\n      onSkipped(span, 'it overlaps an earlier span');\n      continue;\n    }\n    if (state.remaining <= 0) {\n      onSkipped(span, 'the block already reached its marked-span limit');\n      continue;\n    }\n    // Only the first mention in a block is marked: the chip already opens the\n    // same menu, and a paragraph where every repeat is a chip is unreadable.\n    if (state.seen.has(span.value)) continue;\n\n    if (span.start > cursor) {\n      out.push(textNode(text.slice(cursor - nodeStart, span.start - nodeStart)));\n    }\n    out.push(entityNode(span, text.slice(span.start - nodeStart, span.end - nodeStart)));\n\n    state.seen.add(span.value);\n    state.remaining -= 1;\n    cursor = span.end;\n  }\n\n  if (out.length === 0) return [node];\n  if (cursor < nodeEnd) out.push(textNode(text.slice(cursor - nodeStart)));\n  return out;\n}\n\nfunction textNode(value: string): MdNode {\n  return { type: 'text', value };\n}\n\n/**\n * Emits a node that mdast-util-to-hast turns into `<octopus-entity>` carrying\n * `data-*` attributes. Data attributes rather than bespoke props so nothing\n * reaches the DOM that React would warn about if the mapping were ever missing.\n */\nfunction entityNode(span: EntitySpan, sourceText: string): MdNode {\n  const hProperties: Record<string, string> = {\n    'data-entity-kind': span.kind,\n    'data-entity-value': span.value,\n    'data-entity-display': span.display ?? sourceText,\n  };\n  if (span.verdict) hProperties['data-entity-verdict'] = span.verdict;\n\n  return {\n    type: 'octopusEntity',\n    children: [textNode(span.display ?? sourceText)],\n    data: { hName: ENTITY_ELEMENT, hProperties },\n  };\n}\n\n/**\n * remark plugin form, for `ReactMarkdown`'s `remarkPlugins`.\n *\n * @example remarkPlugins={[remarkGfm, [remarkEntitySpans, { spans }]]}\n */\nexport function remarkEntitySpans(\n  options: ApplyEntitySpansOptions & { spans?: readonly EntitySpan[] } = {},\n) {\n  const { spans = [], ...rest } = options;\n  return (tree: MdNode) => applyEntitySpans(tree, spans, rest);\n}\n","/**\n * AnalystMarkdown\n * Classification: custom\n *\n * Renders an AI-written investigation summary, with the entity values inside it\n * turned into interactive chips an analyst can copy and pivot on.\n *\n * Published as `@aistrike-dev/ui/markdown`, deliberately NOT re-exported from\n * `src/index.ts`: `react-markdown` and its unified/remark tree are a large\n * dependency and a consumer that never renders model output should never pay\n * for one. `scripts/assert-no-markdown-in-root.ts` enforces that at build time.\n *\n * ### Safety\n *\n * The input is model output, so it is treated as untrusted. `react-markdown`\n * builds the tree itself and never parses raw HTML unless `rehype-raw` is added\n * -- which is why it is not added here -- so markup in the source renders as\n * text rather than as elements. It also sanitises URLs to safe protocols, which\n * stops a generated `javascript:` link. Both properties depend on nothing being\n * bolted on: adding `rehype-raw` to this component would make it an XSS sink.\n */\nimport { useMemo, useState } from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\nimport Link from '@mui/material/Link';\nimport Typography from '@mui/material/Typography';\nimport AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';\nimport { Chip, type EntityKind, type EntityVerdict } from '@/atoms/Chip';\nimport {\n  EntityMenu,\n  type Entity,\n  type EntityMenuAction,\n} from '@/molecules/EntityMenu';\nimport { fontFamily } from '@/tokens/typography';\nimport { ENTITY_ELEMENT, remarkEntitySpans, type EntitySpan } from './entitySpans';\n\nexport interface AnalystMarkdownProps {\n  /** The raw markdown. Entity offsets are resolved against this string. */\n  source: string;\n  /**\n   * Resolved entity spans, as offsets into `source`. Supplied by the model or\n   * the enrichment service -- never derived by pattern-matching the prose.\n   */\n  entities?: readonly EntitySpan[];\n  /**\n   * Renders one marker on the block declaring it AI generated. Broad visibility\n   * in Carbon's terms: one marker for the whole generated block, never one per\n   * entity chip, which would be decoration and would collide with verdict tint.\n   */\n  aiGenerated?: boolean;\n  /** Cap on marked spans per block. Defaults to 8. */\n  maxMarkedPerBlock?: number;\n  /** Pivot actions appended to every entity menu, after the copy actions. */\n  entityActions?: EntityMenuAction[];\n  onEntityAction?: (actionId: string, entity: Entity) => void;\n}\n\ninterface OpenEntity {\n  anchorEl: HTMLElement;\n  entity: Entity;\n}\n\n/** Props react-markdown passes down for the custom entity element. */\ninterface EntityElementProps {\n  'data-entity-kind'?: string;\n  'data-entity-value'?: string;\n  'data-entity-display'?: string;\n  'data-entity-verdict'?: string;\n}\n\n/**\n * @example\n * <AnalystMarkdown\n *   source={summary.markdown}\n *   entities={summary.entities}\n *   aiGenerated\n *   entityActions={[{ id: 'pivot', label: 'Pivot to search' }]}\n *   onEntityAction={handleEntityAction}\n * />\n */\nexport function AnalystMarkdown({\n  source,\n  entities = [],\n  aiGenerated = false,\n  maxMarkedPerBlock,\n  entityActions,\n  onEntityAction,\n}: AnalystMarkdownProps) {\n  const [open, setOpen] = useState<OpenEntity | null>(null);\n\n  const remarkPlugins = useMemo(\n    () => [remarkGfm, [remarkEntitySpans, { spans: entities, maxPerBlock: maxMarkedPerBlock }]],\n    [entities, maxMarkedPerBlock],\n  );\n\n  const components = useMemo<Components>(() => {\n    /**\n     * The rendered element carries only strings, so enrichment attributes are\n     * looked up from the span list by canonical value rather than serialised\n     * into DOM attributes.\n     */\n    const attributesFor = (value: string) =>\n      entities.find((span) => span.value === value)?.attributes;\n\n    const EntityElement = ({\n      'data-entity-kind': kind,\n      'data-entity-value': value,\n      'data-entity-display': display,\n      'data-entity-verdict': verdict,\n    }: EntityElementProps) => {\n      if (!kind || !value) return null;\n      const entity: Entity = {\n        kind: kind as EntityKind,\n        value,\n        display,\n        verdict: verdict as EntityVerdict | undefined,\n        attributes: attributesFor(value),\n      };\n      return (\n        <Chip\n          purpose=\"entity\"\n          kind={entity.kind}\n          value={entity.value}\n          display={entity.display}\n          verdict={entity.verdict}\n          onOpen={(event) => setOpen({ anchorEl: event.currentTarget, entity })}\n        />\n      );\n    };\n\n    const standard: Components = {\n      p: ({ children }) => (\n        <Typography variant=\"body1\" sx={{ mb: 1.5, '&:last-child': { mb: 0 } }}>\n          {children}\n        </Typography>\n      ),\n      h1: ({ children }) => <Heading level=\"h5\">{children}</Heading>,\n      h2: ({ children }) => <Heading level=\"h6\">{children}</Heading>,\n      h3: ({ children }) => <Heading level=\"subtitle1\">{children}</Heading>,\n      h4: ({ children }) => <Heading level=\"subtitle2\">{children}</Heading>,\n      h5: ({ children }) => <Heading level=\"subtitle2\">{children}</Heading>,\n      h6: ({ children }) => <Heading level=\"subtitle2\">{children}</Heading>,\n\n      ul: ({ children }) => (\n        <Box component=\"ul\" sx={{ pl: 3, my: 1.5, display: 'grid', gap: 0.5 }}>\n          {children}\n        </Box>\n      ),\n      ol: ({ children }) => (\n        <Box component=\"ol\" sx={{ pl: 3, my: 1.5, display: 'grid', gap: 0.5 }}>\n          {children}\n        </Box>\n      ),\n      li: ({ children }) => (\n        <Typography component=\"li\" variant=\"body1\">\n          {children}\n        </Typography>\n      ),\n\n      a: ({ href, children }) => (\n        // Model output is untrusted, so an outbound link never gets access to\n        // this window via `opener`.\n        <Link href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\">\n          {children}\n        </Link>\n      ),\n\n      code: ({ children }) => (\n        <Box\n          component=\"code\"\n          sx={{\n            fontFamily: fontFamily.mono,\n            fontSize: '0.875em',\n            px: 0.5,\n            py: 0.125,\n            borderRadius: 0.5,\n            bgcolor: 'action.hover',\n          }}\n        >\n          {children}\n        </Box>\n      ),\n      pre: ({ children }) => (\n        <Box\n          component=\"pre\"\n          sx={{\n            fontFamily: fontFamily.mono,\n            fontSize: '0.8125rem',\n            p: 1.5,\n            my: 1.5,\n            overflowX: 'auto',\n            borderRadius: 1,\n            bgcolor: 'action.hover',\n            '& code': { bgcolor: 'transparent', p: 0 },\n          }}\n        >\n          {children}\n        </Box>\n      ),\n\n      blockquote: ({ children }) => (\n        <Box\n          sx={{\n            borderLeft: 2,\n            borderColor: 'divider',\n            pl: 2,\n            my: 1.5,\n            color: 'text.secondary',\n          }}\n        >\n          {children}\n        </Box>\n      ),\n\n      table: ({ children }) => (\n        <Box sx={{ overflowX: 'auto', my: 1.5 }}>\n          <Box\n            component=\"table\"\n            sx={{ borderCollapse: 'collapse', width: '100%', fontSize: '0.875rem' }}\n          >\n            {children}\n          </Box>\n        </Box>\n      ),\n      th: ({ children }) => (\n        <Box\n          component=\"th\"\n          sx={{\n            textAlign: 'left',\n            px: 1,\n            py: 0.75,\n            borderBottom: 1,\n            borderColor: 'divider',\n            color: 'text.secondary',\n            fontWeight: 600,\n          }}\n        >\n          {children}\n        </Box>\n      ),\n      td: ({ children }) => (\n        <Box\n          component=\"td\"\n          sx={{ px: 1, py: 0.75, borderBottom: 1, borderColor: 'divider' }}\n        >\n          {children}\n        </Box>\n      ),\n\n      hr: () => <Divider sx={{ my: 2 }} />,\n    };\n\n    // The entity element is not an intrinsic HTML tag, so it is merged in after\n    // the typed map rather than declared inside it.\n    return { ...standard, [ENTITY_ELEMENT]: EntityElement } as Components;\n  }, [entities]);\n\n  return (\n    <Box>\n      {aiGenerated && <AiMarker />}\n\n      <ReactMarkdown remarkPlugins={remarkPlugins as never} components={components}>\n        {source}\n      </ReactMarkdown>\n\n      {open && (\n        <EntityMenu\n          entity={open.entity}\n          anchorEl={open.anchorEl}\n          open\n          onClose={() => setOpen(null)}\n          actions={entityActions}\n          onAction={onEntityAction}\n        />\n      )}\n    </Box>\n  );\n}\n\nfunction Heading({ level, children }: { level: 'h5' | 'h6' | 'subtitle1' | 'subtitle2'; children: React.ReactNode }) {\n  return (\n    <Typography variant={level} sx={{ mt: 2, mb: 1, '&:first-of-type': { mt: 0 } }}>\n      {children}\n    </Typography>\n  );\n}\n\n/**\n * One marker for the whole generated block. Carbon's rules for an AI label\n * apply: it is the indicator, it must not be decorative, and it must not be an\n * action trigger -- so this is a static chip, not a button.\n */\nfunction AiMarker() {\n  return (\n    <Box sx={{ mb: 1.5 }}>\n      <Chip\n        purpose=\"category\"\n        size=\"small\"\n        label=\"AI generated\"\n        icon={<AutoAwesomeIcon />}\n      />\n    </Box>\n  );\n}\n\nexport default AnalystMarkdown;\n","import { defineMeta } from '@/registry/types';\n\nexport const analystMarkdownMeta = defineMeta({\n  name: 'AnalystMarkdown',\n  level: 'organism',\n  category: 'data-display',\n  classification: 'custom',\n  description:\n    'Renders an AI-written investigation summary, turning resolved entity values inside the prose into interactive chips an analyst can copy and pivot on. Ships from the @aistrike-dev/ui/markdown subpath so the markdown renderer stays out of the root bundle.',\n  baseLibrary: 'react-markdown',\n  importPath: '@aistrike-dev/ui/markdown',\n  requiredProps: ['source'],\n  optionalProps: [\n    'entities',\n    'aiGenerated',\n    'maxMarkedPerBlock',\n    'entityActions',\n    'onEntityAction',\n  ],\n  supportedStates: ['default', 'ai-generated', 'entity-menu-open', 'no-entities'],\n  designTokens: ['typography', 'spacing', 'colors'],\n  accessibility: [\n    'Entity chips join the tab order in reading order, and each opens its menu with Enter or Space.',\n    'Every entity has an accessible name carrying its kind, its full canonical value and its verdict, since the visible text may be truncated and the tint is not perceivable to everyone.',\n    'A long summary is a lot of tab stops. Keep the marked-span cap low and treat a chip-dense paragraph as a content problem upstream rather than a navigation problem to work around.',\n  ],\n  usageExamples: [\n    \"import { AnalystMarkdown } from '@aistrike-dev/ui/markdown';\",\n    '<AnalystMarkdown source={summary.markdown} entities={summary.entities} aiGenerated />',\n    '<AnalystMarkdown source={md} entities={spans} entityActions={[{ id: \"pivot\", label: \"Pivot to search\" }]} onEntityAction={run} />',\n  ],\n  rules: [\n    'Import from `@aistrike-dev/ui/markdown`, never from the root entry; the root stays free of the markdown renderer.',\n    'Supply `entities` as offsets into the exact `source` string you pass, produced by the model or the enrichment service.',\n    'Mark only what an analyst can act on: network and file indicators, principals, and catalogue references. Not ordinary nouns, product names, times or counts.',\n    'Pass the canonical full value as `value` and any shortened form as `display`, so a truncated hash still copies in full.',\n    'Set `aiGenerated` for model-written content. One marker covers the block.',\n    'Keep `maxMarkedPerBlock` at or below the default of 8. A summary genuinely dense with indicators wants a table underneath it, not more chips inside it.',\n    'Put pivot and lookup actions in `entityActions`; keep response actions on the entity page.',\n  ],\n  antiPatterns: [\n    'Do not derive entity spans by pattern-matching the prose. A pattern for IP addresses also matches a version number, and a hash pattern matches any long hex string; every false positive attaches a menu to something with no entity behind it.',\n    'Do not attach a verdict to a value that was not resolved; that is a fabricated claim.',\n    'Do not compute offsets against rendered text. Emphasis markers, links and escapes shift the indices and silently attach entities to the wrong words.',\n    'Do not add rehype-raw or any raw-HTML plugin. The input is model output, and parsing HTML in it would make this component an XSS sink.',\n    'Do not put an AI marker on every chip; mark the generated block once.',\n    'Do not use this for prose the product wrote itself; plain Typography is lighter and needs no renderer.',\n  ],\n  llmSafe: true,\n  whenToUse: [\n    'AI-generated investigation or alert summaries where analysts need to act on the values',\n    'Any model output whose entities have already been resolved to structured spans',\n  ],\n  whenNotToUse: [\n    'Static product copy (use Typography)',\n    'Untrusted markdown with no entity resolution (there is nothing to gain over Typography)',\n    'Code display (use CodeEditor from @aistrike-dev/ui/monaco)',\n  ],\n});\n\nexport default analystMarkdownMeta;\n"],"mappings":"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"}