{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { marked, type Token } from 'marked'\r\n\r\n// Type augmentation for marked Tokens\r\ndeclare module 'marked' {\r\n  namespace Tokens {\r\n    interface Generic {\r\n      attributes?: Record<string, string>\r\n    }\r\n  }\r\n}\r\n\r\n/**\r\n * Token type with attributes property for use in walkTokens\r\n * @example\r\n * ```typescript\r\n * import { type TokenWithAttributes } from 'marked-attributes'\r\n *\r\n * marked.use({\r\n *   walkTokens(token: TokenWithAttributes) {\r\n *     token.attributes = { 'class': 'my-class' }\r\n *   }\r\n * })\r\n * ```\r\n */\r\nexport type TokenWithAttributes = Token & {\r\n  attributes?: Record<string, string>\r\n}\r\n\r\n/**\r\n * Configuration options for marked-attributes extension\r\n */\r\nexport interface markedAttributesOptions {\r\n  // Reserved for future options like:\r\n  // prefix?: string\r\n  // attributeKey?: string (default 'attributes')\r\n}\r\n\r\n/**\r\n * Creates an HTML attributes string from an object\r\n * @example createAttributesString({ 'data-id': '123', class: 'foo' }) => 'data-id=\"123\" class=\"foo\"'\r\n */\r\nfunction createAttributesString(attributes: Record<string, string>): string {\r\n  return Object.entries(attributes)\r\n    .map(([key, value]) => `${key}=\"${value}\"`)\r\n    .join(' ')\r\n}\r\n\r\n/**\r\n * Regex to match opening HTML tag and capture tag name and suffix\r\n * Captures: <tag> or <tag with following space, suffix is the closing '>'\r\n */\r\nconst tagNameRegExp = /^<(?<tag>[a-z][a-z0-9\\-]*)(?<suffix>\\s|>)/i\r\n\r\n/**\r\n * Higher-order function that wraps a renderer function to inject attributes\r\n * into the rendered HTML from token.attributes property\r\n */\r\nfunction withAttributes(render: (...args: any[]) => string): (...args: any[]) => string {\r\n  return function renderAttributes(this: any, token: any) {\r\n    if (!token.attributes) return render.call(this, token)\r\n    const attributesString = createAttributesString(token.attributes)\r\n    const html = render.call(this, token)\r\n    // Fixed regex replacement using callback function for proper capture groups\r\n    return html.replace(tagNameRegExp, (match, tag, suffix) => `<${tag} ${attributesString}${suffix}`)\r\n  }\r\n}\r\n\r\n/**\r\n * Methods to exclude from attribute wrapping.\r\n * - 'constructor': Not a rendering method\r\n * - 'options': Not a rendering method (configuration)\r\n */\r\nconst excludedMethods = ['constructor', 'options']\r\n\r\n/**\r\n * Marked extension that adds support for custom HTML attributes on any token.\r\n *\r\n * This extension configures marked.js renderer to automatically inject attributes\r\n * from token.attributes property into all rendered HTML elements. This enables\r\n * adding data-token-id or other custom attributes to any token during\r\n * lexing/processing.\r\n *\r\n * Uses dynamic iteration through marked.Renderer.prototype to automatically wrap\r\n * all renderer methods, ensuring compatibility with all current and future\r\n * renderer methods.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { marked } from 'marked'\r\n * import { markedAttributes } from 'marked-attributes'\r\n *\r\n * // Enable attribute rendering\r\n * marked.use(markedAttributes())\r\n *\r\n * // Add attributes to tokens using walkTokens\r\n * marked.use({\r\n *   walkTokens(token) {\r\n *     token.attributes = { 'data-token-id': generateId() }\r\n *   }\r\n * })\r\n *\r\n * const html = marked('**bold text**')\r\n * // Output: <p><strong data-token-id=\"...\">bold text</strong></p>\r\n * ```\r\n *\r\n * @param options - Configuration options (reserved for future use)\r\n * @returns Extension object for marked.use()\r\n */\r\nexport function markedAttributes(options: markedAttributesOptions = {}) {\r\n  // Get all renderer method names, excluding non-rendering methods\r\n  const prototypeRenderer = marked.Renderer.prototype\r\n  const rendererMethodNames = Object.getOwnPropertyNames(prototypeRenderer).filter(\r\n    name => !excludedMethods.includes(name)\r\n  )\r\n\r\n  // Dynamically wrap all renderer methods with attribute support\r\n  const renderer: Record<string, (...args: any[]) => string> = {}\r\n\r\n  for (const methodName of rendererMethodNames) {\r\n    const originalMethod = prototypeRenderer[methodName as keyof typeof prototypeRenderer]\r\n    if (typeof originalMethod === 'function') {\r\n      renderer[methodName] = withAttributes(originalMethod)\r\n    }\r\n  }\r\n\r\n  return {\r\n    renderer\r\n  }\r\n}\r\n"],"names":["createAttributesString","attributes","Object","entries","map","key","value","join","tagNameRegExp","withAttributes","render","renderAttributes","token","call","attributesString","html","replace","match","tag","suffix","excludedMethods","markedAttributes","options","prototypeRenderer","marked","Renderer","prototype","rendererMethodNames","getOwnPropertyNames","filter","name","includes","renderer","methodName","originalMethod"],"mappings":";;;;AAqCA;;;AAGG;AACH,SAASA,sBAAsBA,CAACC,UAAkC,EAAA;EAChE,OAAOC,MAAM,CAACC,OAAO,CAACF,UAAU,CAAC,CAC9BG,GAAG,CAAC,CAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,KAAK,CAAA,EAAGD,GAAG,CAAA,EAAA,EAAKC,KAAK,CAAA,CAAA,CAAG,CAAC,CAC1CC,IAAI,CAAC,GAAG,CAAC;AACd;AAEA;;;AAGG;AACH,MAAMC,aAAa,GAAG,4CAA4C;AAElE;;;AAGG;AACH,SAASC,cAAcA,CAACC,MAAkC,EAAA;AACxD,EAAA,OAAO,SAASC,gBAAgBA,CAAYC,KAAU,EAAA;AACpD,IAAA,IAAI,CAACA,KAAK,CAACX,UAAU,EAAE,OAAOS,MAAM,CAACG,IAAI,CAAC,IAAI,EAAED,KAAK,CAAC;AACtD,IAAA,MAAME,gBAAgB,GAAGd,sBAAsB,CAACY,KAAK,CAACX,UAAU,CAAC;IACjE,MAAMc,IAAI,GAAGL,MAAM,CAACG,IAAI,CAAC,IAAI,EAAED,KAAK,CAAC;AACrC;IACA,OAAOG,IAAI,CAACC,OAAO,CAACR,aAAa,EAAE,CAACS,KAAK,EAAEC,GAAG,EAAEC,MAAM,KAAK,IAAID,GAAG,CAAA,CAAA,EAAIJ,gBAAgB,CAAA,EAAGK,MAAM,EAAE,CAAC;EACpG,CAAC;AACH;AAEA;;;;AAIG;AACH,MAAMC,eAAe,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;AACG,SAAUC,gBAAgBA,CAACC,OAAA,GAAmC,EAAE,EAAA;AACpE;AACA,EAAA,MAAMC,iBAAiB,GAAGC,aAAM,CAACC,QAAQ,CAACC,SAAS;EACnD,MAAMC,mBAAmB,GAAGzB,MAAM,CAAC0B,mBAAmB,CAACL,iBAAiB,CAAC,CAACM,MAAM,CAC9EC,IAAI,IAAI,CAACV,eAAe,CAACW,QAAQ,CAACD,IAAI,CAAC,CACxC;AAED;EACA,MAAME,QAAQ,GAA+C,EAAE;AAE/D,EAAA,KAAK,MAAMC,UAAU,IAAIN,mBAAmB,EAAE;AAC5C,IAAA,MAAMO,cAAc,GAAGX,iBAAiB,CAACU,UAA4C,CAAC;AACtF,IAAA,IAAI,OAAOC,cAAc,KAAK,UAAU,EAAE;AACxCF,MAAAA,QAAQ,CAACC,UAAU,CAAC,GAAGxB,cAAc,CAACyB,cAAc,CAAC;AACvD,IAAA;AACF,EAAA;EAEA,OAAO;AACLF,IAAAA;GACD;AACH;;;;"}