{"version":3,"sources":["jsdelivr-header.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/KoenigDecoratorNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/read-text-content.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/render-empty-container.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/visibility.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/generate-decorator-node.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/build-clean-basic-html-for-element.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/read-caption-from-element.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/read-image-attributes-from-element.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/image/image-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/get-available-image-widths.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/is-local-content-image.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/is-unsplash-image.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/srcset-attribute.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/get-resized-image-dimensions.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/add-create-document-option.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/image/image-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/image/ImageNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/codeblock/codeblock-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/codeblock/codeblock-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/codeblock/CodeBlockNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/markdown/markdown-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/markdown/MarkdownNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/video/video-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/video/video-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/video/VideoNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/audio/audio-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/audio/audio-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/audio/AudioNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/clean-dom.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/callout/callout-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/callout/callout-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/callout/CalloutNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/call-to-action/calltoaction-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/rgb-to-hex.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/call-to-action/calltoaction-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/call-to-action/CallToActionNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/aside/AsideParser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/aside/AsideNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/horizontalrule/horizontalrule-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/horizontalrule/horizontalrule-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/horizontalrule/HorizontalRuleNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/html/html-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/html/html-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/html/HtmlNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/toggle/toggle-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/tagged-template-fns.mjs","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/toggle/toggle-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/toggle/ToggleNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/button/button-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/render-helpers/email-button.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/button/button-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/button/ButtonNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/bookmark/bookmark-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/escape-html.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/truncate.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/bookmark/bookmark-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/bookmark/BookmarkNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/size-byte-converter.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/file/file-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/file/file-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/file/FileNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/slugify.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/header/renderers/v1/header-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/header/parsers/header-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/header/renderers/v2/header-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/header/HeaderNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/paywall/paywall-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/paywall/paywall-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/paywall/PaywallNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/product/product-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/product/product-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/product/ProductNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/embed/embed-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/embed/types/twitter.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/embed/embed-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/embed/EmbedNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/replacement-strings.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/email/email-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/email/EmailNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/gallery/gallery-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/gallery/gallery-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/gallery/GalleryNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/email-cta/email-cta-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/email-cta/EmailCtaNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/signup/signup-parser.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/signup/signup-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/signup/SignupNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/utils/set-src-background-from-parent.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/transistor/transistor-renderer.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/transistor/TransistorNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/ExtendedTextNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/ExtendedHeadingNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/ExtendedQuoteNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/TKNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/at-link/AtLinkNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/at-link/AtLinkSearchNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/nodes/zwnj/ZWNJNode.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/serializers/linebreak.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/serializers/paragraph.js","/npm/@tryghost/kg-default-nodes@2.0.13/lib/kg-default-nodes.js"],"names":[],"mappings":"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","file":"/npm/@tryghost/kg-default-nodes@2.0.13/cjs/kg-default-nodes.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@tryghost/kg-default-nodes@2.0.13/cjs/kg-default-nodes.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/* eslint-disable ghost/filenames/match-exported-class */\n/* c8 ignore start */\nimport {DecoratorNode} from 'lexical';\n\nexport class KoenigDecoratorNode extends DecoratorNode {\n}\n\nexport function $isKoenigCard(node) {\n    return node instanceof KoenigDecoratorNode;\n}\n/* c8 ignore end */\n","import {$getRoot} from 'lexical';\n\n// when used nodes are used client-side their data attributes may be an editor\n// instance rather than a string in the case of nested editors\nexport default function readTextContent(node, property) {\n    const propertyName = `__${property}`;\n    const propertyEditorName = `${propertyName}Editor`;\n\n    // prefer the editor if it exists as the underlying value isn't written until export\n    const value = node[propertyEditorName] || node[propertyName];\n\n    if (!value) {\n        return '';\n    }\n\n    if (typeof value === 'string') {\n        return value;\n    }\n\n    if (typeof value === 'number') {\n        return value.toString();\n    }\n\n    if (typeof value.getEditorState === 'function') {\n        let text = '';\n\n        value.getEditorState().read(() => {\n            text = $getRoot().getTextContent();\n        });\n\n        return text;\n    }\n\n    return '';\n}\n","/*\n * Renders an empty container element\n * In the returned object, `type: 'inner'` is picked up by the `@tryghost/kg-lexical-html-renderer` package\n * to render the inner content of the container element (in this case, nothing)\n *\n * @see @tryghost/kg-lexical-html-renderer package\n * @see https://github.com/TryGhost/Koenig/blob/e14c008e176f7a1036fe3f3deb924ed69a69191f/packages/kg-lexical-html-renderer/lib/convert-to-html-string.js#L29\n */\nexport function renderEmptyContainer(document) {\n    const emptyContainer = document.createElement('span');\n    return {element: emptyContainer, type: 'inner'};\n}\n","import {renderEmptyContainer} from './render-empty-container';\n\nexport const ALL_MEMBERS_SEGMENT = 'status:free,status:-free';\nexport const PAID_MEMBERS_SEGMENT = 'status:-free'; // paid + comped\nexport const FREE_MEMBERS_SEGMENT = 'status:free';\nexport const NO_MEMBERS_SEGMENT = '';\n\nconst DEFAULT_VISIBILITY = {\n    web: {\n        nonMember: true,\n        memberSegment: ALL_MEMBERS_SEGMENT\n    },\n    email: {\n        memberSegment: ALL_MEMBERS_SEGMENT\n    }\n};\n\nfunction isNullish(value) {\n    return value === null || value === undefined;\n}\n\n// ensure we always work with a deep copy to avoid accidental ref mutations\nexport function buildDefaultVisibility() {\n    return JSON.parse(JSON.stringify(DEFAULT_VISIBILITY));\n}\n\nexport function isOldVisibilityFormat(visibility) {\n    return !Object.prototype.hasOwnProperty.call(visibility, 'web')\n        || !Object.prototype.hasOwnProperty.call(visibility, 'email')\n        || !Object.prototype.hasOwnProperty.call(visibility.web, 'nonMember')\n        || isNullish(visibility.web.memberSegment)\n        || isNullish(visibility.email.memberSegment);\n}\n\nexport function isVisibilityRestricted(visibility) {\n    if (isOldVisibilityFormat(visibility)) {\n        return visibility.showOnEmail === false\n            || visibility.showOnWeb === false\n            || visibility.emailOnly === true\n            || visibility.segment !== '';\n    } else {\n        return visibility.web.nonMember === false\n            || visibility.web.memberSegment !== ALL_MEMBERS_SEGMENT\n            || visibility.email.memberSegment !== ALL_MEMBERS_SEGMENT;\n    }\n}\n\n// old formats...\n//\n// \"segment\" only applies to email visibility\n// {emailOnly: true/false, segment: ''}\n// {showOnWeb: true/false, showOnEmail: true/false, segment: 'status:free,status:-free'}\n//\n// segment: '' = everyone\n// segment: 'status:free' = free members\n// segment: 'status:paid' = paid members (incorrect, misses comped)\n// segment: 'status:-free' = paid members (correct, includes comped)\n// segment: 'status:-free+status:-paid' = no-one (incorrect, misses comped)\n//\n// new format...\n//\n// {\n//     web: {\n//         nonMember: true/false,\n//         memberSegment: 'status:free,status:-free'\n//     },\n//     email: {\n//         memberSegment: 'status:free,status:-free'\n//     }\n// }\n//\n// memberSegment: '' = no-one\n// memberSegment: 'status:free,status:-free' = everyone\n// memberSegment: 'status:free' = free members\n// memberSegment: 'status:-free' = paid + comped members\nexport function migrateOldVisibilityFormat(visibility) {\n    if (!visibility || !isOldVisibilityFormat(visibility)) {\n        return visibility;\n    }\n\n    // deep clone to avoid mutating the original object\n    const newVisibility = JSON.parse(JSON.stringify(visibility));\n\n    // ensure we have expected objects ready to populate\n    newVisibility.web ??= {};\n    newVisibility.email ??= {};\n\n    // convert web visibility, old formats only had on/off for web visibility rather than specific segments\n    if (isNullish(visibility.showOnWeb) && isNullish(visibility.emailOnly)) {\n        newVisibility.web = buildDefaultVisibility().web;\n    } else if (!isNullish(visibility.emailOnly)) {\n        newVisibility.web.nonMember = !visibility.emailOnly;\n        newVisibility.web.memberSegment = visibility.emailOnly ? NO_MEMBERS_SEGMENT : ALL_MEMBERS_SEGMENT;\n    } else {\n        newVisibility.web.nonMember = visibility.showOnWeb;\n        newVisibility.web.memberSegment = visibility.showOnWeb ? ALL_MEMBERS_SEGMENT : NO_MEMBERS_SEGMENT;\n    }\n\n    // convert email visibility, taking into account the old (and sometimes incorrect) segment formats\n    if (isNullish(visibility.showOnEmail) && isNullish(visibility.emailOnly)) {\n        newVisibility.email = buildDefaultVisibility().email;\n    } else if (visibility.showOnEmail === false) {\n        newVisibility.email.memberSegment = NO_MEMBERS_SEGMENT;\n    } else if (visibility.segment === 'status:-free+status:-paid') {\n        newVisibility.email.memberSegment = NO_MEMBERS_SEGMENT;\n    } else if (visibility.segment === 'status:free') {\n        newVisibility.email.memberSegment = FREE_MEMBERS_SEGMENT;\n    } else if (visibility.segment === 'status:paid' || visibility.segment === 'status:-free') {\n        newVisibility.email.memberSegment = PAID_MEMBERS_SEGMENT;\n    } else if (!visibility.segment) {\n        newVisibility.email.memberSegment = ALL_MEMBERS_SEGMENT;\n    }\n\n    return newVisibility;\n}\n\nexport function renderWithVisibility(originalRenderOutput, visibility, options) {\n    const document = originalRenderOutput.element.ownerDocument;\n    const content = _getRenderContent(originalRenderOutput);\n\n    visibility = migrateOldVisibilityFormat(visibility);\n\n    if (options.target === 'email') {\n        if (visibility.email.memberSegment === NO_MEMBERS_SEGMENT) {\n            return renderEmptyContainer(document);\n        }\n\n        if (visibility.email.memberSegment === ALL_MEMBERS_SEGMENT) {\n            return originalRenderOutput;\n        }\n\n        return _renderWithEmailVisibility(document, content, visibility.email);\n    }\n\n    const isNotVisibleOnWeb =\n        visibility.web.nonMember === false &&\n        visibility.web.memberSegment === NO_MEMBERS_SEGMENT;\n\n    if (isNotVisibleOnWeb) {\n        return renderEmptyContainer(document);\n    }\n\n    const hasWebVisibilityRestrictions =\n        visibility.web.nonMember !== true ||\n        visibility.web.memberSegment !== ALL_MEMBERS_SEGMENT;\n\n    if (hasWebVisibilityRestrictions) {\n        return _renderWithWebVisibility(document, content, visibility.web);\n    }\n\n    return originalRenderOutput;\n}\n\n/* Private functions -------------------------------------------------------- */\n\nfunction _getRenderContent({element, type}) {\n    if (type === 'inner') {\n        return element.innerHTML;\n    } else if (type === 'value') {\n        if ('value' in element) {\n            return element.value;\n        }\n        return '';\n    } else {\n        return element.outerHTML;\n    }\n}\n\nfunction _renderWithEmailVisibility(document, content, emailVisibility) {\n    const {memberSegment} = emailVisibility;\n    const container = document.createElement('div');\n    container.innerHTML = content;\n    container.setAttribute('data-gh-segment', memberSegment);\n    container.classList.add('kg-visibility-wrapper');\n    return {element: container, type: 'html'};\n}\n\nfunction _renderWithWebVisibility(document, content, webVisibility) {\n    const {nonMember, memberSegment} = webVisibility;\n    const wrappedContent = `\\n<!--kg-gated-block:begin nonMember:${nonMember} memberSegment:\"${memberSegment}\" -->${content}<!--kg-gated-block:end-->\\n`;\n    const textarea = document.createElement('textarea');\n    textarea.value = wrappedContent;\n    return {element: textarea, type: 'value'};\n}\n","import {KoenigDecoratorNode} from './KoenigDecoratorNode';\nimport readTextContent from './utils/read-text-content';\nimport {buildDefaultVisibility, isVisibilityRestricted, migrateOldVisibilityFormat} from './utils/visibility';\n/**\n * Validates the required arguments passed to `generateDecoratorNode`\n*/\nfunction validateArguments(nodeType, properties) {\n    /* eslint-disable ghost/ghost-custom/no-native-error */\n    /* c8 ignore start */\n    if (!nodeType) {\n        throw new Error({message: '[generateDecoratorNode] A unique \"nodeType\" should be provided'});\n    }\n\n    properties.forEach((prop) => {\n        if (!('name' in prop) || !('default' in prop)){\n            throw new Error({message: '[generateDecoratorNode] Properties should have both \"name\" and \"default\" attributes.'});\n        }\n\n        if (prop.urlType && !['url', 'html', 'markdown'].includes(prop.urlType)) {\n            throw new Error({message: '[generateDecoratorNode] \"urlType\" should be either \"url\", \"html\" or \"markdown\"'});\n        }\n\n        if ('wordCount' in prop && typeof prop.wordCount !== 'boolean') {\n            throw new Error({message: '[generateDecoratorNode] \"wordCount\" should be of boolean type.'});\n        }\n    });\n    /* c8 ignore stop */\n}\n\n/**\n * @typedef {Object} DecoratorNodeProperty\n * @property {string} name - The property's name.\n * @property {*} default - The property's default value\n * @property {('url'|'html'|'markdown'|null)} urlType - If the property contains a URL, the URL's type: 'url', 'html' or 'markdown'. Use 'url' is the property contains only a URL, 'html' or 'markdown' if the property contains HTML or markdown code, that may contain URLs.\n * @property {boolean} wordCount - Whether the property should be counted in the word count\n *\n * @param {string} nodeType – The node's type (must be unique)\n * @param {DecoratorNodeProperty[]} properties - An array of properties for the generated class\n * @param {boolean} hasVisibility - Whether to add a visibility property to the node\n * @param {Function} defaultRenderFn - A function that returns a @tryghost/kg-lexical-html-renderer compatible object, e.g. {element: Div, type: 'inner}\n * @returns {Object} - The generated class.\n */\nexport function generateDecoratorNode({nodeType, properties = [], defaultRenderFn, version = 1, hasVisibility = false}) {\n    validateArguments(nodeType, properties);\n\n    // Adds a `privateName` field to the properties for convenience (e.g. `__name`):\n    // properties: [{name: 'name', privateName: '__name', type: 'string', default: 'hello'}, {...}]\n    properties = properties.map((prop) => {\n        return {...prop, privateName: `__${prop.name}`};\n    });\n\n    // Adds `visibility` property to the properties array if `hasVisibility` is true\n    // uses a getter for `default` to avoid problems with mutation of nested objects\n    if (hasVisibility) {\n        properties.push({\n            name: 'visibility',\n            get default() {\n                return buildDefaultVisibility();\n            },\n            privateName: '__visibility'\n        });\n    }\n\n    class GeneratedDecoratorNode extends KoenigDecoratorNode {\n        constructor(data = {}, key) {\n            super(key);\n            properties.forEach((prop) => {\n                if (typeof prop.default === 'boolean') {\n                    this[prop.privateName] = data[prop.name] ?? prop.default;\n                } else {\n                    this[prop.privateName] = data[prop.name] || prop.default;\n                }\n            });\n        }\n\n        /**\n         * Returns the node's unique type\n         * @extends DecoratorNode\n         * @see https://lexical.dev/docs/concepts/nodes#extending-decoratornode\n         * @returns {string}\n         */\n        static getType() {\n            return nodeType;\n        }\n\n        /**\n         * Creates a copy of an existing node with all its properties\n         * @extends DecoratorNode\n         * @see https://lexical.dev/docs/concepts/nodes#extending-decoratornode\n         */\n        static clone(node) {\n            return new this(node.getDataset(), node.__key);\n        }\n\n        /**\n         * Returns default values for any properties, allowing our editor code\n         * to detect when a property has been changed\n         */\n        static getPropertyDefaults() {\n            return properties.reduce((obj, prop) => {\n                obj[prop.name] = prop.default;\n                return obj;\n            }, {});\n        }\n\n        /**\n         * Transforms URLs contained in the payload to relative paths (`__GHOST_URL__/relative/path/`),\n         * so that URLs to be changed without having to update the database\n         * @see https://github.com/TryGhost/SDK/tree/main/packages/url-utils\n         */\n        static get urlTransformMap() {\n            let map = {};\n\n            properties.forEach((prop) => {\n                if (prop.urlType) {\n                    if (prop.urlPath) {\n                        map[prop.urlPath] = prop.urlType;\n                    } else {\n                        map[prop.name] = prop.urlType;\n                    }\n                }\n            });\n\n            return map;\n        }\n\n        /**\n         * Convenience method to get all properties of the node\n         * @returns {Object} - The node's properties\n         */\n        getDataset() {\n            const self = this.getLatest();\n\n            let dataset = {};\n            properties.forEach((prop) => {\n                dataset[prop.name] = self[prop.privateName];\n            });\n\n            return dataset;\n        }\n\n        /**\n         * Converts JSON to a Lexical node\n         * @see https://lexical.dev/docs/concepts/serialization#lexicalnodeimportjson\n         * @extends DecoratorNode\n         * @param {Object} serializedNode - Lexical's representation of the node, in JSON format\n         */\n        static importJSON(serializedNode) {\n            const data = {};\n\n            // migrate older nodes that were saved with an earlier version of the visibility format\n            serializedNode.visibility = migrateOldVisibilityFormat(serializedNode.visibility);\n\n            properties.forEach((prop) => {\n                data[prop.name] = serializedNode[prop.name];\n            });\n\n            return new this(data);\n        }\n\n        /**\n         * Serializes a Lexical node to JSON. The JSON content is then saved to the database.\n         * @extends DecoratorNode\n         * @see https://lexical.dev/docs/concepts/serialization#lexicalnodeexportjson\n         */\n        exportJSON() {\n            const dataset = {\n                type: nodeType,\n                version: version,\n                ...properties.reduce((obj, prop) => {\n                    obj[prop.name] = this[prop.name];\n                    return obj;\n                }, {})\n            };\n            return dataset;\n        }\n\n        exportDOM(options = {}) {\n            // this.__version is used when a node has a version property which\n            // means it's set from the serialized version data at runtime\n            const nodeVersion = this.__version || version;\n\n            if (options.nodeRenderers?.[nodeType]) {\n                const render = options.nodeRenderers[nodeType];\n\n                if (typeof render === 'object') {\n                    const versionRenderer = render[nodeVersion];\n                    if (!versionRenderer) {\n                        throw new Error(`[generateDecoratorNode] ${nodeType}: options.nodeRenderers['${nodeType}'] for version ${nodeVersion} is required`);\n                    }\n                    return versionRenderer(this, options);\n                } else {\n                    return render(this, options);\n                }\n            }\n\n            if (typeof defaultRenderFn === 'object') {\n                const render = defaultRenderFn[nodeVersion];\n                if (!render) {\n                    throw new Error(`[generateDecoratorNode] ${nodeType}: \"defaultRenderFn\" for version ${nodeVersion} is required`);\n                }\n                return render(this, options);\n            }\n\n            if (!defaultRenderFn) {\n                throw new Error(`[generateDecoratorNode] ${nodeType}: \"defaultRenderFn\" is required`);\n            }\n\n            const render = defaultRenderFn;\n\n            return render(this, options);\n        }\n\n        /* c8 ignore start */\n        /**\n         * Inserts node in the DOM. Required when extending the DecoratorNode.\n         * @extends DecoratorNode\n         * @see https://lexical.dev/docs/concepts/nodes#extending-decoratornode\n         */\n        createDOM() {\n            return document.createElement('div');\n        }\n\n        /**\n         * Required when extending the DecoratorNode\n         * @extends DecoratorNode\n         * @see https://lexical.dev/docs/concepts/nodes#extending-decoratornode\n         */\n        updateDOM() {\n            return false;\n        }\n\n        /**\n         * Defines whether a node is a top-level block.\n         * @see https://lexical.dev/docs/api/classes/lexical.DecoratorNode#isinline\n         */\n        isInline() {\n            // All our cards are top-level blocks. Override if needed.\n            return false;\n        }\n        /* c8 ignore stop */\n\n        /**\n         * Defines whether a node has dynamic data that needs to be fetched from the server when rendering\n         */\n        hasDynamicData() {\n            return false;\n        }\n\n        /**\n         * Defines whether a node has an edit mode in the editor UI\n         */\n        hasEditMode() {\n            // Most of our cards have an edit mode. Override if needed.\n            return true;\n        }\n\n        /*\n        * Returns the text content of the node, used by the editor to calculate the word count\n        * This method filters out properties without `wordCount: true`\n        */\n        getTextContent() {\n            const self = this.getLatest();\n            const propertiesWithText = properties.filter(prop => !!prop.wordCount);\n\n            const text = propertiesWithText.map(\n                prop => readTextContent(self, prop.name)\n            ).filter(Boolean).join('\\n');\n\n            return text ? `${text}\\n\\n` : '';\n        }\n\n        /**\n         * Returns true/false for whether the node's visibility property\n         * is active or not. Always false if a node has no visibility property\n         * @returns {boolean}\n         */\n        getIsVisibilityActive() {\n            if (!properties.some(prop => prop.name === 'visibility')) {\n                return false;\n            }\n\n            const self = this.getLatest();\n            const visibility = self.__visibility;\n\n            return isVisibilityRestricted(visibility);\n        }\n    }\n\n    /**\n     * Generates getters and setters for each property, following ES6 syntax\n     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get\n     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set\n     *\n     * Example: for a given property 'content', the generated getter and setter will be:\n     * get content() {\n     *    const self = this.getLatest();\n     *    return self.__content;\n     * }\n     *\n     * set content(newVal) {\n     *   const writable = this.getWritable();\n     *   writable.__content = newVal;\n     * }\n     *\n     * They can be used as `node.content` (getter) and `node.content = 'new value'` (setter)\n     */\n    properties.forEach((prop) => {\n        Object.defineProperty(GeneratedDecoratorNode.prototype, prop.name, {\n            get: function () {\n                const self = this.getLatest();\n                return self[prop.privateName];\n            },\n            set: function (newVal) {\n                const writable = this.getWritable();\n                writable[prop.privateName] = newVal;\n            }\n        });\n    });\n\n    return GeneratedDecoratorNode;\n}\n","import cleanBasicHtml from '@tryghost/kg-clean-basic-html';\n\nexport function buildCleanBasicHtmlForElement(domNode) {\n    return function _cleanBasicHtml(html, additionalOptions = {}) {\n        const cleanedHtml = cleanBasicHtml(html, {\n            createDocument: (_html) => {\n                const newDoc = domNode.ownerDocument.implementation.createHTMLDocument();\n                newDoc.body.innerHTML = _html;\n                return newDoc;\n            },\n            ...additionalOptions\n        });\n        return cleanedHtml;\n    };\n}\n","import {buildCleanBasicHtmlForElement} from './build-clean-basic-html-for-element';\n\nexport function readCaptionFromElement(element, {selector = 'figcaption'} = {}) {\n    const cleanBasicHtml = buildCleanBasicHtmlForElement(element);\n\n    let caption;\n\n    const figcaptions = Array.from(element.querySelectorAll(selector));\n    if (figcaptions.length) {\n        figcaptions.forEach((figcaption) => {\n            const cleanHtml = cleanBasicHtml(figcaption.innerHTML);\n            caption = caption ? `${caption} / ${cleanHtml}` : cleanHtml;\n        });\n    }\n\n    return caption;\n}\n","export function readImageAttributesFromElement(element) {\n    const attrs = {};\n\n    if (element.src) {\n        attrs.src = element.src;\n    }\n\n    if (element.width) {\n        attrs.width = element.width;\n    } else if (element.dataset && element.dataset.width) {\n        attrs.width = parseInt(element.dataset.width, 10);\n    }\n\n    if (element.height) {\n        attrs.height = element.height;\n    } else if (element.dataset && element.dataset.height) {\n        attrs.height = parseInt(element.dataset.height, 10);\n    }\n\n    if ((!element.width && !element.height) && element.getAttribute('data-image-dimensions')) {\n        const [, width, height] = (/^(\\d*)x(\\d*)$/gi).exec(element.getAttribute('data-image-dimensions'));\n        attrs.width = parseInt(width, 10);\n        attrs.height = parseInt(height, 10);\n    }\n\n    if (element.alt) {\n        attrs.alt = element.alt;\n    }\n\n    if (element.title) {\n        attrs.title = element.title;\n    }\n\n    if (element.parentNode.tagName === 'A') {\n        const href = element.parentNode.href;\n\n        if (href !== attrs.src) {\n            attrs.href = href;\n        }\n    }\n\n    return attrs;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element.js';\nimport {readImageAttributesFromElement} from '../../utils/read-image-attributes-from-element.js';\n\nexport function parseImageNode(ImageNode) {\n    return {\n        img: () => ({\n            conversion(domNode) {\n                if (domNode.tagName === 'IMG') {\n                    const {src, width, height, alt, title, href} = readImageAttributesFromElement(domNode);\n\n                    const node = new ImageNode({alt, src, title, width, height, href});\n                    return {node};\n                }\n\n                return null;\n            },\n            priority: 1\n        }),\n        figure: (nodeElem) => {\n            const img = nodeElem.querySelector('img');\n            if (img) {\n                return {\n                    conversion(domNode) {\n                        const kgClass = domNode.className.match(/kg-width-(wide|full)/);\n                        const grafClass = domNode.className.match(/graf--layout(FillWidth|OutsetCenter)/);\n\n                        if (!img) {\n                            return null;\n                        }\n\n                        const payload = readImageAttributesFromElement(img);\n\n                        if (kgClass) {\n                            payload.cardWidth = kgClass[1];\n                        } else if (grafClass) {\n                            payload.cardWidth = grafClass[1] === 'FillWidth' ? 'full' : 'wide';\n                        }\n\n                        payload.caption = readCaptionFromElement(domNode);\n\n                        const {src, width, height, alt, title, caption, cardWidth, href} = payload;\n                        const node = new ImageNode({alt, src, title, width, height, caption, cardWidth, href});\n                        return {node};\n                    },\n                    priority: 0 // since we are generically parsing figure elements, we want this to run after others (like the gallery)\n                };\n            }\n            return null;\n        }\n    };\n}\n","export const getAvailableImageWidths = function (image, imageSizes) {\n    // get a sorted list of the available responsive widths\n    const imageWidths = Object.values(imageSizes)\n        .map(({width}) => width)\n        .sort((a, b) => a - b);\n\n    // select responsive widths that are usable based on the image width\n    const availableImageWidths = imageWidths\n        .filter(width => width <= image.width);\n\n    // add the original image size to the responsive list if it's not captured by largest responsive size\n    // - we can't know the width/height of the original `src` image because we don't know if it was resized\n    //   or not. Adding the original image to the responsive list ensures we're not showing smaller sized\n    //   images than we need to be\n    if (image.width > availableImageWidths[availableImageWidths.length - 1] && image.width < imageWidths[imageWidths.length - 1]) {\n        availableImageWidths.push(image.width);\n    }\n\n    return availableImageWidths;\n};\n","export const isLocalContentImage = function (url, siteUrl = '') {\n    const normalizedSiteUrl = siteUrl.replace(/\\/$/, '');\n    const imagePath = url.replace(normalizedSiteUrl, '');\n    return /^(\\/.*|__GHOST_URL__)\\/?content\\/images\\//.test(imagePath);\n};\n","export const isUnsplashImage = function (url) {\n    return /images\\.unsplash\\.com/.test(url);\n};\n","import {isLocalContentImage} from './is-local-content-image';\nimport {getAvailableImageWidths} from './get-available-image-widths';\nimport {isUnsplashImage} from './is-unsplash-image';\n\n// default content sizes: [600, 1000, 1600, 2400]\n\nexport const getSrcsetAttribute = function ({src, width, options}) {\n    if (!options.imageOptimization || options.imageOptimization.srcsets === false || !width || !options.imageOptimization.contentImageSizes) {\n        return;\n    }\n\n    if (isLocalContentImage(src, options.siteUrl) && options.canTransformImage && !options.canTransformImage(src)) {\n        return;\n    }\n\n    const srcsetWidths = getAvailableImageWidths({width}, options.imageOptimization.contentImageSizes);\n\n    // apply srcset if this is a relative image that matches Ghost's image url structure\n    if (isLocalContentImage(src, options.siteUrl)) {\n        const [, imagesPath, filename] = src.match(/(.*\\/content\\/images)\\/(.*)/);\n        const srcs = [];\n\n        srcsetWidths.forEach((srcsetWidth) => {\n            if (srcsetWidth === width) {\n                // use original image path if width matches exactly (avoids 302s from size->original)\n                srcs.push(`${src} ${srcsetWidth}w`);\n            } else if (srcsetWidth <= width) {\n                // avoid creating srcset sizes larger than intrinsic image width\n                srcs.push(`${imagesPath}/size/w${srcsetWidth}/${filename} ${srcsetWidth}w`);\n            }\n        });\n\n        if (srcs.length) {\n            return srcs.join(', ');\n        }\n    }\n\n    // apply srcset if this is an Unsplash image\n    if (isUnsplashImage(src)) {\n        const unsplashUrl = new URL(src);\n        const srcs = [];\n\n        srcsetWidths.forEach((srcsetWidth) => {\n            unsplashUrl.searchParams.set('w', srcsetWidth);\n            srcs.push(`${unsplashUrl.href} ${srcsetWidth}w`);\n        });\n\n        return srcs.join(', ');\n    }\n};\n\nexport const setSrcsetAttribute = function (elem, image, options) {\n    if (!elem || !['IMG', 'SOURCE'].includes(elem.tagName) || !elem.getAttribute('src') || !image) {\n        return;\n    }\n\n    const {src, width} = image;\n    const srcset = getSrcsetAttribute({src, width, options});\n\n    if (srcset) {\n        elem.setAttribute('srcset', srcset);\n    }\n};\n","export const getResizedImageDimensions = function (image, {width: desiredWidth, height: desiredHeight} = {}) {\n    const {width, height} = image;\n    const ratio = width / height;\n\n    if (desiredWidth) {\n        const resizedHeight = Math.round(desiredWidth / ratio);\n\n        return {\n            width: desiredWidth,\n            height: resizedHeight\n        };\n    }\n\n    if (desiredHeight) {\n        const resizedWidth = Math.round(desiredHeight * ratio);\n\n        return {\n            width: resizedWidth,\n            height: desiredHeight\n        };\n    }\n};\n","// If we're in a browser environment, we can use the global document object,\n// but if we're in a non-browser environment, we need to be passed a `createDocument` function\nexport function addCreateDocumentOption(options) {\n    if (!options.createDocument && options.dom) {\n        options.createDocument = function () {\n            return options.dom.window.document;\n        };\n    }\n\n    if (!options.createDocument) {\n        /* c8 ignore start */\n        let document = typeof window !== 'undefined' && window.document;\n\n        if (!document) {\n            throw new Error('Must be passed a `createDocument` function as an option when used in a non-browser environment'); // eslint-disable-line\n        }\n\n        options.createDocument = function () {\n            return document;\n        };\n        /* c8 ignore end */\n    }\n}\n","import {getAvailableImageWidths} from '../../utils/get-available-image-widths';\nimport {isLocalContentImage} from '../../utils/is-local-content-image';\nimport {setSrcsetAttribute} from '../../utils/srcset-attribute';\nimport {getResizedImageDimensions} from '../../utils/get-resized-image-dimensions';\nimport {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderImageNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n\n    if (!node.src || node.src.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    const figure = document.createElement('figure');\n\n    let figureClasses = 'kg-card kg-image-card';\n    if (node.cardWidth !== 'regular') {\n        figureClasses += ` kg-width-${node.cardWidth}`;\n    }\n    if (node.caption) {\n        figureClasses += ' kg-card-hascaption';\n    }\n\n    figure.setAttribute('class', figureClasses);\n\n    const img = document.createElement('img');\n    img.setAttribute('src', node.src);\n    img.setAttribute('class', 'kg-image');\n    img.setAttribute('alt', node.alt);\n    img.setAttribute('loading', 'lazy');\n\n    if (node.title) {\n        img.setAttribute('title', node.title);\n    }\n\n    if (node.width && node.height) {\n        img.setAttribute('width', node.width);\n        img.setAttribute('height', node.height);\n    }\n\n    // images can be resized to max width, if that's the case output\n    // the resized width/height attrs to ensure 3rd party gallery plugins\n    // aren't affected by differing sizes\n    const {canTransformImage} = options;\n    const {defaultMaxWidth} = options.imageOptimization || {};\n    if (\n        defaultMaxWidth &&\n            node.width > defaultMaxWidth &&\n            isLocalContentImage(node.src, options.siteUrl) &&\n            canTransformImage &&\n            canTransformImage(node.src)\n    ) {\n        const imageDimensions = {\n            width: node.width,\n            height: node.height\n        };\n        const {width, height} = getResizedImageDimensions(imageDimensions, {width: defaultMaxWidth});\n        img.setAttribute('width', width);\n        img.setAttribute('height', height);\n    }\n\n    if (options.target !== 'email') {\n        const imgAttributes = {\n            src: node.src,\n            width: node.width,\n            height: node.height\n        };\n        setSrcsetAttribute(img, imgAttributes, options);\n\n        if (img.getAttribute('srcset') && node.width && node.width >= 720) {\n            // standard size\n            if (!node.cardWidth || node.cardWidth === 'regular') {\n                img.setAttribute('sizes', '(min-width: 720px) 720px');\n            }\n\n            if (node.cardWidth === 'wide' && node.width >= 1200) {\n                img.setAttribute('sizes', '(min-width: 1200px) 1200px');\n            }\n        }\n    }\n\n    // Outlook is unable to properly resize images without a width/height\n    // so we add that at the expected size in emails (600px) and use a higher\n    // resolution image to keep images looking good on retina screens\n    if (options.target === 'email' && node.width && node.height) {\n        let imageDimensions = {\n            width: node.width,\n            height: node.height\n        };\n        if (node.width >= 600) {\n            imageDimensions = getResizedImageDimensions(imageDimensions, {width: 600});\n        }\n        img.setAttribute('width', imageDimensions.width);\n        img.setAttribute('height', imageDimensions.height);\n\n        if (isLocalContentImage(node.src, options.siteUrl) && options.canTransformImage?.(node.src)) {\n            // find available image size next up from 2x600 so we can use it for the \"retina\" src\n            const availableImageWidths = getAvailableImageWidths(node, options.imageOptimization.contentImageSizes);\n            const srcWidth = availableImageWidths.find(width => width >= 1200);\n\n            if (!srcWidth || srcWidth === node.width) {\n                // do nothing, width is smaller than retina or matches the original node src\n            } else {\n                const [, imagesPath, filename] = node.src.match(/(.*\\/content\\/images)\\/(.*)/);\n                img.setAttribute('src', `${imagesPath}/size/w${srcWidth}/${filename}`);\n            }\n        }\n    }\n\n    if (node.href) {\n        const a = document.createElement('a');\n        a.setAttribute('href', node.href);\n        a.appendChild(img);\n        figure.appendChild(a);\n    } else {\n        figure.appendChild(img);\n    }\n\n    if (node.caption) {\n        const caption = document.createElement('figcaption');\n        caption.innerHTML = node.caption;\n        figure.appendChild(caption);\n    }\n\n    return {element: figure};\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseImageNode} from './image-parser';\nimport {renderImageNode} from './image-renderer';\nexport class ImageNode extends generateDecoratorNode({\n    nodeType: 'image',\n    properties: [\n        {name: 'src', default: '', urlType: 'url'},\n        {name: 'caption', default: '', urlType: 'html', wordCount: true},\n        {name: 'title', default: ''},\n        {name: 'alt', default: ''},\n        {name: 'cardWidth', default: 'regular'},\n        {name: 'width', default: null},\n        {name: 'height', default: null},\n        {name: 'href', default: '', urlType: 'url'}\n    ],\n    defaultRenderFn: renderImageNode\n}) {\n    /* @override */\n    exportJSON() {\n        // checks if src is a data string\n        const {src, width, height, title, alt, caption, cardWidth, href} = this;\n        const isBlob = src && src.startsWith('data:');\n\n        const dataset = {\n            type: 'image',\n            version: 1,\n            src: isBlob ? '<base64String>' : src,\n            width,\n            height,\n            title,\n            alt,\n            caption,\n            cardWidth,\n            href\n        };\n        return dataset;\n    }\n\n    static importDOM() {\n        return parseImageNode(this);\n    }\n\n    hasEditMode() {\n        return false;\n    }\n}\n\nexport const $createImageNode = (dataset) => {\n    return new ImageNode(dataset);\n};\n\nexport function $isImageNode(node) {\n    return node instanceof ImageNode;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element';\n\nexport function parseCodeBlockNode(CodeBlockNode) {\n    return {\n        figure: (nodeElem) => {\n            const pre = nodeElem.querySelector('pre');\n            if (nodeElem.tagName === 'FIGURE' && pre) {\n                return {\n                    conversion(domNode) {        \n                        let code = pre.querySelector('code');\n                        let figcaption = domNode.querySelector('figcaption');\n    \n                        // if there's no caption the pre key should pick it up\n                        if (!code || !figcaption) {\n                            return null;\n                        }\n    \n                        let payload = {\n                            code: code.textContent,\n                            caption: readCaptionFromElement(domNode)\n                        };\n    \n                        let preClass = pre.getAttribute('class') || '';\n                        let codeClass = code.getAttribute('class') || '';\n                        let langRegex = /lang(?:uage)?-(.*?)(?:\\s|$)/i;\n                        let languageMatches = preClass.match(langRegex) || codeClass.match(langRegex);\n                        if (languageMatches) {\n                            payload.language = languageMatches[1].toLowerCase();\n                        }\n    \n                        const node = new CodeBlockNode(payload);\n                        return {node};\n                    },\n                    priority: 2 // falls back to pre if no caption\n                };\n            }\n            return null;\n        },\n        pre: () => ({\n            conversion(domNode) {\n                if (domNode.tagName === 'PRE') {\n                    let [codeElement] = domNode.children;\n\n                    if (codeElement && codeElement.tagName === 'CODE') {\n                        let payload = {code: codeElement.textContent};\n                        let preClass = domNode.getAttribute('class') || '';\n                        let codeClass = codeElement.getAttribute('class') || '';\n                        let langRegex = /lang(?:uage)?-(.*?)(?:\\s|$)/i;\n                        let languageMatches = preClass.match(langRegex) || codeClass.match(langRegex);\n                        if (languageMatches) {\n                            payload.language = languageMatches[1].toLowerCase();\n                        }\n                        const node = new CodeBlockNode(payload);\n                        return {node};\n                    }\n                }\n\n                return null;\n            },\n            priority: 1\n        })\n    };\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderCodeBlockNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    if (!node.code || node.code.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    const pre = document.createElement('pre');\n    const code = document.createElement('code');\n\n    if (node.language) {\n        code.setAttribute('class', `language-${node.language}`);\n    }\n\n    code.appendChild(document.createTextNode(node.code));\n    pre.appendChild(code);\n\n    if (node.caption) {\n        let figure = document.createElement('figure');\n        figure.setAttribute('class', 'kg-card kg-code-card');\n        figure.appendChild(pre);\n\n        let figcaption = document.createElement('figcaption');\n        figcaption.innerHTML = node.caption;\n        figure.appendChild(figcaption);\n\n        return {element: figure};\n    } else {\n        return {element: pre};\n    }\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseCodeBlockNode} from './codeblock-parser';\nimport {renderCodeBlockNode} from './codeblock-renderer';\n\nexport class CodeBlockNode extends generateDecoratorNode({\n    nodeType: 'codeblock',\n    properties: [\n        {name: 'code', default: '', wordCount: true},\n        {name: 'language', default: ''},\n        {name: 'caption', default: '', urlType: 'html', wordCount: true}\n    ],\n    defaultRenderFn: renderCodeBlockNode\n}) {\n    static importDOM() {\n        return parseCodeBlockNode(this);\n    }\n\n    isEmpty() {\n        return !this.__code;\n    }\n}\n\nexport function $createCodeBlockNode(dataset) {\n    return new CodeBlockNode(dataset);\n}\n\nexport function $isCodeBlockNode(node) {\n    return node instanceof CodeBlockNode;\n}\n","import markdownHtmlRenderer from '@tryghost/kg-markdown-html-renderer';\nimport {addCreateDocumentOption} from '../../utils/add-create-document-option';\n\nexport function renderMarkdownNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const html = markdownHtmlRenderer.render(node.markdown || '', options);\n\n    const element = document.createElement('div');\n    element.innerHTML = html;\n\n    // `type: 'inner'` will render only the innerHTML of the element\n    // @see @tryghost/kg-lexical-html-renderer package\n    return {element, type: 'inner'};\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderMarkdownNode} from './markdown-renderer';\n\nexport class MarkdownNode extends generateDecoratorNode({\n    nodeType: 'markdown',\n    properties: [\n        {name: 'markdown', default: '', urlType: 'markdown', wordCount: true}\n    ],\n    defaultRenderFn: renderMarkdownNode\n}) {\n    isEmpty() {\n        return !this.__markdown;\n    }\n}\n\nexport function $createMarkdownNode(dataset) {\n    return new MarkdownNode(dataset);\n}\n\nexport function $isMarkdownNode(node) {\n    return node instanceof MarkdownNode;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element';\n\nexport function parseVideoNode(VideoNode) {\n    return {\n        figure: (nodeElem) => {\n            const isKgVideoCard = nodeElem.classList?.contains('kg-video-card');\n            if (nodeElem.tagName === 'FIGURE' && isKgVideoCard) {\n                return {\n                    conversion(domNode) {\n                        const videoNode = domNode.querySelector('.kg-video-container video');\n                        const durationNode = domNode.querySelector('.kg-video-duration');\n                        const videoSrc = videoNode && videoNode.src;\n                        const videoWidth = videoNode && videoNode.width;\n                        const videoHeight = videoNode && videoNode.height;\n                        const durationText = durationNode && durationNode.innerHTML.trim();\n                        const captionText = readCaptionFromElement(domNode);\n\n                        if (!videoSrc) {\n                            return null;\n                        }\n\n                        const payload = {\n                            src: videoSrc,\n                            loop: !!videoNode.loop,\n                            cardWidth: getCardWidth(videoNode)\n                        };\n\n                        if (durationText) {\n                            const [minutes, seconds] = durationText.split(':');\n                            try {\n                                payload.duration = parseInt(minutes) * 60 + parseInt(seconds);\n                            } catch (e) {\n                                // ignore duration\n                            }\n                        }\n\n                        if (domNode.dataset.kgThumbnail) {\n                            payload.thumbnailSrc = domNode.dataset.kgThumbnail;\n                        }\n\n                        if (domNode.dataset.kgCustomThumbnail) {\n                            payload.customThumbnailSrc = domNode.dataset.kgCustomThumbnail;\n                        }\n\n                        if (captionText) {\n                            payload.caption = captionText;\n                        }\n\n                        if (videoWidth) {\n                            payload.width = videoWidth;\n                        }\n\n                        if (videoHeight) {\n                            payload.height = videoHeight;\n                        }\n\n                        const node = new VideoNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n\nfunction getCardWidth(domNode) {\n    if (domNode.classList.contains('kg-width-full')) {\n        return 'full';\n    } else if (domNode.classList.contains('kg-width-wide')) {\n        return 'wide';\n    } else {\n        return 'regular';\n    }\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderVideoNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n\n    if (!node.src || node.src.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    const cardClasses = getCardClasses(node).join(' ');\n\n    const htmlString = options.target === 'email'\n        ? emailCardTemplate({node, options, cardClasses})\n        : cardTemplate({node, cardClasses});\n\n    const element = document.createElement('div');\n    element.innerHTML = htmlString.trim();\n\n    return {element: element.firstElementChild};\n}\n\nexport function cardTemplate({node, cardClasses}) {\n    const width = node.width;\n    const height = node.height;\n    const posterSpacerSrc = `https://img.spacergif.org/v1/${width}x${height}/0a/spacer.png`;\n    const autoplayAttr = node.loop ? 'loop autoplay muted' : '';\n    const thumbnailSrc = node.customThumbnailSrc || node.thumbnailSrc;\n    const hideControlsClass = node.loop ? ' kg-video-hide' : '';\n\n    return (\n        `\n        <figure class=\"${cardClasses}\" data-kg-thumbnail=${node.thumbnailSrc} data-kg-custom-thumbnail=${node.customThumbnailSrc}>\n            <div class=\"kg-video-container\">\n                <video\n                    src=\"${node.src}\"\n                    poster=\"${posterSpacerSrc}\"\n                    width=\"${width}\"\n                    height=\"${height}\"\n                    ${autoplayAttr}\n                    playsinline\n                    preload=\"metadata\"\n                    style=\"background: transparent url('${thumbnailSrc}') 50% 50% / cover no-repeat;\"\n                ></video>\n                <div class=\"kg-video-overlay\">\n                    <button class=\"kg-video-large-play-icon\" aria-label=\"Play video\">\n                        <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                            <path d=\"M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z\"/>\n                        </svg>\n                    </button>\n                </div>\n                <div class=\"kg-video-player-container${hideControlsClass}\">\n                    <div class=\"kg-video-player\">\n                        <button class=\"kg-video-play-icon\" aria-label=\"Play video\">\n                            <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                                <path d=\"M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z\"></path>\n                            </svg>\n                        </button>\n                        <button class=\"kg-video-pause-icon kg-video-hide\" aria-label=\"Pause video\">\n                            <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                                <rect x=\"3\" y=\"1\" width=\"7\" height=\"22\" rx=\"1.5\" ry=\"1.5\"></rect>\n                                <rect x=\"14\" y=\"1\" width=\"7\" height=\"22\" rx=\"1.5\" ry=\"1.5\"></rect>\n                            </svg>\n                        </button>\n                        <span class=\"kg-video-current-time\">0:00</span>\n                        <div class=\"kg-video-time\">\n                            /<span class=\"kg-video-duration\">${node.formattedDuration}</span>\n                        </div>\n                        <input type=\"range\" class=\"kg-video-seek-slider\" max=\"100\" value=\"0\">\n                        <button class=\"kg-video-playback-rate\" aria-label=\"Adjust playback speed\">1&#215;</button>\n                        <button class=\"kg-video-unmute-icon\" aria-label=\"Unmute\">\n                            <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                                <path d=\"M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z\"></path>\n                            </svg>\n                        </button>\n                        <button class=\"kg-video-mute-icon kg-video-hide\" aria-label=\"Mute\">\n                            <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                                <path d=\"M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z\"></path>\n                            </svg>\n                        </button>\n                        <input type=\"range\" class=\"kg-video-volume-slider\" max=\"100\" value=\"100\"/>\n                    </div>\n                </div>\n            </div>\n            ${node.caption ? `<figcaption>${node.caption}</figcaption>` : ''}\n        </figure>\n    `\n    );\n}\n\nexport function emailCardTemplate({node, options, cardClasses}) {\n    const thumbnailSrc = node.customThumbnailSrc || node.thumbnailSrc;\n    const emailTemplateMaxWidth = 600;\n    const aspectRatio = node.width / node.height;\n    const emailSpacerWidth = Math.round(emailTemplateMaxWidth / 4);\n    const emailSpacerHeight = Math.round(emailTemplateMaxWidth / aspectRatio);\n    const posterSpacerSrc = `https://img.spacergif.org/v1/${emailSpacerWidth}x${emailSpacerHeight}/0a/spacer.png`;\n    const outlookCircleLeft = Math.round((emailTemplateMaxWidth / 2) - 39);\n    const outlookCircleTop = Math.round((emailSpacerHeight / 2) - 39);\n    const outlookPlayLeft = Math.round((emailTemplateMaxWidth / 2) - 11);\n    const outlookPlayTop = Math.round((emailSpacerHeight / 2) - 17);\n\n    return (\n        `\n         <figure class=\"${cardClasses}\">\n            <!--[if !mso !vml]-->\n            <a class=\"kg-video-preview\" href=\"${options.postUrl}\" aria-label=\"Play video\" style=\"mso-hide: all\">\n                <table\n                    cellpadding=\"0\"\n                    cellspacing=\"0\"\n                    border=\"0\"\n                    width=\"100%\"\n                    background=\"${thumbnailSrc}\"\n                    role=\"presentation\"\n                    style=\"background: url('${thumbnailSrc}') left top / cover; mso-hide: all\"\n                >\n                    <tr style=\"mso-hide: all\">\n                        <td width=\"25%\" style=\"visibility: hidden; mso-hide: all\">\n                            <img src=\"${posterSpacerSrc}\" alt=\"\" width=\"100%\" border=\"0\" style=\"display:block; height: auto; opacity: 0; visibility: hidden; mso-hide: all;\">\n                        </td>\n                        <td width=\"50%\" align=\"center\" valign=\"middle\" style=\"vertical-align: middle; mso-hide: all;\">\n                            <div class=\"kg-video-play-button\" style=\"mso-hide: all\"><div style=\"mso-hide: all\"></div></div>\n                        </td>\n                        <td width=\"25%\" style=\"mso-hide: all\">&nbsp;</td>\n                    </tr>\n                </table>\n            </a>\n            <!--[endif]-->\n\n            <!--[if vml]>\n            <v:group xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" coordsize=\"${emailTemplateMaxWidth},${emailSpacerHeight}\" coordorigin=\"0,0\" href=\"${options.postUrl}\" style=\"width:${emailTemplateMaxWidth}px;height:${emailSpacerHeight}px;\">\n                <v:rect fill=\"t\" stroked=\"f\" style=\"position:absolute;width:${emailTemplateMaxWidth};height:${emailSpacerHeight};\"><v:fill src=\"${thumbnailSrc}\" type=\"frame\"/></v:rect>\n                <v:oval fill=\"t\" strokecolor=\"white\" strokeweight=\"4px\" style=\"position:absolute;left:${outlookCircleLeft};top:${outlookCircleTop};width:78;height:78\"><v:fill color=\"black\" opacity=\"30%\" /></v:oval>\n                <v:shape coordsize=\"24,32\" path=\"m,l,32,24,16,xe\" fillcolor=\"white\" stroked=\"f\" style=\"position:absolute;left:${outlookPlayLeft};top:${outlookPlayTop};width:30;height:34;\" />\n            </v:group>\n            <![endif]-->\n\n            ${node.caption ? `<figcaption>${node.caption}</figcaption>` : ''}\n        </figure>\n        `\n    );\n}\n\nexport function getCardClasses(node) {\n    let cardClasses = ['kg-card kg-video-card'];\n\n    if (node.cardWidth) {\n        cardClasses.push(`kg-width-${node.cardWidth}`);\n    }\n    if (node.caption) {\n        cardClasses.push(`kg-card-hascaption`);\n    }\n\n    return cardClasses;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseVideoNode} from './video-parser';\nimport {renderVideoNode} from './video-renderer';\nexport class VideoNode extends generateDecoratorNode({\n    nodeType: 'video',\n    properties: [\n        {name: 'src', default: '', urlType: 'url'},\n        {name: 'caption', default: '', urlType: 'html', wordCount: true},\n        {name: 'fileName', default: ''},\n        {name: 'mimeType', default: ''},\n        {name: 'width', default: null},\n        {name: 'height', default: null},\n        {name: 'duration', default: 0},\n        {name: 'thumbnailSrc', default: '', urlType: 'url'},\n        {name: 'customThumbnailSrc', default: '', urlType: 'url'},\n        {name: 'thumbnailWidth', default: null},\n        {name: 'thumbnailHeight', default: null},\n        {name: 'cardWidth', default: 'regular'},\n        {name: 'loop', default: false}\n    ],\n    defaultRenderFn: renderVideoNode\n}) {\n    /* override */\n    exportJSON() {\n        const {src, caption, fileName, mimeType, width, height, duration, thumbnailSrc, customThumbnailSrc, thumbnailWidth, thumbnailHeight, cardWidth, loop} = this;\n        // checks if src is a data string\n        const isBlob = src && src.startsWith('data:');\n\n        const dataset = {\n            type: 'video',\n            version: 1,\n            src: isBlob ? '<base64String>' : src,\n            caption,\n            fileName,\n            mimeType,\n            width,\n            height,\n            duration,\n            thumbnailSrc,\n            customThumbnailSrc,\n            thumbnailWidth,\n            thumbnailHeight,\n            cardWidth,\n            loop\n        };\n        return dataset;\n    }\n\n    static importDOM() {\n        return parseVideoNode(this);\n    }\n\n    get formattedDuration() {\n        const minutes = Math.floor(this.duration / 60);\n        const seconds = Math.floor(this.duration - (minutes * 60));\n        const paddedSeconds = String(seconds).padStart(2, '0');\n        const formattedDuration = `${minutes}:${paddedSeconds}`;\n        return formattedDuration;\n    }\n}\n\nexport const $createVideoNode = (dataset) => {\n    return new VideoNode(dataset);\n};\n\nexport function $isVideoNode(node) {\n    return node instanceof VideoNode;\n}\n","export function parseAudioNode(AudioNode) {\n    return {\n        div: (nodeElem) => {\n            const isKgAudioCard = nodeElem.classList?.contains('kg-audio-card');\n            if (nodeElem.tagName === 'DIV' && isKgAudioCard) {\n                return {\n                    conversion(domNode) {\n                        const titleNode = domNode?.querySelector('.kg-audio-title');\n                        const audioNode = domNode?.querySelector('.kg-audio-player-container audio');\n                        const durationNode = domNode?.querySelector('.kg-audio-duration');\n                        const thumbnailNode = domNode?.querySelector('.kg-audio-thumbnail');\n                        const title = titleNode && titleNode.innerHTML.trim();\n                        const audioSrc = audioNode && audioNode.src;\n                        const thumbnailSrc = thumbnailNode && thumbnailNode.src;\n                        const durationText = durationNode && durationNode.innerHTML.trim();\n                        const payload = {\n                            src: audioSrc,\n                            title: title\n                        };\n                        if (thumbnailSrc) {\n                            payload.thumbnailSrc = thumbnailSrc;\n                        }\n\n                        if (durationText) {\n                            const [minutes, seconds = 0] = durationText.split(':');\n                            try {\n                                payload.duration = parseInt(minutes) * 60 + parseInt(seconds);\n                            } catch (e) {\n                                // ignore duration\n                            }\n                        }\n\n                        const node = new AudioNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderAudioNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    if (!node.src || node.src.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    const thumbnailCls = getThumbnailCls(node);\n    const emptyThumbnailCls = getEmptyThumbnailCls(node);\n\n    if (options.target === 'email') {\n        return emailTemplate(node, document, options, thumbnailCls, emptyThumbnailCls);\n    } else {\n        return frontendTemplate(node, document, thumbnailCls, emptyThumbnailCls);\n    }\n}\n\nfunction frontendTemplate(node, document, thumbnailCls, emptyThumbnailCls) {\n    const element = document.createElement('div');\n    element.setAttribute('class', 'kg-card kg-audio-card');\n    const img = document.createElement('img');\n    img.src = node.thumbnailSrc;\n    img.alt = 'audio-thumbnail';\n    img.setAttribute('class', thumbnailCls);\n    element.appendChild(img);\n\n    const emptyThumbnailDiv = document.createElement('div');\n    emptyThumbnailDiv.setAttribute('class', emptyThumbnailCls);\n    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    svg.setAttribute('width', '24');\n    svg.setAttribute('height', '24');\n    svg.setAttribute('fill', 'none');\n    const path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    path1.setAttribute('fill-rule', 'evenodd');\n    path1.setAttribute('clip-rule', 'evenodd');\n    path1.setAttribute('d', 'M7.5 15.33a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-2.25.75a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0ZM15 13.83a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-2.25.75a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0Z');\n    svg.appendChild(path1);\n    const path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    path2.setAttribute('fill-rule', 'evenodd');\n    path2.setAttribute('clip-rule', 'evenodd');\n    path2.setAttribute('d', 'M14.486 6.81A2.25 2.25 0 0 1 17.25 9v5.579a.75.75 0 0 1-1.5 0v-5.58a.75.75 0 0 0-.932-.727.755.755 0 0 1-.059.013l-4.465.744a.75.75 0 0 0-.544.72v6.33a.75.75 0 0 1-1.5 0v-6.33a2.25 2.25 0 0 1 1.763-2.194l4.473-.746Z');\n    svg.appendChild(path2);\n    const path3 = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    path3.setAttribute('fill-rule', 'evenodd');\n    path3.setAttribute('clip-rule', 'evenodd');\n    path3.setAttribute('d', 'M3 1.5a.75.75 0 0 0-.75.75v19.5a.75.75 0 0 0 .75.75h18a.75.75 0 0 0 .75-.75V5.133a.75.75 0 0 0-.225-.535l-.002-.002-3-2.883A.75.75 0 0 0 18 1.5H3ZM1.409.659A2.25 2.25 0 0 1 3 0h15a2.25 2.25 0 0 1 1.568.637l.003.002 3 2.883a2.25 2.25 0 0 1 .679 1.61V21.75A2.25 2.25 0 0 1 21 24H3a2.25 2.25 0 0 1-2.25-2.25V2.25c0-.597.237-1.169.659-1.591Z');\n    svg.appendChild(path3);\n    emptyThumbnailDiv.appendChild(svg);\n\n    element.appendChild(emptyThumbnailDiv);\n\n    const audioPlayerContainer = document.createElement('div');\n    audioPlayerContainer.setAttribute('class', 'kg-audio-player-container');\n\n    const audioElement = document.createElement('audio');\n    audioElement.setAttribute('src', node.src);\n    audioElement.setAttribute('preload', 'metadata');\n    audioPlayerContainer.appendChild(audioElement);\n\n    const audioTitle = document.createElement('div');\n    audioTitle.setAttribute('class', 'kg-audio-title');\n    audioTitle.textContent = node.title;\n    audioPlayerContainer.appendChild(audioTitle);\n\n    const audioPlayer = document.createElement('div');\n    audioPlayer.setAttribute('class', 'kg-audio-player');\n    const audioPlayIcon = document.createElement('button');\n    audioPlayIcon.setAttribute('class', 'kg-audio-play-icon');\n    audioPlayIcon.setAttribute('aria-label', 'Play audio');\n    const audioPlayIconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    audioPlayIconSvg.setAttribute('viewBox', '0 0 24 24');\n    const playPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    playPath.setAttribute('d', 'M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z');\n    audioPlayIconSvg.appendChild(playPath);\n    audioPlayIcon.appendChild(audioPlayIconSvg);\n    audioPlayer.appendChild(audioPlayIcon);\n\n    const audioPauseIcon = document.createElement('button');\n    audioPauseIcon.setAttribute('class', 'kg-audio-pause-icon kg-audio-hide');\n    audioPauseIcon.setAttribute('aria-label', 'Pause audio');\n    const audioPauseIconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    audioPauseIconSvg.setAttribute('viewBox', '0 0 24 24');\n    const rectSvg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n    rectSvg.setAttribute('x', '3');\n    rectSvg.setAttribute('y', '1');\n    rectSvg.setAttribute('width', '7');\n    rectSvg.setAttribute('height', '22');\n    rectSvg.setAttribute('rx', '1.5');\n    rectSvg.setAttribute('ry', '1.5');\n    audioPauseIconSvg.appendChild(rectSvg);\n    const rectSvg2 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n    rectSvg2.setAttribute('x', '14');\n    rectSvg2.setAttribute('y', '1');\n    rectSvg2.setAttribute('width', '7');\n    rectSvg2.setAttribute('height', '22');\n    rectSvg2.setAttribute('rx', '1.5');\n    rectSvg2.setAttribute('ry', '1.5');\n    audioPauseIconSvg.appendChild(rectSvg2);\n    audioPauseIcon.appendChild(audioPauseIconSvg);\n    audioPlayer.appendChild(audioPauseIcon);\n\n    const audioDuration = document.createElement('span');\n    audioDuration.setAttribute('class', 'kg-audio-current-time');\n    audioDuration.textContent = '0:00';\n    audioPlayer.appendChild(audioDuration);\n\n    const audioDurationTotal = document.createElement('div');\n    audioDurationTotal.setAttribute('class', 'kg-audio-time');\n    audioDurationTotal.textContent = '/';\n    const audioDUrationNode = document.createElement('span');\n    audioDUrationNode.setAttribute('class', 'kg-audio-duration');\n    audioDUrationNode.textContent = node.duration;\n    audioDurationTotal.appendChild(audioDUrationNode);\n    audioPlayer.appendChild(audioDurationTotal);\n\n    const audioSlider = document.createElement('input');\n    audioSlider.setAttribute('type', 'range');\n    audioSlider.setAttribute('class', 'kg-audio-seek-slider');\n    audioSlider.setAttribute('max', '100');\n    audioSlider.setAttribute('value', '0');\n    audioPlayer.appendChild(audioSlider);\n\n    const playbackRate = document.createElement('button');\n    playbackRate.setAttribute('class', 'kg-audio-playback-rate');\n    playbackRate.setAttribute('aria-label', 'Adjust playback speed');\n    playbackRate.innerHTML = '1&#215;'; // innerHTML not textContent because we need the HTML entity\n    audioPlayer.appendChild(playbackRate);\n\n    const unmuteIcon = document.createElement('button');\n    unmuteIcon.setAttribute('class', 'kg-audio-unmute-icon');\n    unmuteIcon.setAttribute('aria-label', 'Unmute');\n    const unmuteIconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    unmuteIconSvg.setAttribute('viewBox', '0 0 24 24');\n    const unmutePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    unmutePath.setAttribute('d', 'M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z');\n    unmuteIconSvg.appendChild(unmutePath);\n    unmuteIcon.appendChild(unmuteIconSvg);\n    audioPlayer.appendChild(unmuteIcon);\n\n    const muteIcon = document.createElement('button');\n    muteIcon.setAttribute('class', 'kg-audio-mute-icon kg-audio-hide');\n    muteIcon.setAttribute('aria-label', 'Mute');\n\n    const muteIconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    muteIconSvg.setAttribute('viewBox', '0 0 24 24');\n    const mutePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n    mutePath.setAttribute('d', 'M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z');\n    muteIconSvg.appendChild(mutePath);\n    muteIcon.appendChild(muteIconSvg);\n    audioPlayer.appendChild(muteIcon);\n\n    const volumeSlider = document.createElement('input');\n    volumeSlider.setAttribute('type', 'range');\n    volumeSlider.setAttribute('class', 'kg-audio-volume-slider');\n    volumeSlider.setAttribute('max', '100');\n    volumeSlider.setAttribute('value', '100');\n    audioPlayer.appendChild(volumeSlider);\n\n    audioPlayerContainer.appendChild(audioPlayer);\n    element.appendChild(audioPlayerContainer);\n\n    return {element};\n}\n\nfunction emailTemplate(node, document, options, thumbnailCls, emptyThumbnailCls) {\n    const html = (`\n        <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"kg-audio-card\">\n                <tr>\n                    <td>\n                        <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                            <tr>\n                                <td width=\"60\">\n                                    <a href=\"${options.postUrl}\" style=\"display: block; width: 60px; height: 60px; padding-top: 4px; padding-right: 16px; padding-bottom: 4px; padding-left: 4px; border-radius: 2px;\">\n                                        ${node.thumbnailSrc ? `\n                                        <img src=\"${node.thumbnailSrc}\" class=\"${thumbnailCls}\" style=\"width: 60px; height: 60px; object-fit: cover; border: 0; border-radius: 2px;\">\n                                        ` : `\n                                        <img src=\"https://static.ghost.org/v4.0.0/images/audio-file-icon.png\" class=\"${emptyThumbnailCls}\" style=\"width: 24px; height: 24px; padding: 18px; border-radius: 2px;\">\n                                        `}\n                                    </a>\n                                </td>\n                                <td style=\"position: relative; vertical-align: center;\" valign=\"middle\">\n                                    <a href=\"${options.postUrl}\" style=\"position: absolute; display: block; top: 0; right: 0; bottom: 0; left: 0;\"></a>\n                                    <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                                        <tr>\n                                            <td>\n                                                <a href=\"${options.postUrl}\" class=\"kg-audio-title\">${node.title}</a>\n                                            </td>\n                                        </tr>\n                                        <tr>\n                                            <td>\n                                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                                                    <tr>\n                                                        <td width=\"24\" style=\"vertical-align: middle;\" valign=\"middle\">\n                                                            <a href=\"${options.postUrl}\" class=\"kg-audio-play-button\"></a>\n                                                        </td>\n                                                        <td style=\"vertical-align: middle;\" valign=\"middle\">\n                                                            <a href=\"${options.postUrl}\" class=\"kg-audio-duration\">${getFormattedDuration(node.duration)}<span class=\"kg-audio-link\"> • Click to play audio</span></a>\n                                                        </td>\n                                                    </tr>\n                                                </table>\n                                            </td>\n                                        </tr>\n                                    </table>\n                                </td>\n                            </tr>\n                        </table>\n                    </td>\n                </tr>\n            </table>\n            `);\n\n    const container = document.createElement('div');\n    container.innerHTML = html.trim();\n\n    return {element: container.firstElementChild};\n}\n\nfunction getThumbnailCls(node) {\n    let thumbnailCls = 'kg-audio-thumbnail';\n\n    if (!node.thumbnailSrc) {\n        thumbnailCls += ' kg-audio-hide';\n    }\n\n    return thumbnailCls;\n}\n\nfunction getEmptyThumbnailCls(node) {\n    let emptyThumbnailCls = 'kg-audio-thumbnail placeholder';\n\n    if (node.thumbnailSrc) {\n        emptyThumbnailCls += ' kg-audio-hide';\n    }\n\n    return emptyThumbnailCls;\n}\n\nfunction getFormattedDuration(duration = 200) {\n    const minutes = Math.floor(duration / 60);\n    const seconds = Math.floor(duration - (minutes * 60));\n    const paddedSeconds = String(seconds).padStart(2, '0');\n    const formattedDuration = `${minutes}:${paddedSeconds}`;\n    return formattedDuration;\n}","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseAudioNode} from './audio-parser';\nimport {renderAudioNode} from './audio-renderer';\n\nexport class AudioNode extends generateDecoratorNode({\n    nodeType: 'audio',\n    properties: [\n        {name: 'duration', default: 0},\n        {name: 'mimeType', default: ''},\n        {name: 'src', default: '', urlType: 'url'},\n        {name: 'title', default: ''},\n        {name: 'thumbnailSrc', default: ''}\n    ],\n    defaultRenderFn: renderAudioNode\n}) {\n    static importDOM() {\n        return parseAudioNode(this);\n    }\n}\n\nexport const $createAudioNode = (dataset) => {\n    return new AudioNode(dataset);\n};\n\nexport function $isAudioNode(node) {\n    return node instanceof AudioNode;\n}\n","export function cleanDOM(node, allowedTags) {\n    for (let i = 0; i < node.childNodes.length; i++) {\n        let child = node.childNodes[i];\n        if (child.nodeType === 1 && !allowedTags.includes(child.tagName)) {\n            while (child.firstChild) {\n                node.insertBefore(child.firstChild, child);\n            }\n            node.removeChild(child);\n            i -= 1;\n        } else if (child.nodeType === 1) {\n            cleanDOM(child, allowedTags);\n        }\n    }\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {cleanDOM} from '../../utils/clean-dom';\n\nexport function renderCalloutNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n    const element = document.createElement('div');\n\n    // backgroundColor can end up with `rgba(0, 0, 0, 0)` from old mobiledoc copy/paste\n    // that is invalid when used in a class name so fall back to `white` when we don't have\n    // something that looks like a valid class\n    if (!node.backgroundColor || !node.backgroundColor.match(/^[a-zA-Z\\d-]+$/)) {\n        node.backgroundColor = 'white';\n    }\n\n    element.classList.add('kg-card', 'kg-callout-card', `kg-callout-card-${node.backgroundColor}`);\n\n    if (node.calloutEmoji) {\n        const emojiElement = document.createElement('div');\n        emojiElement.classList.add('kg-callout-emoji');\n        emojiElement.textContent = node.calloutEmoji;\n        element.appendChild(emojiElement);\n    }\n\n    const textElement = document.createElement('div');\n    textElement.classList.add('kg-callout-text');\n\n    const temporaryContainer = document.createElement('div');\n    temporaryContainer.innerHTML = node.calloutText;\n\n    const allowedTags = ['A', 'STRONG', 'EM', 'B', 'I', 'BR', 'CODE', 'MARK', 'S', 'DEL', 'U', 'SUP', 'SUB'];\n    cleanDOM(temporaryContainer, allowedTags);\n\n    textElement.innerHTML = temporaryContainer.innerHTML;\n    element.appendChild(textElement);\n\n    return {element};\n}\n","const getColorTag = (nodeElem) => {\n    const colorClass = nodeElem.classList?.value?.match(/kg-callout-card-(\\w+)/);\n    return colorClass && colorClass[1];\n};\n\nexport function parseCalloutNode(CalloutNode) {\n    return {\n        div: (nodeElem) => {\n            const isKgCalloutCard = nodeElem.classList?.contains('kg-callout-card');\n            if (nodeElem.tagName === 'DIV' && isKgCalloutCard) {\n                return {\n                    conversion(domNode) {\n                        const textNode = domNode?.querySelector('.kg-callout-text');\n                        const emojiNode = domNode?.querySelector('.kg-callout-emoji');\n                        const color = getColorTag(domNode);\n\n                        const payload = {\n                            calloutText: textNode && textNode.innerHTML.trim() || '',\n                            calloutEmoji: emojiNode && emojiNode.innerHTML.trim() || '',\n                            backgroundColor: color\n                        };\n\n                        const node = new CalloutNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderCalloutNode} from './callout-renderer';\nimport {parseCalloutNode} from './callout-parser';\n\nexport class CalloutNode extends generateDecoratorNode({\n    nodeType: 'callout',\n    properties: [\n        {name: 'calloutText', default: '', wordCount: true},\n        {name: 'calloutEmoji', default: '💡'},\n        {name: 'backgroundColor', default: 'blue'}\n    ],\n    defaultRenderFn: renderCalloutNode\n}) {\n    /* override */\n    constructor({calloutText, calloutEmoji, backgroundColor} = {}, key) {\n        super(key);\n        this.__calloutText = calloutText || '';\n        this.__calloutEmoji = calloutEmoji !== undefined ? calloutEmoji : '💡';\n        this.__backgroundColor = backgroundColor || 'blue';\n    }\n\n    static importDOM() {\n        return parseCalloutNode(this);\n    }\n}\n\nexport function $isCalloutNode(node) {\n    return node instanceof CalloutNode;\n}\n\nexport const $createCalloutNode = (dataset) => {\n    return new CalloutNode(dataset);\n};\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderWithVisibility} from '../../utils/visibility';\nimport {getResizedImageDimensions} from '../../utils/get-resized-image-dimensions';\nimport {isLocalContentImage} from '../../utils/is-local-content-image';\nimport {buildCleanBasicHtmlForElement} from '../../utils/build-clean-basic-html-for-element';\n\nconst showButton = dataset => dataset.showButton && dataset.buttonUrl && dataset.buttonText;\n\nconst wrapWithLink = (dataset, content) => {\n    if (!showButton(dataset)) {\n        return content;\n    }\n\n    return `<a href=\"${dataset.buttonUrl}\">${content}</a>`;\n};\n\nfunction ctaCardTemplate(dataset) {\n    // Add validation for buttonColor\n    if (!dataset.buttonColor || !dataset.buttonColor.match(/^[a-zA-Z\\d-]+|#([a-fA-F\\d]{3}|[a-fA-F\\d]{6})$/)) {\n        dataset.buttonColor = 'accent';\n    }\n    const buttonAccent = dataset.buttonColor === 'accent' ? 'kg-style-accent' : '';\n    const buttonStyle = dataset.buttonColor === 'accent'\n        ? `style=\"color: ${dataset.buttonTextColor};\"`\n        : `style=\"background-color: ${dataset.buttonColor}; color: ${dataset.buttonTextColor};\"`;\n\n    return `\n        <div class=\"kg-card kg-cta-card kg-cta-bg-${dataset.backgroundColor} kg-cta-${dataset.layout} ${dataset.showDividers ? '' : 'kg-cta-no-dividers'} ${dataset.imageUrl ? 'kg-cta-has-img' : ''} ${dataset.linkColor === 'accent' ? 'kg-cta-link-accent' : ''} ${dataset.alignment === 'center' ? 'kg-cta-centered' : ''}\" data-layout=\"${dataset.layout}\">\n            ${dataset.hasSponsorLabel ? `\n                <div class=\"kg-cta-sponsor-label-wrapper\">\n                    <div class=\"kg-cta-sponsor-label\">\n                        ${dataset.sponsorLabel}\n                    </div>\n                </div>\n            ` : ''}\n            <div class=\"kg-cta-content\">\n                ${dataset.imageUrl ? `\n                    <div class=\"kg-cta-image-container\">\n                        ${wrapWithLink(dataset, `<img src=\"${dataset.imageUrl}\" alt=\"CTA Image\" ${dataset?.imageWidth && dataset.imageHeight ? `data-image-dimensions=\"${dataset.imageWidth}x${dataset.imageHeight}\"` : '' }>`)}\n                    </div>\n                ` : ''}\n                ${dataset.textValue || dataset.showButton ? `\n                    <div class=\"kg-cta-content-inner\">\n                    ${dataset.textValue ? `\n                        <div class=\"kg-cta-text\">\n                            ${dataset.textValue}\n                        </div>\n                    ` : ''}\n                    ${showButton(dataset) ? `\n                        <a href=\"${dataset.buttonUrl}\" class=\"kg-cta-button ${buttonAccent}\" ${buttonStyle}>\n                            ${dataset.buttonText}\n                        </a>\n                        ` : ''}\n                    </div>\n                ` : ''}\n            </div>\n        </div>\n    `;\n}\n\nfunction emailCTATemplate(dataset, options = {}) {\n    // accent button color backgrounds are set in main template styles,\n    // for other button colors we need to set the background color explicitly\n    let buttonStyle = dataset.buttonColor === 'accent'\n        ? `color: ${dataset.buttonTextColor};`\n        : `background-color: ${dataset.buttonColor}; color: ${dataset.buttonTextColor};`;\n    // by default we duplicate style across the <td> and <a> tags, but\n    // we separate the variables to allow <a> tag style overrides for outline buttons\n    let buttonLinkStyle = buttonStyle;\n\n    if (\n        (options?.feature?.emailCustomization || options?.feature?.emailCustomizationAlpha) &&\n        options?.design?.buttonStyle === 'outline' &&\n        // accent buttons are fully handled by main template CSS\n        dataset.buttonColor !== 'accent'\n    ) {\n        buttonStyle = `\n            border: 1px solid ${dataset.buttonColor};\n            background-color: transparent;\n            color: ${dataset.buttonColor};\n        `;\n        buttonLinkStyle = `\n            background-color: transparent;\n            color: ${dataset.buttonColor};\n        `;\n    }\n\n    let imageDimensions;\n\n    if (dataset.imageUrl && dataset.imageWidth && dataset.imageHeight) {\n        imageDimensions = {\n            width: dataset.imageWidth,\n            height: dataset.imageHeight\n        };\n\n        if (dataset.imageWidth >= 560) {\n            imageDimensions = getResizedImageDimensions(imageDimensions, {width: 560});\n        }\n    }\n\n    if (dataset.layout === 'minimal' && dataset.imageUrl) {\n        if (isLocalContentImage(dataset.imageUrl, options.siteUrl) && options.canTransformImage?.(dataset.imageUrl)) {\n            const [, imagesPath, filename] = dataset.imageUrl.match(/(.*\\/content\\/images)\\/(.*)/);\n            const iconSize = options?.imageOptimization?.internalImageSizes?.['email-cta-minimal-image'] || {width: 256, height: 256}; // default to 256 since we know the image is a square\n            dataset.imageUrl = `${imagesPath}/size/w${iconSize.width}h${iconSize.height}/${filename}`;\n        }\n    }\n\n    if (options.feature?.emailCustomization || options.feature?.emailCustomizationAlpha) {\n        const renderContent = () => {\n            if (dataset.layout === 'minimal') {\n                return `\n                    <tr>\n                        <td class=\"kg-cta-content\">\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" class=\"kg-cta-content-wrapper\">\n                                <tr>\n                                    ${dataset.imageUrl ? `\n                                        <td class=\"kg-cta-image-container\" width=\"64\">\n                                            ${wrapWithLink(dataset, `<img src=\"${dataset.imageUrl}\" alt=\"CTA Image\" class=\"kg-cta-image\" width=\"64\" height=\"64\">`)}\n                                        </td>\n                                    ` : ''}\n                                    <td class=\"kg-cta-content-inner\">\n                                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                            ${dataset.textValue ? `\n                                                <tr>\n                                                    <td class=\"kg-cta-text\">\n                                                        ${dataset.textValue}\n                                                    </td>\n                                                </tr>\n                                            ` : ''}\n                                            ${showButton(dataset) ? `\n                                            <tr>\n                                                <td class=\"kg-cta-button-container\">\n                                                    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"btn\">\n                                                        <tr>\n                                                            <td class=\"${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\" style=\"${buttonStyle}\">\n                                                                <a href=\"${dataset.buttonUrl}\"\n                                                                   class=\"${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\"\n                                                                   style=\"${buttonLinkStyle}\"\n                                                                >\n                                                                    ${dataset.buttonText}\n                                                                </a>\n                                                            </td>\n                                                        </tr>\n                                                    </table>\n                                                </td>\n                                            </tr>\n                                            ` : ''}\n                                        </table>\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                `;\n            }\n\n            return `\n                <tr>\n                    <td class=\"kg-cta-content\">\n                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" class=\"kg-cta-content-wrapper\">\n                            ${dataset.imageUrl ? `\n                                <tr>\n                                    <td class=\"kg-cta-image-container\">\n                                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                            <tr>\n                                                <td>\n                                                    ${wrapWithLink(dataset, `<img src=\"${dataset.imageUrl}\" alt=\"CTA Image\" class=\"kg-cta-image\" ${imageDimensions ? `width=\"${imageDimensions.width}\"` : ''} ${imageDimensions ? `height=\"${imageDimensions.height}\"` : ''}>`)}\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                            <tr>\n                                <td class=\"kg-cta-text\">\n                                    ${dataset.textValue}\n                                </td>\n                            </tr>\n                            ${showButton(dataset) ? `\n                                <tr>\n                                    <td class=\"kg-cta-button-container\" align=\"${dataset.alignment}\">\n                                        <table class=\"btn\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n                                            <tr>\n                                                <td class=\"${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\" style=\"${buttonStyle}\" align=\"${dataset.alignment}\">\n                                                    <a href=\"${dataset.buttonUrl}\"\n                                                       class=\"${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\"\n                                                       style=\"${buttonLinkStyle}\"\n                                                    >\n                                                        ${dataset.buttonText}\n                                                    </a>\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                        </table>\n                    </td>\n                </tr>\n            `;\n        };\n\n        return `\n            <table class=\"kg-card kg-cta-card kg-cta-bg-${dataset.backgroundColor} ${dataset.showDividers ? '' : 'kg-cta-no-dividers'} kg-cta-${dataset.layout} ${dataset.hasSponsorLabel ? '' : 'kg-cta-no-label'} ${dataset.textValue ? '' : 'kg-cta-no-text'} ${dataset.imageUrl ? 'kg-cta-has-img' : ''} ${dataset.linkColor === 'accent' ? 'kg-cta-link-accent' : ''} ${dataset.alignment === 'center' ? 'kg-cta-centered' : ''}\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                ${dataset.hasSponsorLabel ? `\n                    <tr>\n                        <td>\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                <tr>\n                                    <td class=\"kg-cta-sponsor-label\">\n                                        ${dataset.sponsorLabel}\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                ` : ''}\n                ${renderContent()}\n            </table>\n        `;\n    } else {\n        const renderContent = () => {\n            if (dataset.layout === 'minimal') {\n                return `\n                    <tr>\n                        <td class=\"kg-cta-content\">\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" class=\"kg-cta-content-wrapper\">\n                                <tr>\n                                    ${dataset.imageUrl ? `\n                                        <td class=\"kg-cta-image-container\" width=\"64\">\n                                            ${wrapWithLink(dataset, `<img src=\"${dataset.imageUrl}\" alt=\"CTA Image\" class=\"kg-cta-image\" width=\"64\" height=\"64\">`)}\n                                        </td>\n                                    ` : ''}\n                                    <td class=\"kg-cta-content-inner\">\n                                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                            ${dataset.textValue ? `\n                                                <tr>\n                                                    <td class=\"kg-cta-text\">\n                                                        ${dataset.textValue}\n                                                    </td>\n                                                </tr>\n                                            ` : ''}\n                                            ${showButton(dataset) ? `\n                                            <tr>\n                                                <td class=\"kg-cta-button-container\">\n                                                    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"kg-cta-button-wrapper\">\n                                                        <tr>\n                                                            <td class=\"${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\" style=\"${buttonStyle}\">\n                                                                <a href=\"${dataset.buttonUrl}\"\n                                                                   class=\"kg-cta-button ${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\"\n                                                                   style=\"${buttonStyle}\"\n                                                                >\n                                                                    ${dataset.buttonText}\n                                                                </a>\n                                                            </td>\n                                                        </tr>\n                                                    </table>\n                                                </td>\n                                            </tr>\n                                            ` : ''}\n                                        </table>\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                `;\n            }\n\n            return `\n                <tr>\n                    <td class=\"kg-cta-content\">\n                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" class=\"kg-cta-content-wrapper\">\n                            ${dataset.imageUrl ? `\n                                <tr>\n                                    <td class=\"kg-cta-image-container\">\n                                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                            <tr>\n                                                <td>\n                                                    ${wrapWithLink(dataset, `<img src=\"${dataset.imageUrl}\" alt=\"CTA Image\" class=\"kg-cta-image\" ${imageDimensions ? `width=\"${imageDimensions.width}\"` : ''} ${imageDimensions ? `height=\"${imageDimensions.height}\"` : ''}>`)}\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                            <tr>\n                                <td class=\"kg-cta-text\">\n                                    ${dataset.textValue}\n                                </td>\n                            </tr>\n                            ${showButton(dataset) ? `\n                                <tr>\n                                    <td class=\"kg-cta-button-container\">\n                                        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n                                            <tr>\n                                                <td class=\"kg-cta-button-wrapper ${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\" style=\"${buttonStyle}\">\n                                                    <a href=\"${dataset.buttonUrl}\"\n                                                       class=\"kg-cta-button ${dataset.buttonColor === 'accent' ? 'kg-style-accent' : ''}\"\n                                                       style=\"${buttonStyle}\"\n                                                    >\n                                                        ${dataset.buttonText}\n                                                    </a>\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                        </table>\n                    </td>\n                </tr>\n            `;\n        };\n\n        return `\n            <table class=\"kg-card kg-cta-card kg-cta-bg-${dataset.backgroundColor} ${dataset.showDividers ? '' : 'kg-cta-no-dividers'} kg-cta-${dataset.layout} ${dataset.hasSponsorLabel ? '' : 'kg-cta-no-label'} ${dataset.textValue ? '' : 'kg-cta-no-text'} ${dataset.imageUrl ? 'kg-cta-has-img' : ''} ${dataset.linkColor === 'accent' ? 'kg-cta-link-accent' : ''} ${dataset.alignment === 'center' ? 'kg-cta-centered' : ''}\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                ${dataset.hasSponsorLabel ? `\n                    <tr>\n                        <td>\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                <tr>\n                                    <td class=\"kg-cta-sponsor-label\">\n                                        ${dataset.sponsorLabel}\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                ` : ''}\n                ${renderContent()}\n            </table>\n        `;\n    }\n}\n\nexport function renderCallToActionNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n    const dataset = {\n        layout: node.layout,\n        alignment: node.alignment,\n        textValue: node.textValue,\n        showButton: node.showButton,\n        showDividers: node.showDividers,\n        buttonText: node.buttonText,\n        buttonUrl: node.buttonUrl,\n        buttonColor: node.buttonColor,\n        buttonTextColor: node.buttonTextColor,\n        hasSponsorLabel: node.hasSponsorLabel,\n        backgroundColor: node.backgroundColor,\n        sponsorLabel: node.sponsorLabel,\n        imageUrl: node.imageUrl,\n        imageWidth: node.imageWidth,\n        imageHeight: node.imageHeight,\n        linkColor: node.linkColor\n    };\n\n    // Add validation for backgroundColor\n\n    if (!dataset.backgroundColor || !dataset.backgroundColor.match(/^[a-zA-Z\\d-]+|#([a-fA-F\\d]{3}|[a-fA-F\\d]{6})$/)) {\n        dataset.backgroundColor = 'white';\n    }\n\n    if (options.target === 'email') {\n        const emailDoc = options.createDocument();\n        const emailDiv = emailDoc.createElement('div');\n\n        emailDiv.innerHTML = emailCTATemplate(dataset, options);\n\n        return renderWithVisibility({element: emailDiv.firstElementChild}, node.visibility, options);\n    }\n\n    const element = document.createElement('div');\n\n    if (dataset.hasSponsorLabel) {\n        const cleanBasicHtml = buildCleanBasicHtmlForElement(element);\n        const cleanedHtml = cleanBasicHtml(dataset.sponsorLabel, {firstChildInnerContent: true});\n        dataset.sponsorLabel = cleanedHtml;\n    }\n    const htmlString = ctaCardTemplate(dataset);\n\n    element.innerHTML = htmlString?.trim();\n\n    return renderWithVisibility({element: element.firstElementChild}, node.visibility, options);\n}\n","export const rgbToHex = (rgb) => {\n    if (rgb === 'transparent') {\n        return rgb;\n    }\n\n    try {\n        // Extract the red, green, and blue values from the RGB string\n        const [r, g, b] = rgb.match(/\\d+/g);\n        // Convert each component to hexadecimal\n        const red = parseInt(r, 10).toString(16).padStart(2, '0');\n        const green = parseInt(g, 10).toString(16).padStart(2, '0');\n        const blue = parseInt(b, 10).toString(16).padStart(2, '0');\n        // Concatenate the hexadecimal values\n        const hex = `#${red}${green}${blue}`;\n        return hex;\n    } catch (e) {\n        return null;\n    }\n};\n","import {rgbToHex} from '../../utils/rgb-to-hex';\nimport {readImageAttributesFromElement} from '../../utils/read-image-attributes-from-element.js';\n\nexport function parseCallToActionNode(CallToActionNode) {\n    return {\n        div: (nodeElem) => {\n            const isCallToActionElement = nodeElem.classList?.contains('kg-cta-card');\n            if (isCallToActionElement) {\n                return {\n                    conversion(domNode) {\n                        const div = domNode;\n                        const layout = div.getAttribute('data-layout') || 'minimal';\n                        const alignment = div.getAttribute('data-alignment') || 'left';\n                        const textValueElement = domNode.querySelector('.kg-cta-text');\n                        const buttonElement = domNode.querySelector('.kg-cta-button');\n                        const buttonStyles = buttonElement?.style || {};\n                        const buttonColor = buttonStyles.backgroundColor || '#000000';\n                        const buttonTextColor = buttonStyles.color || '#ffffff';\n                        const sponsorLabelElement = domNode.querySelector('.kg-cta-sponsor-label');\n\n                        const bgMatch = div.className.match(/kg-cta-bg-(\\w+)/);\n                        const backgroundColor = bgMatch ? bgMatch[1] : 'grey';\n                        const showDividers = div.classList.contains('kg-cta-has-dividers');\n                        const imageContainer = domNode.querySelector('.kg-cta-image-container');\n                        const imageElement = imageContainer?.querySelector('img');\n                        let imageData = {\n                            imageUrl: '',\n                            imageWidth: null,\n                            imageHeight: null\n                        };\n\n                        if (imageElement) {\n                            const {src, width, height} = readImageAttributesFromElement(imageElement);\n                            imageData.imageUrl = src;\n                            imageData.imageWidth = width || null;\n                            imageData.imageHeight = height || null;\n                        }\n\n                        // sponsorLabel gets rendered without <p> in the web rendered version.\n                        // however we need to keep the <p> tag in the lexical stored version to ensure\n                        // consistency in the editor when a CTA card is copied and pasted into the editor.\n                        if (sponsorLabelElement) {\n                            sponsorLabelElement.innerHTML = `<p>${sponsorLabelElement.innerHTML.trim()}</p>`;\n                        }\n\n                        const payload = {\n                            layout: layout,\n                            alignment: alignment,\n                            textValue: textValueElement.textContent.trim() || '',\n                            showButton: buttonElement ? true : false,\n                            showDividers: showDividers,\n                            buttonText: buttonElement?.textContent.trim() || '',\n                            buttonUrl: buttonElement?.getAttribute('href'),\n                            buttonColor: rgbToHex(buttonColor),\n                            buttonTextColor: rgbToHex(buttonTextColor),\n                            hasSponsorLabel: sponsorLabelElement ? true : false,\n                            sponsorLabel: sponsorLabelElement?.innerHTML || '',\n                            backgroundColor: backgroundColor,\n                            imageUrl: imageData.imageUrl,\n                            imageWidth: imageData.imageWidth,\n                            imageHeight: imageData.imageHeight\n                        };\n\n                        const node = new CallToActionNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","// eslint-disable-next-line ghost/filenames/match-exported-class\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderCallToActionNode} from './calltoaction-renderer';\nimport {parseCallToActionNode} from './calltoaction-parser';\n\nexport class CallToActionNode extends generateDecoratorNode({\n    nodeType: 'call-to-action',\n    hasVisibility: true,\n    properties: [\n        {name: 'layout', default: 'minimal'},\n        {name: 'alignment', default: 'left'},\n        {name: 'textValue', default: '', wordCount: true},\n        {name: 'showButton', default: true},\n        {name: 'showDividers', default: true},\n        {name: 'buttonText', default: 'Learn more'},\n        {name: 'buttonUrl', default: ''},\n        {name: 'buttonColor', default: '#000000'}, // Where colour is customisable, we should use hex values\n        {name: 'buttonTextColor', default: '#ffffff'},\n        {name: 'hasSponsorLabel', default: true},\n        {name: 'sponsorLabel', default: '<p><span style=\"white-space: pre-wrap;\">SPONSORED</span></p>'},\n        {name: 'backgroundColor', default: 'grey'}, // Since this is one of a few fixed options, we stick to colour names.\n        {name: 'linkColor', default: 'text'},\n        {name: 'imageUrl', default: ''},\n        {name: 'imageWidth', default: null},\n        {name: 'imageHeight', default: null}\n    ],\n    defaultRenderFn: renderCallToActionNode\n}) {\n    static importDOM() {\n        return parseCallToActionNode(this);\n    }\n}\n\nexport const $createCallToActionNode = (dataset) => {\n    return new CallToActionNode(dataset);\n};\n\nexport const $isCallToActionNode = (node) => {\n    return node instanceof CallToActionNode;\n};\n","export class AsideParser {\n    constructor(NodeClass) {\n        this.NodeClass = NodeClass;\n    }\n\n    get DOMConversionMap() {\n        const self = this;\n\n        return {\n            blockquote: () => ({\n                conversion(domNode) {\n                    const isBigQuote = domNode.classList?.contains('kg-blockquote-alt');\n                    if (domNode.tagName === 'BLOCKQUOTE' && isBigQuote) {\n                        const node = new self.NodeClass();\n                        return {node};\n                    }\n\n                    return null;\n                },\n                priority: 0\n            })\n        };\n    }\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {ElementNode} from 'lexical';\nimport {AsideParser} from './AsideParser';\n\nexport class AsideNode extends ElementNode {\n    static getType() {\n        return 'aside';\n    }\n\n    static clone(node) {\n        return new this(\n            node.__key\n        );\n    }\n\n    static get urlTransformMap() {\n        return {};\n    }\n\n    constructor(key) {\n        super(key);\n    }\n\n    static importJSON(serializedNode) {\n        const node = new this();\n        node.setFormat(serializedNode.format);\n        node.setIndent(serializedNode.indent);\n        node.setDirection(serializedNode.direction);\n        return node;\n    }\n\n    exportJSON() {\n        const dataset = {\n            ...super.exportJSON(),\n            type: 'aside',\n            version: 1\n        };\n        return dataset;\n    }\n\n    static importDOM() {\n        const parser = new AsideParser(this);\n        return parser.DOMConversionMap;\n    }\n\n    /* c8 ignore start */\n    createDOM() {\n        return document.createElement('div');\n    }\n\n    updateDOM() {\n        return false;\n    }\n\n    isInline() {\n        return false;\n    }\n\n    extractWithChild() {\n        return true;\n    }\n    /* c8 ignore stop */\n}\n\nexport function $createAsideNode() {\n    return new AsideNode();\n}\n\nexport function $isAsideNode(node) {\n    return node instanceof AsideNode;\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\n\nexport function renderHorizontalRuleNode(_, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const element = document.createElement('hr');\n    return {element};\n}","export function parseHorizontalRuleNode(HorizontalRuleNode) {\n    return {\n        hr: () => ({\n            conversion() {\n                const node = new HorizontalRuleNode();\n                return {node};\n            },\n            priority: 0\n        })\n    };\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderHorizontalRuleNode} from './horizontalrule-renderer';\nimport {parseHorizontalRuleNode} from './horizontalrule-parser';\n\nexport class HorizontalRuleNode extends generateDecoratorNode({\n    nodeType: 'horizontalrule',\n    defaultRenderFn: renderHorizontalRuleNode\n}) {\n    static importDOM() {\n        return parseHorizontalRuleNode(this);\n    }\n\n    getTextContent() {\n        return '---\\n\\n';\n    }\n\n    hasEditMode() {\n        return false;\n    }\n}\n\nexport function $createHorizontalRuleNode() {\n    return new HorizontalRuleNode();\n}\n\nexport function $isHorizontalRuleNode(node) {\n    return node instanceof HorizontalRuleNode;\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport {renderWithVisibility} from '../../utils/visibility';\n\nexport function renderHtmlNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const html = node.html;\n\n    if (!html) {\n        return renderEmptyContainer(document);\n    }\n\n    const wrappedHtml = `\\n<!--kg-card-begin: html-->\\n${html}\\n<!--kg-card-end: html-->\\n`;\n\n    const textarea = document.createElement('textarea');\n    textarea.value = wrappedHtml;\n\n    if (node.visibility) {\n        const renderOutput = {element: textarea, type: 'value'};\n        return renderWithVisibility(renderOutput, node.visibility, options);\n    }\n\n    // `type: 'value'` will render the value of the textarea element\n    return {element: textarea, type: 'value'};\n}\n","export function parseHtmlNode(HtmlNode) {\n    return {\n        '#comment': (nodeElem) => {\n            if (nodeElem.nodeType === 8 && nodeElem.nodeValue.trim().match(/^kg-card-begin:\\s?html$/)) {\n                return {\n                    conversion(domNode) {\n                        let html = [];\n                        let nextNode = domNode.nextSibling;\n\n                        while (nextNode && !isHtmlEndComment(nextNode)) {\n                            let currentNode = nextNode;\n                            html.push(currentNode.outerHTML);\n                            nextNode = currentNode.nextSibling;\n                            // remove nodes as we go so that they don't go through the parser\n                            currentNode.remove();\n                        }\n\n                        let payload = {html: html.join('\\n').trim()};\n                        const node = new HtmlNode(payload);\n                        return {node};\n                    },\n                    priority: 0\n                };\n            }\n\n            return null;\n        },\n        table: (nodeElem) => {\n            if (nodeElem.nodeType === 1 && nodeElem.tagName === 'TABLE' && nodeElem.parentNode.tagName !== 'TABLE') {\n                return {\n                    conversion(domNode) {\n                        const payload = {html: domNode.outerHTML};\n                        const node = new HtmlNode(payload);\n                        return {node};\n                    },\n                    priority: 0\n                };\n            }\n\n            return null;\n        }\n    };\n}\n\nfunction isHtmlEndComment(node) {\n    return node && node.nodeType === 8 && node.nodeValue.trim().match(/^kg-card-end:\\s?html$/);\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderHtmlNode} from './html-renderer';\nimport {parseHtmlNode} from './html-parser';\n\nexport class HtmlNode extends generateDecoratorNode({\n    nodeType: 'html',\n    hasVisibility: true,\n    properties: [\n        {name: 'html', default: '', urlType: 'html', wordCount: true}\n    ],\n    defaultRenderFn: renderHtmlNode\n}) {\n    static importDOM() {\n        return parseHtmlNode(this);\n    }\n\n    isEmpty() {\n        return !this.__html;\n    }\n}\n\nexport function $createHtmlNode(dataset) {\n    return new HtmlNode(dataset);\n}\n\nexport function $isHtmlNode(node) {\n    return node instanceof HtmlNode;\n}\n","export function parseToggleNode(ToggleNode) {\n    return {\n        div: (nodeElem) => {\n            const isKgToggleCard = nodeElem.classList?.contains('kg-toggle-card');\n            if (nodeElem.tagName === 'DIV' && isKgToggleCard) {\n                return {\n                    conversion(domNode) {\n                        const headingNode = domNode.querySelector('.kg-toggle-heading-text');\n                        const heading = headingNode.textContent;\n\n                        const contentNode = domNode.querySelector('.kg-toggle-content');\n                        const content = contentNode.textContent;\n\n                        const payload = {\n                            heading,\n                            content\n                        };\n\n                        const node = new ToggleNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}","const oneline = function (strings, ...values) {\n    // Handle case where a plain string is passed\n    if (typeof strings === 'string') {\n        return strings.replace(/\\n\\s+/g, '').trim();\n    }\n\n    // Handle tagged template literal case\n    const result = strings.reduce((acc, str, i) => {\n        return acc + str + (values[i] || '');\n    }, '');\n    // Remove newline+indentation patterns while preserving intentional whitespace\n    return result.replace(/\\n\\s+/g, '').trim();\n};\n\n// Using `html` as a synonym for `oneline` in order to get syntax highlighting in editors\nconst html = oneline;\n\nexport {oneline, html};","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {html} from '../../utils/tagged-template-fns.mjs';\n\nfunction cardTemplate({node}) {\n    return (\n        `\n        <div class=\"kg-card kg-toggle-card\" data-kg-toggle-state=\"close\">\n            <div class=\"kg-toggle-heading\">\n                <h4 class=\"kg-toggle-heading-text\">${node.heading}</h4>\n                <button class=\"kg-toggle-card-icon\" aria-label=\"Expand toggle to read content\">\n                    <svg id=\"Regular\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n                        <path class=\"cls-1\" d=\"M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311\"></path>\n                    </svg>\n                </button>\n            </div>\n            <div class=\"kg-toggle-content\">${node.content}</div>\n        </div>\n        `\n    );\n}\n\nfunction emailCardTemplate({node}, options = {}) {\n    if (options.feature?.emailCustomization || options.feature?.emailCustomizationAlpha) {\n        return (\n            html`\n            <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\" class=\"kg-toggle-card\">\n                <tbody>\n                    <tr>\n                        <td class=\"kg-toggle-heading\">\n                            <h4>${node.heading}</h4>\n                        </td>\n                    </tr>\n                    <tr>\n                        <td class=\"kg-toggle-content\">\n                            ${node.content}\n                        </td>\n                    </tr>\n                </tbody>\n            </table>\n            `\n        );\n    }\n\n    return (\n        `\n        <div style=\"background: transparent;\n        border: 1px solid rgba(124, 139, 154, 0.25); border-radius: 4px; padding: 20px; margin-bottom: 1.5em;\">\n            <h4 style=\"font-size: 1.375rem; font-weight: 600; margin-bottom: 8px; margin-top:0px\">${node.heading}</h4>\n            <div style=\"font-size: 1rem; line-height: 1.5; margin-bottom: -1.5em;\">${node.content}</div>\n        </div>\n        `\n    );\n}\n\nexport function renderToggleNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n\n    const htmlString = options.target === 'email'\n        ? emailCardTemplate({node}, options)\n        : cardTemplate({node});\n\n    const container = document.createElement('div');\n    container.innerHTML = htmlString.trim();\n\n    const element = container.firstElementChild;\n    return {element};\n}","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseToggleNode} from './toggle-parser';\nimport {renderToggleNode} from './toggle-renderer';\n\nexport class ToggleNode extends generateDecoratorNode({\n    nodeType: 'toggle',\n    properties: [\n        {name: 'heading', default: '', urlType: 'html', wordCount: true},\n        {name: 'content', default: '', urlType: 'html', wordCount: true}\n    ],\n    defaultRenderFn: renderToggleNode\n}) {\n    static importDOM() {\n        return parseToggleNode(this);\n    }\n}\n\nexport const $createToggleNode = (dataset) => {\n    return new ToggleNode(dataset);\n};\n\nexport function $isToggleNode(node) {\n    return node instanceof ToggleNode;\n}\n","export function parseButtonNode(ButtonNode) {\n    return {\n        div: (nodeElem) => {\n            const isButtonCard = nodeElem.classList?.contains('kg-button-card');\n            if (nodeElem.tagName === 'DIV' && isButtonCard) {\n                return {\n                    conversion(domNode) {\n                        const alignmentClass = nodeElem.className.match(/kg-align-(left|center)/);\n\n                        let alignment;\n                        if (alignmentClass) {\n                            alignment = alignmentClass[1];\n                        }\n\n                        const buttonNode = domNode?.querySelector('.kg-btn');\n                        const buttonUrl = buttonNode.getAttribute('href');\n                        const buttonText = buttonNode.textContent;\n\n                        const payload = {\n                            buttonText: buttonText,\n                            alignment: alignment,\n                            buttonUrl: buttonUrl\n                        };\n\n                        const node = new ButtonNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","import clsx from 'clsx';\nimport {html} from '../tagged-template-fns.mjs';\n\n/**\n * @param {Object} options\n * @param {string} [options.alignment]\n * @param {string} [options.color='accent']\n * @param {string} [options.text='']\n * @param {string} [options.textColor]\n * @param {string} [options.url='']\n * @returns {string}\n */\nexport function renderEmailButton({\n    alignment = '',\n    color = 'accent',\n    text = '',\n    url = ''\n} = {}) {\n    const buttonClasses = clsx(\n        'btn',\n        color === 'accent' && 'btn-accent'\n    );\n\n    return html`\n        <table class=\"${buttonClasses}\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"${alignment}\">\n            <tbody>\n                <tr>\n                    <td align=\"center\">\n                        <a href=\"${url}\">${text}</a>\n                    </td>\n                </tr>\n            </tbody>\n        </table>\n    `;\n}","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport {renderEmailButton} from '../../utils/render-helpers/email-button';\nimport {html} from '../../utils/tagged-template-fns.mjs';\n\nexport function renderButtonNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    if (!node.buttonUrl || node.buttonUrl.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    if (options.target === 'email') {\n        return emailTemplate(node, options, document);\n    } else {\n        return frontendTemplate(node, document);\n    }\n}\n\nfunction frontendTemplate(node, document) {\n    const cardClasses = getCardClasses(node);\n\n    const cardDiv = document.createElement('div');\n    cardDiv.setAttribute('class', cardClasses);\n\n    const button = document.createElement('a');\n    button.setAttribute('href', node.buttonUrl);\n    button.setAttribute('class', 'kg-btn kg-btn-accent');\n    button.textContent = node.buttonText || 'Button Title';\n\n    cardDiv.appendChild(button);\n    return {element: cardDiv};\n}\n\nfunction emailTemplate(node, options, document) {\n    const {buttonUrl, buttonText} = node;\n\n    let cardHtml;\n    if (options.feature?.emailCustomization) {\n        cardHtml = html`\n        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n            <tr>\n                <td>\n                    <table class=\"btn btn-accent\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"${node.alignment}\">\n                        <tr>\n                            <td align=\"center\">\n                                <a href=\"${buttonUrl}\">${buttonText}</a>\n                            </td>\n                        </tr>\n                    </table>\n                </td>\n            </tr>\n        </table>`;\n\n        const element = document.createElement('p');\n        element.innerHTML = cardHtml;\n        return {element};\n    } else if (options.feature?.emailCustomizationAlpha) {\n        const buttonHtml = renderEmailButton({\n            alignment: node.alignment,\n            color: 'accent',\n            url: buttonUrl,\n            text: buttonText\n        });\n\n        cardHtml = html`\n        <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n            <tbody>\n                <tr>\n                    <td>\n                        ${buttonHtml}\n                    </td>\n                </tr>\n            </tbody>\n        </table>\n        `;\n\n        const element = document.createElement('div');\n        element.innerHTML = cardHtml;\n        return {element, type: 'inner'};\n    } else {\n        cardHtml = html`\n        <div class=\"btn btn-accent\">\n            <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"${node.alignment}\">\n                <tr>\n                    <td align=\"center\">\n                        <a href=\"${buttonUrl}\">${buttonText}</a>\n                    </td>\n                </tr>\n            </table>\n        </div>\n        `;\n\n        const element = document.createElement('p');\n        element.innerHTML = cardHtml;\n        return {element};\n    }\n}\n\nfunction getCardClasses(node) {\n    let cardClasses = ['kg-card kg-button-card'];\n\n    if (node.alignment) {\n        cardClasses.push(`kg-align-${node.alignment}`);\n    }\n\n    return cardClasses.join(' ');\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseButtonNode} from './button-parser';\nimport {renderButtonNode} from './button-renderer';\n\nexport class ButtonNode extends generateDecoratorNode({\n    nodeType: 'button',\n    properties: [\n        {name: 'buttonText', default: ''},\n        {name: 'alignment', default: 'center'},\n        {name: 'buttonUrl', default: '', urlType: 'url'}\n    ],\n    defaultRenderFn: renderButtonNode\n}) {\n    static importDOM() {\n        return parseButtonNode(this);\n    }\n}\n\nexport const $createButtonNode = (dataset) => {\n    return new ButtonNode(dataset);\n};\n\nexport function $isButtonNode(node) {\n    return node instanceof ButtonNode;\n}\n","export function parseBookmarkNode(BookmarkNode) {\n    return {\n        figure: (nodeElem) => {\n            const isKgBookmarkCard = nodeElem.classList?.contains('kg-bookmark-card');\n            if (nodeElem.tagName === 'FIGURE' && isKgBookmarkCard) {\n                return {\n                    conversion(domNode) {\n                        const url = domNode?.querySelector('.kg-bookmark-container')?.getAttribute('href');\n                        const icon = domNode?.querySelector('.kg-bookmark-icon')?.src;\n                        const title = domNode?.querySelector('.kg-bookmark-title')?.textContent;\n                        const description = domNode?.querySelector('.kg-bookmark-description')?.textContent;\n                        const author = domNode?.querySelector('.kg-bookmark-publisher')?.textContent; // NOTE: This is NOT in error. The classes are reversed for theme backwards-compatibility.\n                        const publisher = domNode?.querySelector('.kg-bookmark-author')?.textContent; // NOTE: This is NOT in error. The classes are reversed for theme backwards-compatibility.\n                        const thumbnail = domNode?.querySelector('.kg-bookmark-thumbnail img')?.src;\n                        const caption = domNode?.querySelector('figure.kg-bookmark-card figcaption')?.textContent;\n                        const payload = {\n                            url: url,\n                            metadata: {\n                                icon: icon,\n                                title: title,\n                                description: description,\n                                author: author,\n                                publisher: publisher,\n                                thumbnail: thumbnail\n                            },\n                            caption: caption\n                        };\n                        const node = new BookmarkNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        },\n        div: (nodeElem) => {\n            if (nodeElem.nodeType === 1 && nodeElem.tagName === 'DIV' && nodeElem.className.match(/graf--mixtapeEmbed/)) {\n                return {\n                    conversion(domNode) {\n                        // Grab the relevant elements - Anchor wraps most of the data\n                        const anchorElement = domNode.querySelector('.markup--mixtapeEmbed-anchor');\n                        const titleElement = anchorElement.querySelector('.markup--mixtapeEmbed-strong');\n                        const descElement = anchorElement.querySelector('.markup--mixtapeEmbed-em');\n                        // Image is a top level field inside it's own a tag\n                        const imgElement = domNode.querySelector('.mixtapeImage');\n\n                        domNode.querySelector('br').remove();\n\n                        // Grab individual values from the elements\n                        const url = anchorElement.getAttribute('href');\n                        let title = '';\n                        let description = '';\n                        let thumbnail = '';\n\n                        if (titleElement && titleElement.innerHTML) {\n                            title = titleElement.innerHTML.trim();\n                            // Cleanup anchor so we can see what's left now that we've processed title\n                            anchorElement.removeChild(titleElement);\n                        }\n\n                        if (descElement && descElement.innerHTML) {\n                            description = descElement.innerHTML.trim();\n                            // Cleanup anchor so we can see what's left now that we've processed description\n                            anchorElement.removeChild(descElement);\n                        }\n\n                        // Publisher is the remaining text in the anchor, once title & desc are removed\n                        let publisher = anchorElement.innerHTML.trim();\n\n                        // Image is optional,\n                        // The element usually still exists with an additional has.mixtapeImage--empty class and has no background image\n                        if (imgElement && imgElement.style['background-image']) {\n                            thumbnail = imgElement.style['background-image'].match(/url\\(([^)]*?)\\)/)[1];\n                        }\n\n                        let payload = {url,\n                            metadata: {\n                                title,\n                                description,\n                                publisher,\n                                thumbnail\n                            }};\n                        const node = new BookmarkNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","/**\n * Escape HTML special characters\n * @param {string} unsafe\n * @returns string\n */\nexport function escapeHtml(unsafe) {\n    return unsafe\n        .replace(/&/g, '&amp;')\n        .replace(/</g, '&lt;')\n        .replace(/>/g, '&gt;')\n        .replace(/\"/g, '&quot;')\n        .replace(/'/g, '&#039;');\n}","import {escapeHtml} from './escape-html';\n\nexport function truncateText(text, maxLength) {\n    if (text && text.length > maxLength) {\n        return text.substring(0, maxLength - 1).trim() + '…';\n    } else {\n        return text ?? '';\n    }\n}\n\nexport function truncateHtml(text, maxLength, maxLengthMobile) {\n    // If no mobile length specified or mobile length is larger than desktop,\n    // just do a simple truncate\n    if (!maxLengthMobile || maxLength <= maxLengthMobile) {\n        return escapeHtml(truncateText(text, maxLength));\n    }\n\n    // Handle text shorter than mobile length\n    if (text.length <= maxLengthMobile) {\n        return escapeHtml(text);\n    }\n\n    if (text && text.length > maxLengthMobile) {\n        let ellipsis = '';\n\n        if (text.length > maxLengthMobile && text.length <= maxLength) {\n            ellipsis = '<span class=\"hide-desktop\">…</span>';\n        } else if (text.length > maxLength) {\n            ellipsis = '…';\n        }\n\n        return escapeHtml(text.substring(0, maxLengthMobile - 1)) + '<span class=\"desktop-only\">' + escapeHtml(text.substring(maxLengthMobile - 1, maxLength - 1)) + '</span>' + ellipsis;\n    } else {\n        return escapeHtml(text ?? '');\n    }\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport {escapeHtml} from '../../utils/escape-html';\nimport {truncateHtml} from '../../utils/truncate';\n\nexport function renderBookmarkNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n\n    if (!node.url || node.url.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    if (options.target === 'email') {\n        return emailTemplate(node, document);\n    } else {\n        return frontendTemplate(node, document);\n    }\n}\n\nfunction emailTemplate(node, document) {\n    const title = escapeHtml(node.title);\n    const publisher = escapeHtml(node.publisher);\n    const author = escapeHtml(node.author);\n    const description = escapeHtml(node.description);\n\n    const icon = node.icon;\n    const url = node.url;\n    const thumbnail = node.thumbnail;\n    const caption = node.caption;\n\n    const element = document.createElement('div');\n\n    const html =\n        `\n        <!--[if !mso !vml]-->\n            <figure class=\"kg-card kg-bookmark-card ${caption ? `kg-card-hascaption` : ''}\">\n                <a class=\"kg-bookmark-container\" href=\"${url}\">\n                    <div class=\"kg-bookmark-content\">\n                        <div class=\"kg-bookmark-title\">${title}</div>\n                        <div class=\"kg-bookmark-description\">${truncateHtml(description, 120, 90)}</div>\n                        <div class=\"kg-bookmark-metadata\">\n                            ${icon ? `<img class=\"kg-bookmark-icon\" src=\"${icon}\" alt=\"\">` : ''}\n                            ${publisher ? `<span class=\"kg-bookmark-author\" src=\"${publisher}\">${publisher}</span>` : ''}\n                            ${author ? `<span class=\"kg-bookmark-publisher\" src=\"${author}\">${author}</span>` : ''}\n                        </div>\n                    </div>\n                    ${thumbnail ? `<div class=\"kg-bookmark-thumbnail\" style=\"background-image: url('${thumbnail}')\">\n                        <img src=\"${thumbnail}\" alt=\"\" onerror=\"this.style.display='none'\"></div>` : ''}\n                </a>\n                ${caption ? `<figcaption>${caption}</figcaption>` : ''}\n            </figure>\n        <!--[endif]-->\n        <!--[if vml]>\n            <table class=\"kg-card kg-bookmark-card--outlook\" style=\"margin: 0; padding: 0; width: 100%; border: 1px solid #e5eff5; background: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; border-collapse: collapse; border-spacing: 0;\" width=\"100%\">\n                <tr>\n                    <td width=\"100%\" style=\"padding: 20px;\">\n                        <table style=\"margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;\">\n                            <tr>\n                                <td class=\"kg-bookmark-title--outlook\">\n                                    <a href=\"${url}\" style=\"text-decoration: none; color: #15212A; font-size: 15px; line-height: 1.5em; font-weight: 600;\">\n                                        ${title}\n                                    </a>\n                                </td>\n                            </tr>\n                            <tr>\n                                <td>\n                                    <div class=\"kg-bookmark-description--outlook\">\n                                        <a href=\"${url}\" style=\"text-decoration: none; margin-top: 12px; color: #738a94; font-size: 13px; line-height: 1.5em; font-weight: 400;\">\n                                            ${truncateHtml(description, 120, 90)}\n                                        </a>\n                                    </div>\n                                </td>\n                            </tr>\n                            <tr>\n                                <td class=\"kg-bookmark-metadata--outlook\" style=\"padding-top: 14px; color: #15212A; font-size: 13px; font-weight: 400; line-height: 1.5em;\">\n                                    <table style=\"margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;\">\n                                        <tr>\n                                            ${icon ? `\n                                                <td valign=\"middle\" class=\"kg-bookmark-icon--outlook\" style=\"padding-right: 8px; font-size: 0; line-height: 1.5em;\">\n                                                    <a href=\"${url}\" style=\"text-decoration: none; color: #15212A;\">\n                                                        <img src=\"${icon}\" width=\"22\" height=\"22\" alt=\" \">\n                                                    </a>\n                                                </td>\n                                            ` : ''}\n                                            <td valign=\"middle\" class=\"kg-bookmark-byline--outlook\">\n                                                <a href=\"${url}\" style=\"text-decoration: none; color: #15212A;\">\n                                                    ${publisher}\n                                                    ${author ? `&nbsp;&#x2022;&nbsp;` : ''}\n                                                    ${author}\n                                                </a>\n                                            </td>\n                                        </tr>\n                                    </table>\n                                </td>\n                            </tr>\n                        </table>\n                    </td>\n                </tr>\n            </table>\n            <div class=\"kg-bookmark-spacer--outlook\" style=\"height: 1.5em;\">&nbsp;</div>\n        <![endif]-->`;\n\n    element.innerHTML = html;\n    return {element};\n}\n\nfunction frontendTemplate(node, document) {\n    const element = document.createElement('figure');\n    const caption = node.caption;\n    let cardClass = 'kg-card kg-bookmark-card';\n    if (caption) {\n        cardClass += ' kg-card-hascaption';\n    }\n    element.setAttribute('class', cardClass);\n\n    const container = document.createElement('a');\n    container.setAttribute('class','kg-bookmark-container');\n    container.href = node.url;\n    element.appendChild(container);\n\n    const content = document.createElement('div');\n    content.setAttribute('class','kg-bookmark-content');\n    container.appendChild(content);\n\n    const title = document.createElement('div');\n    title.setAttribute('class','kg-bookmark-title');\n    title.textContent = node.title;\n    content.appendChild(title);\n\n    const description = document.createElement('div');\n    description.setAttribute('class','kg-bookmark-description');\n    description.textContent = node.description;\n    content.appendChild(description);\n\n    const metadata = document.createElement('div');\n    metadata.setAttribute('class','kg-bookmark-metadata');\n    content.appendChild(metadata);\n\n    metadata.icon = node.icon;\n    if (metadata.icon) {\n        const icon = document.createElement('img');\n        icon.setAttribute('class','kg-bookmark-icon');\n        icon.src = metadata.icon;\n        icon.alt = '';\n        metadata.appendChild(icon);\n    }\n\n    metadata.publisher = node.publisher;\n    if (metadata.publisher) {\n        const publisher = document.createElement('span');\n        publisher.setAttribute('class','kg-bookmark-author'); // NOTE: This is NOT in error. The classes are reversed for theme backwards-compatibility.\n        publisher.textContent = metadata.publisher;\n        metadata.appendChild(publisher);\n    }\n\n    metadata.author = node.author;\n    if (metadata.author) {\n        const author = document.createElement('span');\n        author.setAttribute('class','kg-bookmark-publisher'); // NOTE: This is NOT in error. The classes are reversed for theme backwards-compatibility.\n        author.textContent = metadata.author;\n        metadata.appendChild(author);\n    }\n\n    metadata.thumbnail = node.thumbnail;\n    if (metadata.thumbnail) {\n        const thumbnailDiv = document.createElement('div');\n        thumbnailDiv.setAttribute('class','kg-bookmark-thumbnail');\n        container.appendChild(thumbnailDiv);\n\n        const thumbnail = document.createElement('img');\n        thumbnail.src = metadata.thumbnail;\n        thumbnail.alt = '';\n        thumbnail.setAttribute('onerror',`this.style.display = 'none'`); // Hide thumbnail div if image fails to load\n        thumbnailDiv.appendChild(thumbnail);\n    }\n\n    if (caption) {\n        const figCaption = document.createElement('figcaption');\n        figCaption.innerHTML = caption;\n        element.appendChild(figCaption);\n    }\n\n    return {element};\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseBookmarkNode} from './bookmark-parser';\nimport {renderBookmarkNode} from './bookmark-renderer';\n\nexport class BookmarkNode extends generateDecoratorNode({\n    nodeType: 'bookmark',\n    properties: [\n        {name: 'title', default: '', wordCount: true},\n        {name: 'description', default: '', wordCount: true},\n        {name: 'url', default: '', urlType: 'url', wordCount: true},\n        {name: 'caption', default: '', wordCount: true},\n        {name: 'author', default: ''},\n        {name: 'publisher', default: ''},\n        {name: 'icon', urlPath: 'metadata.icon', default: '', urlType: 'url'},\n        {name: 'thumbnail', urlPath: 'metadata.thumbnail', default: '', urlType: 'url'}\n    ],\n    defaultRenderFn: renderBookmarkNode\n}) {\n    static importDOM() {\n        return parseBookmarkNode(this);\n    }\n\n    /* override */\n    constructor({url, metadata, caption} = {}, key) {\n        super(key);\n        this.__url = url || '';\n        this.__icon = metadata?.icon || '';\n        this.__title = metadata?.title || '';\n        this.__description = metadata?.description || '';\n        this.__author = metadata?.author || '';\n        this.__publisher = metadata?.publisher || '';\n        this.__thumbnail = metadata?.thumbnail || '';\n        this.__caption = caption || '';\n    }\n\n    /* @override */\n    getDataset() {\n        const self = this.getLatest();\n        return {\n            url: self.__url,\n            metadata: {\n                icon: self.__icon,\n                title: self.__title,\n                description: self.__description,\n                author: self.__author,\n                publisher: self.__publisher,\n                thumbnail: self.__thumbnail\n            },\n            caption: self.__caption\n        };\n    }\n\n    /* @override */\n    static importJSON(serializedNode) {\n        const {url, metadata, caption} = serializedNode;\n        const node = new this({\n            url,\n            metadata,\n            caption\n        });\n        return node;\n    }\n\n    /* @override */\n    exportJSON() {\n        const dataset = {\n            type: 'bookmark',\n            version: 1,\n            url: this.url,\n            metadata: {\n                icon: this.icon,\n                title: this.title,\n                description: this.description,\n                author: this.author,\n                publisher: this.publisher,\n                thumbnail: this.thumbnail\n            },\n            caption: this.caption\n        };\n        return dataset;\n    }\n\n    isEmpty() {\n        return !this.url;\n    }\n}\n\nexport const $createBookmarkNode = (dataset) => {\n    return new BookmarkNode(dataset);\n};\n\nexport function $isBookmarkNode(node) {\n    return node instanceof BookmarkNode;\n}\n","export function sizeToBytes(size) {\n    if (!size) {\n        return 0;\n    }\n    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n    const sizeParts = size.split(' ');\n    const sizeNumber = parseFloat(sizeParts[0]);\n    const sizeUnit = sizeParts[1];\n    const sizeUnitIndex = sizes.indexOf(sizeUnit);\n    if (sizeUnitIndex === -1) {\n        return 0;\n    }\n    return Math.round(sizeNumber * Math.pow(1024, sizeUnitIndex));\n}\n\nexport function bytesToSize(bytes) {\n    if (!bytes) {\n        return '0 Byte';\n    }\n    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n    if (bytes === 0) {\n        return '0 Byte';\n    }\n    const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));\n    return Math.round((bytes / Math.pow(1024, i))) + ' ' + sizes[i];\n}","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport {escapeHtml} from '../../utils/escape-html';\nimport {bytesToSize} from '../../utils/size-byte-converter';\n\nexport function renderFileNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    if (!node.src || node.src.trim() === '') {\n        return renderEmptyContainer(document);\n    }\n\n    if (options.target === 'email') {\n        return emailTemplate(node, document, options);\n    } else {\n        return cardTemplate(node, document);\n    }\n}\n\nfunction emailTemplate(node, document, options) {\n    let iconCls;\n    if (!node.fileTitle && !node.fileCaption) {\n        iconCls = 'margin-top: 6px; height: 20px; width: 20px; max-width: 20px; padding-top: 4px; padding-bottom: 4px;';\n    } else {\n        iconCls = 'margin-top: 6px; height: 24px; width: 24px; max-width: 24px;';\n    }\n\n    const html = (`\n        <table cellspacing=\"0\" cellpadding=\"4\" border=\"0\" class=\"kg-file-card\" width=\"100%\">\n            <tr>\n                <td>\n                    <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                        <tr>\n                            <td valign=\"middle\" style=\"vertical-align: middle;\">\n                                ${node.fileTitle ? `\n                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\"><tr><td>\n                                    <a href=\"${escapeHtml(options.postUrl)}\" class=\"kg-file-title\">${escapeHtml(node.fileTitle)}</a>\n                                </td></tr></table>\n                                ` : ``}\n                                ${node.fileCaption ? `\n                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\"><tr><td>\n                                    <a href=\"${escapeHtml(options.postUrl)}\" class=\"kg-file-description\">${escapeHtml(node.fileCaption)}</a>\n                                </td></tr></table>\n                                ` : ``}\n                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\"><tr><td>\n                                    <a href=\"${escapeHtml(options.postUrl)}\" class=\"kg-file-meta\"><span class=\"kg-file-name\">${escapeHtml(node.fileName)}</span> &bull; ${bytesToSize(node.fileSize)}</a>\n                                </td></tr></table>\n                            </td>\n                            <td width=\"80\" valign=\"middle\" class=\"kg-file-thumbnail\">\n                                <a href=\"${escapeHtml(options.postUrl)}\" style=\"display: block; top: 0; right: 0; bottom: 0; left: 0;\">\n                                    <img src=\"https://static.ghost.org/v4.0.0/images/download-icon-darkmode.png\" style=\"${escapeHtml(iconCls)}\">\n                                </a>\n                            </td>\n                        </tr>\n                    </table>\n                </td>\n            </tr>\n        </table>\n    `);\n\n    const container = document.createElement('div');\n    container.innerHTML = html.trim();\n\n    return {element: container.firstElementChild};\n}\n\nfunction cardTemplate(node, document) {\n    const card = document.createElement('div');\n    card.setAttribute('class', 'kg-card kg-file-card');\n\n    const container = document.createElement('a');\n    container.setAttribute('class', 'kg-file-card-container');\n    container.setAttribute('href', node.src);\n    container.setAttribute('title', 'Download');\n    container.setAttribute('download', '');\n\n    const contents = document.createElement('div');\n    contents.setAttribute('class', 'kg-file-card-contents');\n\n    const title = document.createElement('div');\n    title.setAttribute('class', 'kg-file-card-title');\n    title.textContent = node.fileTitle || '';\n\n    const caption = document.createElement('div');\n    caption.setAttribute('class', 'kg-file-card-caption');\n    caption.textContent = node.fileCaption || '';\n\n    const metadata = document.createElement('div');\n    metadata.setAttribute('class', 'kg-file-card-metadata');\n\n    const filename = document.createElement('div');\n    filename.setAttribute('class', 'kg-file-card-filename');\n    filename.textContent = node.fileName || '';\n\n    const filesize = document.createElement('div');\n    filesize.setAttribute('class', 'kg-file-card-filesize');\n    filesize.textContent = node.formattedFileSize || '';\n\n    metadata.appendChild(filename);\n    metadata.appendChild(filesize);\n\n    contents.appendChild(title);\n    contents.appendChild(caption);\n    contents.appendChild(metadata);\n\n    container.appendChild(contents);\n\n    const icon = document.createElement('div');\n    icon.setAttribute('class', 'kg-file-card-icon');\n\n    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    svg.setAttribute('viewBox', '0 0 24 24');\n\n    const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n\n    const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n    style.textContent = '.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}';\n\n    defs.appendChild(style);\n\n    const titleElement = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n    titleElement.textContent = 'download-circle';\n\n    const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n    polyline.setAttribute('class', 'a');\n    polyline.setAttribute('points', '8.25 14.25 12 18 15.75 14.25');\n\n    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n    line.setAttribute('class', 'a');\n    line.setAttribute('x1', '12');\n    line.setAttribute('y1', '6.75');\n    line.setAttribute('x2', '12');\n    line.setAttribute('y2', '18');\n\n    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n    circle.setAttribute('class', 'a');\n    circle.setAttribute('cx', '12');\n    circle.setAttribute('cy', '12');\n    circle.setAttribute('r', '11.25');\n\n    svg.appendChild(defs);\n    svg.appendChild(titleElement);\n    svg.appendChild(polyline);\n    svg.appendChild(line);\n    svg.appendChild(circle);\n\n    icon.appendChild(svg);\n    container.appendChild(icon);\n    card.appendChild(container);\n\n    return {element: card};\n}","import {sizeToBytes} from '../../utils/size-byte-converter';\n\nexport function parseFileNode(FileNode) {\n    return {\n        div: (nodeElem) => {\n            const isKgFileCard = nodeElem.classList?.contains('kg-file-card');\n            if (nodeElem.tagName === 'DIV' && isKgFileCard) {\n                return {\n                    conversion(domNode) {\n                        const link = domNode.querySelector('a');\n                        const src = link.getAttribute('href');\n                        const fileTitle = domNode.querySelector('.kg-file-card-title')?.textContent || '';\n                        const fileCaption = domNode.querySelector('.kg-file-card-caption')?.textContent || '';\n                        const fileName = domNode.querySelector('.kg-file-card-filename')?.textContent || '';\n                        let fileSize = sizeToBytes(domNode.querySelector('.kg-file-card-filesize')?.textContent || '');\n                        const payload = {\n                            src,\n                            fileTitle,\n                            fileCaption,\n                            fileName,\n                            fileSize\n                        };\n\n                        const node = new FileNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderFileNode} from './file-renderer';\nimport {parseFileNode} from './file-parser';\nimport {bytesToSize} from '../../utils/size-byte-converter';\n\nexport class FileNode extends generateDecoratorNode({\n    nodeType: 'file',\n    properties: [\n        {name: 'src', default: '', urlType: 'url'},\n        {name: 'fileTitle', default: '', wordCount: true},\n        {name: 'fileCaption', default: '', wordCount: true},\n        {name: 'fileName', default: ''},\n        {name: 'fileSize', default: ''}\n    ],\n    defaultRenderFn: renderFileNode\n}) {\n    /* @override */\n    exportJSON() {\n        const {src, fileTitle, fileCaption, fileName, fileSize} = this;\n        const isBlob = src && src.startsWith('data:');\n\n        return {\n            type: 'file',\n            src: isBlob ? '<base64String>' : src,\n            fileTitle,\n            fileCaption,\n            fileName,\n            fileSize\n        };\n    }\n\n    static importDOM() {\n        return parseFileNode(this);\n    }\n\n    get formattedFileSize() {\n        return bytesToSize(this.fileSize);\n    }\n}\n\nexport function $isFileNode(node) {\n    return node instanceof FileNode;\n}\n\nexport const $createFileNode = (dataset) => {\n    return new FileNode(dataset);\n};\n","export function slugify(str) {\n    // Remove HTML tags\n    str = str.replace(/<[^>]*>?/gm, '');\n\n    // Remove any non-word character with whitespace\n    str = str.replace(/[^\\w\\s]/gi, '');\n\n    // Replace any whitespace character with a dash\n    str = str.replace(/\\s+/g, '-');\n\n    // Convert to lowercase\n    str = str.toLowerCase();\n\n    return str;\n}\n","import {addCreateDocumentOption} from '../../../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../../../utils/render-empty-container';\nimport {slugify} from '../../../../utils/slugify';\n\nexport function renderHeaderNodeV1(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n\n    if (!node.header && !node.subheader && (!node.buttonEnabled || (!node.buttonUrl || !node.buttonText))) {\n        return renderEmptyContainer(document);\n    }\n\n    const templateData = {\n        size: node.size,\n        style: node.style,\n        buttonEnabled: node.buttonEnabled && Boolean(node.buttonUrl) && Boolean(node.buttonText),\n        buttonUrl: node.buttonUrl,\n        buttonText: node.buttonText,\n        header: node.header,\n        headerSlug: slugify(node.header),\n        subheader: node.subheader,\n        subheaderSlug: slugify(node.subheader),\n        hasHeader: !!node.header,\n        hasSubheader: !!node.subheader && !!node.subheader.replace(/(<br>)+$/g).trim(),\n        backgroundImageStyle: node.style === 'image' ? `background-image: url(${node.backgroundImageSrc})` : '',\n        backgroundImageSrc: node.backgroundImageSrc\n    };\n\n    const div = document.createElement('div');\n    div.classList.add('kg-card', 'kg-header-card', 'kg-width-full', `kg-size-${templateData.size}`, `kg-style-${templateData.style}`);\n    div.setAttribute('data-kg-background-image', templateData.backgroundImageSrc);\n    div.setAttribute('style', templateData.backgroundImageStyle);\n\n    if (templateData.hasHeader) {\n        const headerElement = document.createElement('h2');\n        headerElement.classList.add('kg-header-card-header');\n        headerElement.setAttribute('id', templateData.headerSlug);\n        headerElement.innerHTML = templateData.header;\n        div.appendChild(headerElement);\n    }\n\n    if (templateData.hasSubheader) {\n        const subheaderElement = document.createElement('h3');\n        subheaderElement.classList.add('kg-header-card-subheader');\n        subheaderElement.setAttribute('id', templateData.subheaderSlug);\n        subheaderElement.innerHTML = templateData.subheader;\n        div.appendChild(subheaderElement);\n    }\n\n    if (templateData.buttonEnabled) {\n        const buttonElement = document.createElement('a');\n        buttonElement.classList.add('kg-header-card-button');\n        buttonElement.setAttribute('href', templateData.buttonUrl);\n        buttonElement.textContent = templateData.buttonText;\n        div.appendChild(buttonElement);\n    }\n\n    return {element: div};\n}\n","export function parseHeaderNode(HeaderNode) {\n    return {\n        div: (nodeElem) => {\n            const isHeaderCardv1 = nodeElem.classList?.contains('kg-header-card') && !nodeElem.classList?.contains('kg-v2');\n            const isHeaderCardv2 = nodeElem.classList?.contains('kg-header-card') && nodeElem.classList?.contains('kg-v2');\n            // v1 parser\n            if (nodeElem.tagName === 'DIV' && isHeaderCardv1) {\n                return {\n                    conversion(domNode) {\n                        const div = domNode;\n                        const headerElement = domNode.querySelector('.kg-header-card-header');\n                        const subheaderElement = domNode.querySelector('.kg-header-card-subheader');\n                        const buttonElement = domNode.querySelector('.kg-header-card-button');\n                        const size = div.classList.contains('kg-size-large') ? 'large' : 'small';\n                        const style = div.classList.contains('kg-style-image') ? 'image' : 'text';\n                        const backgroundImageSrc = div.getAttribute('data-kg-background-image');\n                        const hasHeader = !!headerElement;\n                        const header = hasHeader ? headerElement.textContent : '';\n                        const hasSubheader = !!subheaderElement;\n                        const subheader = hasSubheader ? subheaderElement.textContent : '';\n                        const buttonEnabled = !!buttonElement;\n                        const buttonUrl = buttonEnabled ? buttonElement.getAttribute('href') : '';\n                        const buttonText = buttonEnabled ? buttonElement.textContent : '';\n\n                        const payload = {\n                            size,\n                            style,\n                            backgroundImageSrc,\n                            header,\n                            subheader,\n                            buttonEnabled,\n                            buttonUrl,\n                            buttonText,\n                            version: 1\n                        };\n\n                        const node = new HeaderNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n\n            // V2 parser\n            if (nodeElem.tagName === 'DIV' && isHeaderCardv2) {\n                return {\n                    conversion(domNode) {\n                        const div = domNode;\n                        const headerElement = div.querySelector('.kg-header-card-heading');\n                        const subheaderElement = div.querySelector('.kg-header-card-subheading');\n                        const buttonElement = div.querySelector('.kg-header-card-button');\n                        const alignment = div.classList.contains('kg-align-center') ? 'center' : '';\n                        const backgroundImageSrc = div.querySelector('.kg-header-card-image')?.getAttribute('src');\n                        const layout = backgroundImageSrc ? 'split' : '';\n                        const backgroundColor = div.classList.contains('kg-style-accent') ? 'accent' : div.getAttribute('data-background-color');\n                        const buttonColor = buttonElement?.getAttribute('data-button-color') || '';\n                        const textColor = headerElement?.getAttribute('data-text-color') || '';\n                        const buttonTextColor = buttonElement?.getAttribute('data-button-text-color') || '';\n                        const header = headerElement?.textContent || '';\n                        const subheader = subheaderElement?.textContent || '';\n                        const buttonEnabled = !!buttonElement;\n                        const buttonUrl = buttonEnabled ? buttonElement.getAttribute('href') : '';\n                        const buttonText = buttonEnabled ? buttonElement.textContent : '';\n\n                        const payload = {\n                            backgroundColor,\n                            buttonColor,\n                            alignment,\n                            backgroundImageSrc,\n                            layout,\n                            textColor,\n                            header,\n                            subheader,\n                            buttonEnabled,\n                            buttonUrl,\n                            buttonText,\n                            buttonTextColor,\n                            version: 2\n                        };\n\n                        const node = new HeaderNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","import {addCreateDocumentOption} from '../../../../utils/add-create-document-option';\nimport {slugify} from '../../../../utils/slugify';\nimport {getSrcsetAttribute} from '../../../../utils/srcset-attribute';\n\nfunction cardTemplate(nodeData, options = {}) {\n    const cardClasses = getCardClasses(nodeData).join(' ');\n\n    const backgroundAccent = nodeData.backgroundColor === 'accent' ? 'kg-style-accent' : '';\n    const buttonAccent = nodeData.buttonColor === 'accent' ? 'kg-style-accent' : '';\n    const buttonStyle = nodeData.buttonColor !== 'accent' ? `background-color: ${nodeData.buttonColor};` : ``;\n    const alignment = nodeData.alignment === 'center' ? 'kg-align-center' : '';\n    const backgroundImageStyle = nodeData.backgroundColor !== 'accent' && (!nodeData.backgroundImageSrc || nodeData.layout === 'split') ? `background-color: ${nodeData.backgroundColor}` : '';\n\n    let imgTemplate = '';\n    if (nodeData.backgroundImageSrc) {\n        const bgImage = {\n            src: nodeData.backgroundImageSrc,\n            width: nodeData.backgroundImageWidth,\n            height: nodeData.backgroundImageHeight\n        };\n\n        const srcsetValue = getSrcsetAttribute({...bgImage, options});\n        const srcset = srcsetValue ? `srcset=\"${srcsetValue}\"` : '';\n\n        imgTemplate = `\n            <picture><img class=\"kg-header-card-image\" src=\"${bgImage.src}\" ${srcset} loading=\"lazy\" alt=\"\" /></picture>\n        `;\n    }\n\n    const header = () => {\n        if (nodeData.header) {\n            return `<h2 id=\"${slugify(nodeData.header)}\" class=\"kg-header-card-heading\" style=\"color: ${nodeData.textColor};\" data-text-color=\"${nodeData.textColor}\">${nodeData.header}</h2>`;\n        }\n        return '';\n    };\n\n    const subheader = () => {\n        if (nodeData.subheader) {\n            return `<p id=\"${slugify(nodeData.subheader)}\" class=\"kg-header-card-subheading\" style=\"color: ${nodeData.textColor};\" data-text-color=\"${nodeData.textColor}\">${nodeData.subheader}</p>`;\n        }\n        return '';\n    };\n\n    const button = () => {\n        if (nodeData.buttonEnabled && nodeData.buttonUrl && nodeData.buttonUrl.trim() !== '') {\n            return `<a href=\"${nodeData.buttonUrl}\" class=\"kg-header-card-button ${buttonAccent}\" style=\"${buttonStyle}color: ${nodeData.buttonTextColor};\" data-button-color=\"${nodeData.buttonColor}\" data-button-text-color=\"${nodeData.buttonTextColor}\">${nodeData.buttonText}</a>`;\n        }\n        return '';\n    };\n\n    const wrapperStyle = backgroundImageStyle ? `style=\"${backgroundImageStyle};\"` : '';\n\n    return `\n        <div class=\"${cardClasses} ${backgroundAccent}\" ${wrapperStyle} data-background-color=\"${nodeData.backgroundColor}\">\n            ${nodeData.layout !== 'split' ? imgTemplate : ''}\n            <div class=\"kg-header-card-content\">\n                ${nodeData.layout === 'split' ? imgTemplate : ''}\n                <div class=\"kg-header-card-text ${alignment}\">\n                    ${header()}\n                    ${subheader()}\n                    ${button()}\n                </div>\n            </div>\n        </div>\n        `;\n}\n\nfunction emailTemplate(nodeData, options) {\n    const backgroundAccent = nodeData.backgroundColor === 'accent' ? `background-color: ${nodeData.accentColor};` : '';\n    let buttonAccent = nodeData.buttonColor === 'accent' ? `background-color: ${nodeData.accentColor};` : nodeData.buttonColor;\n    let buttonStyle = nodeData.buttonColor !== 'accent' ? `background-color: ${nodeData.buttonColor};` : '';\n    let buttonTextColor = nodeData.buttonTextColor;\n    const alignment = nodeData.alignment === 'center' ? 'text-align: center;' : '';\n    const backgroundImageStyle = nodeData.backgroundImageSrc ? (nodeData.layout !== 'split' ? `background-image: url(${nodeData.backgroundImageSrc}); background-size: cover; background-position: center center;` : `background-color: ${nodeData.backgroundColor};`) : `background-color: ${nodeData.backgroundColor};`;\n    const splitImageStyle = `background-image: url(${nodeData.backgroundImageSrc}); background-size: ${nodeData.backgroundSize !== 'contain' ? 'cover' : '50%'}; background-position: center`;\n\n    if (\n        (options?.feature?.emailCustomization || options?.feature?.emailCustomizationAlpha) &&\n        options?.design?.buttonStyle === 'outline'\n    ) {\n        if (nodeData.buttonColor === 'accent') {\n            buttonAccent = '';\n            buttonStyle = `\n                border: 1px solid ${nodeData.accentColor};\n                background-color: transparent;\n                color: ${nodeData.accentColor} !important;\n            `;\n            buttonTextColor = nodeData.accentColor;\n        } else {\n            buttonStyle = `\n                border: 1px solid ${nodeData.buttonColor};\n                background-color: transparent;\n                color: ${nodeData.buttonColor} !important;\n            `;\n            buttonTextColor = nodeData.buttonColor;\n        }\n    }\n\n    if (options?.feature?.emailCustomization || options?.feature?.emailCustomizationAlpha) {\n        return (\n            `\n            <div class=\"kg-header-card kg-v2\" style=\"color:${nodeData.textColor}; ${alignment} ${backgroundImageStyle} ${backgroundAccent}\">\n                ${nodeData.layout === 'split' && nodeData.backgroundImageSrc ? `\n                    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                        <tr>\n                            <td background=\"${nodeData.backgroundImageSrc}\" style=\"${splitImageStyle}\" class=\"kg-header-card-image\"></td>\n                        </tr>\n                    </table>\n                ` : ''}\n                <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"color:${nodeData.textColor}; ${alignment} ${backgroundImageStyle} ${backgroundAccent}\">\n                    <tr>\n                        <td class=\"kg-header-card-content\" style=\"${nodeData.layout === 'split' && nodeData.backgroundSize === 'contain' ? 'padding-top: 0;' : ''}\">\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                <tr>\n                                    <td align=\"${nodeData.alignment}\">\n                                        <h2 class=\"kg-header-card-heading\" style=\"color:${nodeData.textColor};\">${nodeData.header}</h2>\n                                    </td>\n                                </tr>\n                                <tr>\n                                    <td class=\"kg-header-card-subheading-wrapper\" align=\"${nodeData.alignment}\">\n                                        <p class=\"kg-header-card-subheading\" style=\"color:${nodeData.textColor};\">${nodeData.subheader}</p>\n                                    </td>\n                                </tr>\n                                <tr>\n                                    ${nodeData.buttonEnabled && nodeData.buttonUrl && nodeData.buttonUrl.trim() !== '' ? `\n                                        <td class=\"kg-header-button-wrapper\">\n                                            <table class=\"btn\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"${nodeData.alignment}\">\n                                                <tr>\n                                                    <td align=\"center\" style=\"${buttonStyle} ${buttonAccent}\">\n                                                        <a href=\"${nodeData.buttonUrl}\" style=\"color: ${buttonTextColor};\">${nodeData.buttonText}</a>\n                                                    </td>\n                                                </tr>\n                                            </table>\n                                        </td>\n                                    ` : ''}\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                </table>\n            </div>\n            `\n        );\n    }\n\n    return (\n        `\n        <div class=\"kg-header-card kg-v2\" style=\"color:${nodeData.textColor}; ${alignment} ${backgroundImageStyle} ${backgroundAccent}\">\n            ${nodeData.layout === 'split' && nodeData.backgroundImageSrc ? `\n                <div class=\"kg-header-card-image\" background=\"${nodeData.backgroundImageSrc}\" style=\"${splitImageStyle}\"></div>\n            ` : ''}\n            <div class=\"kg-header-card-content\" style=\"${nodeData.layout === 'split' && nodeData.backgroundSize === 'contain' ? 'padding-top: 0;' : ''}\">\n                <h2 class=\"kg-header-card-heading\" style=\"color:${nodeData.textColor};\">${nodeData.header}</h2>\n                <p class=\"kg-header-card-subheading\" style=\"color:${nodeData.textColor};\">${nodeData.subheader}</p>\n                ${nodeData.buttonEnabled && nodeData.buttonUrl && nodeData.buttonUrl.trim() !== '' ? `\n                    <a class=\"kg-header-card-button\" href=\"${nodeData.buttonUrl}\" style=\"color: ${nodeData.buttonTextColor}; ${buttonStyle} ${buttonAccent}\">${nodeData.buttonText}</a>\n                ` : ''}\n            </div>\n        </div>\n        `\n    );\n}\n\nexport function renderHeaderNodeV2(dataset, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const node = {\n        alignment: dataset.__alignment,\n        buttonText: dataset.__buttonText,\n        buttonEnabled: dataset.__buttonEnabled,\n        buttonUrl: dataset.__buttonUrl,\n        header: dataset.__header,\n        subheader: dataset.__subheader,\n        backgroundImageSrc: dataset.__backgroundImageSrc,\n        backgroundImageWidth: dataset.__backgroundImageWidth,\n        backgroundImageHeight: dataset.__backgroundImageHeight,\n        backgroundSize: dataset.__backgroundSize,\n        backgroundColor: dataset.__backgroundColor,\n        buttonColor: dataset.__buttonColor,\n        layout: dataset.__layout,\n        textColor: dataset.__textColor,\n        buttonTextColor: dataset.__buttonTextColor,\n        swapped: dataset.__swapped,\n        accentColor: dataset.__accentColor\n    };\n\n    if (options.target === 'email') {\n        const emailDoc = options.createDocument();\n        const emailDiv = emailDoc.createElement('div');\n\n        emailDiv.innerHTML = emailTemplate(node, options)?.trim();\n\n        return {element: emailDiv.firstElementChild};\n    }\n\n    const htmlString = cardTemplate(node, options);\n\n    const element = document.createElement('div');\n    element.innerHTML = htmlString?.trim();\n\n    if (node.header === '') {\n        const h2Element = element.querySelector('.kg-header-card-heading');\n        if (h2Element) {\n            h2Element.remove();\n        }\n    }\n\n    if (node.subheader === '') {\n        const pElement = element.querySelector('.kg-header-card-subheading');\n        if (pElement) {\n            pElement.remove();\n        }\n    }\n\n    return {element: element.firstElementChild};\n}\n\nexport function getCardClasses(nodeData) {\n    let cardClasses = ['kg-card kg-header-card kg-v2'];\n\n    if (nodeData.layout && nodeData.layout !== 'split') {\n        cardClasses.push(`kg-width-${nodeData.layout}`);\n    }\n\n    if (nodeData.layout === 'split') {\n        cardClasses.push('kg-layout-split kg-width-full');\n    }\n\n    if (nodeData.swapped && nodeData.layout === 'split') {\n        cardClasses.push('kg-swapped');\n    }\n\n    if (nodeData.layout && nodeData.layout === 'full') {\n        cardClasses.push(`kg-content-wide`);\n    }\n\n    if (nodeData.layout === 'split') {\n        if (nodeData.backgroundSize === 'contain') {\n            cardClasses.push('kg-content-wide');\n        }\n    }\n\n    return cardClasses;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderHeaderNodeV1} from './renderers/v1/header-renderer';\nimport {parseHeaderNode} from './parsers/header-parser';\n// V2 imports below\nimport {renderHeaderNodeV2} from './renderers/v2/header-renderer';\n\n// This is our first node that has a custom version property\nexport class HeaderNode extends generateDecoratorNode({\n    nodeType: 'header',\n    properties: [\n        {name: 'size', default: 'small'},\n        {name: 'style', default: 'dark'},\n        {name: 'buttonEnabled', default: false},\n        {name: 'buttonUrl', default: '', urlType: 'url'},\n        {name: 'buttonText', default: ''},\n        {name: 'header', default: '', urlType: 'html', wordCount: true},\n        {name: 'subheader', default: '', urlType: 'html', wordCount: true},\n        {name: 'backgroundImageSrc', default: '', urlType: 'url'},\n        // we need to initialize a new version property here so that we can separate v1 and v2\n        // we should never remove old properties, only add new ones, as this could break & corrupt existing content\n        // ref https://lexical.dev/docs/concepts/serialization#versioning--breaking-changes\n        {name: 'version', default: 1},\n        {name: 'accentColor', default: '#FF1A75'}, // this is used to have the accent color hex for email\n        // v2 properties\n        {name: 'alignment', default: 'center'},\n        {name: 'backgroundColor', default: '#000000'},\n        {name: 'backgroundImageWidth', default: null},\n        {name: 'backgroundImageHeight', default: null},\n        {name: 'backgroundSize', default: 'cover'},\n        {name: 'textColor', default: '#FFFFFF'},\n        {name: 'buttonColor', default: '#ffffff'},\n        {name: 'buttonTextColor', default: '#000000'},\n        {name: 'layout', default: 'full'}, // replaces size\n        {name: 'swapped', default: false}\n    ],\n    defaultRenderFn: {\n        1: renderHeaderNodeV1,\n        2: renderHeaderNodeV2\n    }\n}) {\n    static importDOM() {\n        return parseHeaderNode(this);\n    }\n}\n\nexport const $createHeaderNode = (dataset) => {\n    return new HeaderNode(dataset);\n};\n\nexport function $isHeaderNode(node) {\n    return node instanceof HeaderNode;\n}\n","export function parsePaywallNode(PaywallNode) {\n    return {\n        '#comment': (nodeElem) => {\n            if (nodeElem.nodeType === 8 && nodeElem.nodeValue.trim() === 'members-only') {\n                return {\n                    conversion() {\n                        const node = new PaywallNode();\n                        return {node};\n                    },\n                    priority: 0\n                };\n            }\n            return null;\n        }\n    };\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\n\nexport function renderPaywallNode(_, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n    const element = document.createElement('div');\n\n    element.innerHTML = '<!--members-only-->';\n\n    // `type: 'inner'` will render only the innerHTML of the element\n    // @see @tryghost/kg-lexical-html-renderer package\n    return {element, type: 'inner'};\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parsePaywallNode} from './paywall-parser';\nimport {renderPaywallNode} from './paywall-renderer';\n\nexport class PaywallNode extends generateDecoratorNode({\n    nodeType: 'paywall',\n    defaultRenderFn: renderPaywallNode\n}) {\n    static importDOM() {\n        return parsePaywallNode(this);\n    }\n}\n\nexport const $createPaywallNode = (dataset) => {\n    return new PaywallNode(dataset);\n};\n\nexport function $isPaywallNode(node) {\n    return node instanceof PaywallNode;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element';\n\nexport function parseProductNode(ProductNode) {\n    return {\n        div: (nodeElem) => {\n            const isKgProductCard = nodeElem.classList?.contains('kg-product-card');\n            if (nodeElem.tagName === 'DIV' && isKgProductCard) {\n                return {\n                    conversion(domNode) {\n                        const title = readCaptionFromElement(domNode, {selector: '.kg-product-card-title'});\n                        const description = readCaptionFromElement(domNode, {selector: '.kg-product-card-description'});\n\n                        const payload = {\n                            productButtonEnabled: false,\n                            productRatingEnabled: false,\n                            productTitle: title,\n                            productDescription: description\n                        };\n\n                        const img = domNode.querySelector('.kg-product-card-image');\n                        if (img && img.getAttribute('src')) {\n                            payload.productImageSrc = img.getAttribute('src');\n\n                            if (img.getAttribute('width')) {\n                                payload.productImageWidth = img.getAttribute('width');\n                            }\n\n                            if (img.getAttribute('height')) {\n                                payload.productImageHeight = img.getAttribute('height');\n                            }\n                        }\n\n                        const stars = [...domNode.querySelectorAll('.kg-product-card-rating-active')].length;\n                        if (stars) {\n                            payload.productRatingEnabled = true;\n                            payload.productStarRating = stars;\n                        }\n\n                        const button = domNode.querySelector('a');\n\n                        if (button) {\n                            const buttonUrl = button.getAttribute('href');\n                            const buttonText = getButtonText(button);\n\n                            if (buttonUrl && buttonText) {\n                                payload.productButtonEnabled = true;\n                                payload.productButton = buttonText;\n                                payload.productUrl = buttonUrl;\n                            }\n                        }\n\n                        if (!title && !description && !img && !button) {\n                            return null;\n                        }\n\n                        const node = new ProductNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n\nfunction getButtonText(node) {\n    let buttonText = node.textContent;\n    if (buttonText) {\n        buttonText = buttonText.replace(/\\n/g, ' ').replace(/\\s+/g, ' ').trim();\n    }\n    return buttonText;\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport {getResizedImageDimensions} from '../../utils/get-resized-image-dimensions';\n\nexport function renderProductNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    if (node.isEmpty()) {\n        return renderEmptyContainer(document);\n    }\n\n    let buttonBorderRadius = '5px';\n\n    // we're switching to 6px by default as part of settings being added\n    // TODO: remove 'rounded' check and switch default above to 6px\n    if (options.design?.buttonCorners === 'rounded') {\n        buttonBorderRadius = '6px';\n    } else if (options.design?.buttonCorners === 'square') {\n        buttonBorderRadius = '0px';\n    } else if (options.design?.buttonCorners === 'pill') {\n        buttonBorderRadius = '9999px';\n    }\n\n    const templateData = {\n        ...node.getDataset(),\n        starIcon: `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z\"/></svg>`,\n        buttonBorderRadius\n    };\n\n    const starActiveClasses = 'kg-product-card-rating-active';\n    for (let i = 1; i <= 5; i++) {\n        templateData['star' + i] = '';\n        if (node.productStarRating >= i) {\n            templateData['star' + i] = starActiveClasses;\n        }\n    }\n\n    const htmlString = options.target === 'email'\n        ? emailCardTemplate({data: templateData, feature: options.feature})\n        : cardTemplate({data: templateData, feature: options.feature});\n\n    const element = document.createElement('div');\n    element.innerHTML = htmlString.trim();\n\n    return {element: element.firstElementChild};\n}\n\nexport function cardTemplate({data}) {\n    return (\n        `\n        <div class=\"kg-card kg-product-card\">\n            <div class=\"kg-product-card-container\">\n                ${data.productImageSrc ? `<img src=\"${data.productImageSrc}\" ${data.productImageWidth ? `width=\"${data.productImageWidth}\"` : ''} ${data.productImageHeight ? `height=\"${data.productImageHeight}\"` : ''} class=\"kg-product-card-image\" loading=\"lazy\" />` : ''}\n                <div class=\"kg-product-card-title-container\">\n                    <h4 class=\"kg-product-card-title\">${data.productTitle}</h4>\n                </div>\n                ${data.productRatingEnabled ? `\n                    <div class=\"kg-product-card-rating\">\n                        <span class=\"${data.star1} kg-product-card-rating-star\">${data.starIcon}</span>\n                        <span class=\"${data.star2} kg-product-card-rating-star\">${data.starIcon}</span>\n                        <span class=\"${data.star3} kg-product-card-rating-star\">${data.starIcon}</span>\n                        <span class=\"${data.star4} kg-product-card-rating-star\">${data.starIcon}</span>\n                        <span class=\"${data.star5} kg-product-card-rating-star\">${data.starIcon}</span>\n                    </div>\n                ` : ''}\n\n                <div class=\"kg-product-card-description\">${data.productDescription}</div>\n                ${data.productButtonEnabled ? `\n                    <a href=\"${data.productUrl}\" class=\"kg-product-card-button kg-product-card-btn-accent\" target=\"_blank\" rel=\"noopener noreferrer\"><span>${data.productButton}</span></a>\n                ` : ''}\n            </div>\n        </div>\n    `\n    );\n}\n\nexport function emailCardTemplate({data, feature}) {\n    let imageDimensions;\n\n    if (data.productImageWidth && data.productImageHeight) {\n        imageDimensions = {\n            width: data.productImageWidth,\n            height: data.productImageHeight\n        };\n\n        if (data.productImageWidth >= 560) {\n            imageDimensions = getResizedImageDimensions(imageDimensions, {width: 560});\n        }\n    }\n\n    if (feature?.emailCustomization || feature?.emailCustomizationAlpha) {\n        return (\n            `\n            <table class=\"kg-product-card\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n                <tr>\n                    <td class=\"kg-product-card-container\">\n                        <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n                            ${data.productImageSrc ? `\n                                <tr>\n                                    <td class=\"kg-product-image\" align=\"center\">\n                                        <img src=\"${data.productImageSrc}\" ${imageDimensions ? `width=\"${imageDimensions.width}\"` : ''} ${imageDimensions ? `height=\"${imageDimensions.height}\"` : ''} border=\"0\"/>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                            <tr>\n                                <td valign=\"top\">\n                                    <h4 class=\"kg-product-title\">${data.productTitle}</h4>\n                                </td>\n                            </tr>\n                            ${data.productRatingEnabled ? `\n                                <tr class=\"kg-product-rating\">\n                                    <td valign=\"top\">\n                                        <img src=\"${`https://static.ghost.org/v4.0.0/images/star-rating-${data.productStarRating}.png`}\" border=\"0\" />\n                                    </td>\n                                </tr>\n                            ` : ''}\n                            <tr>\n                                <td class=\"kg-product-description-wrapper\">${data.productDescription}</td>\n                            </tr>\n                            ${data.productButtonEnabled ? `\n                                <tr>\n                                    <td class=\"kg-product-button-wrapper\">\n                                        <table class=\"btn btn-accent\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n                                            <tr>\n                                                <td align=\"center\" width=\"100%\">\n                                                    <a href=\"${data.productUrl}\">${data.productButton}</a>\n                                                </td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            ` : ''}\n                        </table>\n                    </td>\n                </tr>\n            </table>\n            `\n        );\n    }\n\n    return (\n        `\n         <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"width:100%; padding:20px; border:1px solid #E9E9E9; border-radius: 5px; margin: 0 0 1.5em; width: 100%;\">\n            ${data.productImageSrc ? `\n                <tr>\n                    <td align=\"center\" style=\"padding-top:0; padding-bottom:0; margin-bottom:0; padding-bottom:0;\">\n                        <img src=\"${data.productImageSrc}\" ${imageDimensions ? `width=\"${imageDimensions.width}\"` : ''} ${imageDimensions ? `height=\"${imageDimensions.height}\"` : ''} style=\"display: block; width: 100%; height: auto; max-width: 100%; border: none; padding-bottom: 16px;\" border=\"0\"/>\n                    </td>\n                </tr>\n            ` : ''}\n            <tr>\n                <td valign=\"top\">\n                    <h4 style=\"font-size: 22px !important; margin-top: 0 !important; margin-bottom: 0 !important; font-weight: 700;\">${data.productTitle}</h4>\n                </td>\n            </tr>\n            ${data.productRatingEnabled ? `\n                <tr style=\"padding-top:0; padding-bottom:0; margin-bottom:0; padding-bottom:0;\">\n                    <td valign=\"top\">\n                        <img src=\"${`https://static.ghost.org/v4.0.0/images/star-rating-${data.productStarRating}.png`}\" style=\"border: none; width: 96px;\" border=\"0\" />\n                    </td>\n                </tr>\n            ` : ''}\n            <tr>\n                <td style=\"padding-top:0; padding-bottom:0; margin-bottom:0; padding-bottom:0;\">\n                    <div style=\"padding-top: 8px; opacity: 0.7; font-size: 17px; line-height: 1.4; margin-bottom: -24px;\">${data.productDescription}</div>\n                </td>\n            </tr>\n            ${data.productButtonEnabled ? `\n                <tr>\n                    <td style=\"padding-top:0; padding-bottom:0; margin-bottom:0; padding-bottom:0;\">\n                        <div class=\"btn btn-accent\" style=\"box-sizing: border-box;display: table;width: 100%;padding-top: 16px;\">\n                            <a href=\"${data.productUrl}\" style=\"overflow-wrap: anywhere;border: solid 1px;border-radius: ${data.buttonBorderRadius};box-sizing: border-box;cursor: pointer;display: inline-block;font-size: 14px;font-weight: bold;margin: 0;padding: 0;text-decoration: none;color: #FFFFFF; width: 100%; text-align: center;\"><span style=\"display: block;padding: 12px 25px;\">${data.productButton}</span></a>\n                        </div>\n                    </td>\n                </tr>\n            ` : ''}\n        </table>\n        `\n    );\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseProductNode} from './product-parser';\nimport {renderProductNode} from './product-renderer';\n\nexport class ProductNode extends generateDecoratorNode({\n    nodeType: 'product',\n    properties: [\n        {name: 'productImageSrc', default: '', urlType: 'url'},\n        {name: 'productImageWidth', default: null},\n        {name: 'productImageHeight', default: null},\n        {name: 'productTitle', default: '', urlType: 'html', wordCount: true},\n        {name: 'productDescription', default: '', urlType: 'html', wordCount: true},\n        {name: 'productRatingEnabled', default: false},\n        {name: 'productStarRating', default: 5},\n        {name: 'productButtonEnabled', default: false},\n        {name: 'productButton', default: ''},\n        {name: 'productUrl', default: ''}\n    ],\n    defaultRenderFn: renderProductNode\n}) {\n    /* override */\n    exportJSON() {\n        // checks if src is a data string\n        const {productImageSrc, productImageWidth, productImageHeight, productTitle, productDescription, productRatingEnabled, productStarRating, productButtonEnabled, productButton, productUrl} = this;\n        const isBlob = productImageSrc && productImageSrc.startsWith('data:');\n\n        const dataset = {\n            type: 'product',\n            version: 1,\n            productImageSrc: isBlob ? '<base64String>' : productImageSrc,\n            productImageWidth,\n            productImageHeight,\n            productTitle,\n            productDescription,\n            productRatingEnabled,\n            productStarRating,\n            productButtonEnabled,\n            productButton,\n            productUrl\n\n        };\n        return dataset;\n    }\n\n    static importDOM() {\n        return parseProductNode(this);\n    }\n\n    isEmpty() {\n        const isButtonFilled = this.__productButtonEnabled && this.__productUrl && this.__productButton;\n        return !this.__productTitle && !this.__productDescription && !isButtonFilled && !this.__productImageSrc && !this.__productRatingEnabled;\n    }\n}\n\nexport const $createProductNode = (dataset) => {\n    return new ProductNode(dataset);\n};\n\nexport function $isProductNode(node) {\n    return node instanceof ProductNode;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element.js';\n\n// TODO: add NFT card parser\nexport function parseEmbedNode(EmbedNode) {\n    return {\n        figure: (nodeElem) => {\n            if (nodeElem.nodeType === 1 && nodeElem.tagName === 'FIGURE') {\n                const iframe = nodeElem.querySelector('iframe');\n                if (iframe) {\n                    return {\n                        conversion(domNode) {\n                            const payload = _createPayloadForIframe(iframe);\n\n                            if (!payload) {\n                                return null;\n                            }\n\n                            payload.caption = readCaptionFromElement(domNode);\n\n                            const node = new EmbedNode(payload);\n                            return {node};\n                        },\n                        priority: 1\n                    };\n                }\n                const blockquote = nodeElem.querySelector('blockquote');\n                if (blockquote) {\n                    return {\n                        conversion(domNode) {\n                            const link = domNode.querySelector('a');\n                            if (!link) {\n                                return null;\n                            }\n\n                            let url = link.getAttribute('href');\n\n                            // If we don't have a url, or it's not an absolute URL, we can't handle this\n                            if (!url || !url.match(/^https?:\\/\\//i)) {\n                                return null;\n                            }\n\n                            let payload = {url: url};\n\n                            // append caption, remove element from blockquote\n                            payload.caption = readCaptionFromElement(domNode);\n                            let figcaption = domNode.querySelector('figcaption');\n                            figcaption?.remove();\n\n                            payload.html = domNode.innerHTML;\n\n                            const node = new EmbedNode(payload);\n                            return {node};\n                        },\n                        priority: 1\n                    };\n                }\n            }\n            return null;\n        },\n        iframe: (nodeElem) => {\n            if (nodeElem.nodeType === 1 && nodeElem.tagName === 'IFRAME') {\n                return {\n                    conversion(domNode) {\n                        const payload = _createPayloadForIframe(domNode);\n\n                        if (!payload) {\n                            return null;\n                        }\n\n                        const node = new EmbedNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n\nfunction _createPayloadForIframe(iframe) {\n    // If we don't have a src Or it's not an absolute URL, we can't handle this\n    // This regex handles http://, https:// or //\n    if (!iframe.src || !iframe.src.match(/^(https?:)?\\/\\//i)) {\n        return;\n    }\n\n    // if it's a schemaless URL, convert to https\n    if (iframe.src.match(/^\\/\\//)) {\n        iframe.src = `https:${iframe.src}`;\n    }\n\n    let payload = {\n        url: iframe.src\n    };\n\n    payload.html = iframe.outerHTML;\n\n    return payload;\n}","import {DateTime} from 'luxon';\nimport toArray from 'lodash/toArray';\n\nexport default function render(node, document, options) {\n    const metadata = node.metadata;\n\n    const figure = document.createElement('figure');\n    figure.setAttribute('class', 'kg-card kg-embed-card');\n\n    let html = node.html;\n\n    const tweetData = metadata && metadata.tweet_data;\n    const isEmail = options.target === 'email';\n\n    if (tweetData && isEmail) {\n        const tweetId = tweetData.id;\n        const numberFormatter = new Intl.NumberFormat('en-US', {\n            style: 'decimal',\n            notation: 'compact',\n            unitDisplay: 'narrow',\n            maximumFractionDigits: 1\n        });\n        const retweetCount = numberFormatter.format(tweetData.public_metrics.retweet_count);\n        const likeCount = numberFormatter.format(tweetData.public_metrics.like_count);\n        const authorUser = tweetData.users && tweetData.users.find(user => user.id === tweetData.author_id);\n        const tweetTime = DateTime.fromISO(tweetData.created_at).toLocaleString(DateTime.TIME_SIMPLE);\n        const tweetDate = DateTime.fromISO(tweetData.created_at).toLocaleString(DateTime.DATE_MED);\n\n        const mentions = tweetData.entities && tweetData.entities.mentions || [];\n        const urls = tweetData.entities && tweetData.entities.urls || [];\n        const hashtags = tweetData.entities && tweetData.entities.hashtags || [];\n        const entities = mentions.concat(urls).concat(hashtags).sort((a, b) => a.start - b.start);\n        let tweetContent = tweetData.text;\n\n        let tweetImageUrl = null;\n        const hasImageOrVideo = tweetData.attachments && tweetData.attachments && tweetData.attachments.media_keys;\n        if (hasImageOrVideo) {\n            tweetImageUrl = tweetData.includes.media[0].preview_image_url || tweetData.includes.media[0].url;\n        }\n        const hasPoll = tweetData.attachments && tweetData.attachments && tweetData.attachments.poll_ids;\n\n        if (mentions) {\n            let last = 0;\n            let parts = [];\n            let content = toArray(tweetContent);\n            for (const entity of entities) {\n                let type = 'text';\n                let data = content.slice(entity.start, entity.end + 1).join('').replace(/\\n/g, '<br>');\n                if (entity.url) {\n                    if (!entity.display_url || entity.display_url.startsWith('pic.twitter.com')) {\n                        type = 'img_url';\n                    } else {\n                        type = 'url';\n                        data = data.replace(entity.url, entity.display_url);\n                    }\n                }\n                if (entity.username) {\n                    type = 'mention';\n                }\n                if (entity.tag) {\n                    type = 'hashtag';\n                }\n                parts.push({\n                    type: 'text',\n                    data: content.slice(last, entity.start).join('').replace(/\\n/g, '<br>')\n                });\n                parts.push({\n                    type: type,\n                    data: data\n                });\n                last = entity.end + 1;\n            }\n            parts.push({\n                type: 'text',\n                data: content.slice(last, content.length).join('').replace(/\\n/g, '<br>')\n            });\n\n            tweetContent = parts.reduce((partContent, part) => {\n                if (part.type === 'text') {\n                    return partContent + part.data;\n                }\n                if (part.type === 'mention') {\n                    return partContent + `<span style=\"color: #1DA1F2;\">${part.data}</span>`;\n                }\n                if (part.type === 'hashtag') {\n                    return partContent + `<span style=\"color: #1DA1F2;\">${part.data}</span>`;\n                }\n                if (part.type === 'url') {\n                    return partContent + `<span style=\"color: #1DA1F2; word-break: break-all;\">${part.data}</span>`;\n                }\n                return partContent;\n            }, '');\n        }\n\n        html = `\n        <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"kg-twitter-card\">\n            <tr>\n                <td>\n                    <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                        ${authorUser ? `\n                            <tr>\n                                ${authorUser.profile_image_url ? `<td width=\"48\" style=\"width: 48px;\">\n                                    <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"padding-left: 16px; padding-top: 16px;\"><img src=\"${authorUser.profile_image_url}\" style=\"max-width: 512px; border: none; width: 48px; height: 48px; border-radius: 999px;\" border=\"0\"></a>\n                                </td>` : ''}\n                                ${authorUser.name ? `\n                                <td style=\"line-height: 1.3em; width: 100%;\">\n                                    <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"font-size: 15px !important; font-weight: 600; width: 100%; padding-top: 20px; padding-bottom: 18px;\">${authorUser.name} <br> <span style=\"color: #ABB4BE; font-size: 14px; font-weight: 500;\">@${authorUser.username}</span></a>\n                                </td>` : ''}\n                                <td align=\"right\" width=\"24\" style=\"width: 24px;\">\n                                    <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"padding-right: 16px; padding-top: 20px; width: 24px; height: 38px;\"><img src=\"https://static.ghost.org/v4.0.0/images/twitter-logo-small.png\" width=\"24\" border=\"0\"></a>\n                                </td>\n                            </tr>\n                        ` : ''}\n                        <tr>\n                            <td colspan=\"3\">\n                                <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"font-size: 15px; line-height: 1.4em; padding-top: 8px; padding-left: 16px; padding-right: 16px; padding-bottom: 16px;\">${tweetContent}\n                                ${hasPoll ? `<br><span style=\"color: #1DA1F2;\">View poll &rarr;</span>` : ''}\n                                </a>\n                            </td>\n                        </tr>\n                        ${hasImageOrVideo ? `<tr>\n                            <td colspan=\"3\" align=\"center\" style=\"width: 100%;\">\n                                <a href=\"https://twitter.com/twitter/status/${tweetId}\" style=\"display: block; padding-top: 0; padding-left: 16px; padding-right: 16px; padding-bottom: 0;\"><img src=\"${tweetImageUrl}\" style=\"width: 100%; border: 1px solid #E9E9E9; max-width: 528px; border-radius: 10px;\" border=\"0\"></a>\n                            </td>\n                        </tr>` : ''}\n                        <tr>\n                            <td colspan=\"3\" style=\"width: 100%;\">\n                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n                                    <tr>\n                                        <td>\n                                        <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"padding-top: 4px; padding-right: 16px; padding-bottom: 12px; padding-left: 16px;\"><span style=\"color: #838383;\">${tweetTime} &bull; ${tweetDate}</span></a>\n                                        </td>\n                                    </tr>\n                                </table>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td colspan=\"3\" style=\"width: 100%;\">\n                                <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\" style=\"border-top: 1px solid #E9E9E9;\">\n                                    <tr>\n                                        <td>\n                                            <a href=\"https://twitter.com/twitter/status/${tweetId}\" class=\"kg-twitter-link\" style=\"padding-top: 12px; padding-right: 16px; padding-bottom: 12px; padding-left: 16px;\">\n                                                <span style=\"font-weight: 600;\">${likeCount}</span> <span style=\"color: #838383;\">likes &bull;</span>\n                                                <span style=\"font-weight: 600;\">${retweetCount}</span> <span style=\"color: #838383;\">retweets</span>\n                                            </a>\n                                        </td>\n                                    </tr>\n                                </table>\n                            </td>\n                        </tr>\n                    </table>\n                </td>\n            </tr>\n        </table>\n        `;\n    }\n\n    figure.innerHTML = html.trim();\n\n    const caption = node.caption;\n    if (caption) {\n        const figcaption = document.createElement('figcaption');\n        figcaption.innerHTML = caption;\n        figure.appendChild(figcaption);\n        figure.setAttribute('class', `${figure.getAttribute('class')} kg-card-hascaption`);\n    }\n\n    return {element: figure};\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\nimport twitterRenderer from './types/twitter';\n\nexport function renderEmbedNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n    const embedType = node.embedType;\n\n    if (embedType === 'twitter') {\n        return twitterRenderer(node, document, options);\n    }\n\n    return renderTemplate(node, document, options);\n}\n\nfunction renderTemplate(node, document, options) {\n    if (node.isEmpty()) {\n        return renderEmptyContainer(document);\n    }\n    const isEmail = options.target === 'email';\n    const metadata = node.metadata;\n    const url = node.url;\n    const isVideoWithThumbnail = node.embedType === 'video' && metadata && metadata.thumbnail_url;\n    const figure = document.createElement('figure');\n    figure.setAttribute('class', 'kg-card kg-embed-card');\n\n    if (isEmail && isVideoWithThumbnail) {\n        const emailTemplateMaxWidth = 600;\n        const thumbnailAspectRatio = metadata.thumbnail_width / metadata.thumbnail_height;\n        const spacerWidth = Math.round(emailTemplateMaxWidth / 4);\n        const spacerHeight = Math.round(emailTemplateMaxWidth / thumbnailAspectRatio);\n        const html = `\n            <!--[if !mso !vml]-->\n            <a class=\"kg-video-preview\" href=\"${url}\" aria-label=\"Play video\" style=\"mso-hide: all\">\n                <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" background=\"${metadata.thumbnail_url}\" role=\"presentation\" style=\"background: url('${metadata.thumbnail_url}') left top / cover; mso-hide: all\">\n                    <tr style=\"mso-hide: all\">\n                        <td width=\"25%\" style=\"visibility: hidden; mso-hide: all\">\n                            <img src=\"https://img.spacergif.org/v1/${spacerWidth}x${spacerHeight}/0a/spacer.png\" alt=\"\" width=\"100%\" border=\"0\" style=\"display:block; height: auto; opacity: 0; visibility: hidden; mso-hide: all;\">\n                        </td>\n                        <td width=\"50%\" align=\"center\" valign=\"middle\" style=\"vertical-align: middle; mso-hide: all;\">\n                            <div class=\"kg-video-play-button\" style=\"mso-hide: all\"><div style=\"mso-hide: all\"></div></div>\n                        </td>\n                        <td width=\"25%\" style=\"mso-hide: all\">&nbsp;</td>\n                    </tr>\n                </table>\n            </a>\n            <!--[endif]-->\n\n            <!--[if vml]>\n            <v:group xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" coordsize=\"${emailTemplateMaxWidth},${spacerHeight}\" coordorigin=\"0,0\" href=\"${url}\" style=\"width:${emailTemplateMaxWidth}px;height:${spacerHeight}px;\">\n                <v:rect fill=\"t\" stroked=\"f\" style=\"position:absolute;width:${emailTemplateMaxWidth};height:${spacerHeight};\"><v:fill src=\"${metadata.thumbnail_url}\" type=\"frame\"/></v:rect>\n                <v:oval fill=\"t\" strokecolor=\"white\" strokeweight=\"4px\" style=\"position:absolute;left:${Math.round((emailTemplateMaxWidth / 2) - 39)};top:${Math.round((spacerHeight / 2) - 39)};width:78;height:78\"><v:fill color=\"black\" opacity=\"30%\" /></v:oval>\n                <v:shape coordsize=\"24,32\" path=\"m,l,32,24,16,xe\" fillcolor=\"white\" stroked=\"f\" style=\"position:absolute;left:${Math.round((emailTemplateMaxWidth / 2) - 11)};top:${Math.round((spacerHeight / 2) - 17)};width:30;height:34;\" />\n            </v:group>\n            <![endif]-->\n        `;\n        figure.innerHTML = html.trim();\n    } else {\n        figure.innerHTML = node.html;\n    }\n\n    const caption = node.caption;\n    if (caption) {\n        const figcaption = document.createElement('figcaption');\n        figcaption.innerHTML = caption;\n        figure.appendChild(figcaption);\n        figure.setAttribute('class', `${figure.getAttribute('class')} kg-card-hascaption`);\n    }\n\n    return {element: figure};\n}","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseEmbedNode} from './embed-parser';\nimport {renderEmbedNode} from './embed-renderer';\n\nexport class EmbedNode extends generateDecoratorNode({\n    nodeType: 'embed',\n    properties: [\n        {name: 'url', default: '', urlType: 'url'},\n        {name: 'embedType', default: ''},\n        {name: 'html', default: ''},\n        {name: 'metadata', default: {}},\n        {name: 'caption', default: '', wordCount: true}\n    ],\n    defaultRenderFn: renderEmbedNode\n}) {\n    static importDOM() {\n        return parseEmbedNode(this);\n    }\n\n    isEmpty() {\n        return !this.__url && !this.__html;\n    }\n}\n\nexport const $createEmbedNode = (dataset) => {\n    return new EmbedNode(dataset);\n};\n\nexport function $isEmbedNode(node) {\n    return node instanceof EmbedNode;\n}\n","/**\n * Removes consecutive whitespaces and newlines\n * @param {string} html\n * @returns {string}\n */\nexport function removeSpaces(html) {\n    return html.replace(/\\n/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Wraps replacement strings with %%\n * This helps to prevent conflicts between code samples and our replacement strings\n * Example: {foo} -> %%{foo}%%\n * @param {string} html\n * @returns {string}\n */\nexport function wrapReplacementStrings(html) {\n    return html.replace(/\\{(\\w*?)(?:,? *\"(.*?)\")?\\}/g, '%%$&%%');\n}\n\n/**\n * Removes any <code> wrappers around replacement strings {foo}\n * Example input:  <code><span>{foo}</span></code>\n * Example output:       <span>{foo}</span>\n * @param {string} html\n * @returns {string}\n */\nexport function removeCodeWrappersFromHelpers(html,document) {\n    // parse html to make patterns easier to match\n    const tempDiv = document.createElement('div');\n    tempDiv.innerHTML = html;\n\n    const codeElements = tempDiv.querySelectorAll('code');\n    codeElements.forEach((codeElement) => {\n        const codeTextContent = codeElement.textContent;\n        // extract the content of the code element if it follows the helper pattern (e.g. {foo})\n        if (codeTextContent.match(/((.*?){.*?}(.*?))/gi)) {\n            const codeContent = codeElement.innerHTML; \n            codeElement.parentNode.replaceChild(document.createRange().createContextualFragment(codeContent), codeElement);\n        }\n    });\n\n    const cleanedHtml = tempDiv.innerHTML;\n    return cleanedHtml;\n}","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {removeSpaces, removeCodeWrappersFromHelpers, wrapReplacementStrings} from '../../utils/replacement-strings';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderEmailNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const html = node.html;\n\n    if (!html || options.target !== 'email') {\n        return renderEmptyContainer(document);\n    }\n\n    const cleanedHtml = wrapReplacementStrings(removeCodeWrappersFromHelpers(removeSpaces(html),document));\n\n    const element = document.createElement('div');\n    element.innerHTML = cleanedHtml;\n\n    // `type: 'inner'` will render only the innerHTML of the element\n    // @see @tryghost/kg-lexical-html-renderer package\n    return {element, type: 'inner'};\n}","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderEmailNode} from './email-renderer';\n\nexport class EmailNode extends generateDecoratorNode({\n    nodeType: 'email',\n    properties: [\n        {name: 'html', default: '', urlType: 'html'}\n    ],\n    defaultRenderFn: renderEmailNode\n}) {\n}\n\nexport const $createEmailNode = (dataset) => {\n    return new EmailNode(dataset);\n};\n\nexport function $isEmailNode(node) {\n    return node instanceof EmailNode;\n}\n","import {readCaptionFromElement} from '../../utils/read-caption-from-element.js';\nimport {readImageAttributesFromElement} from '../../utils/read-image-attributes-from-element.js';\n\nfunction readGalleryImageAttributesFromElement(element, imgNum) {\n    const image = readImageAttributesFromElement(element);\n\n    image.fileName = element.src.match(/[^/]*$/)[0];\n    image.row = Math.floor(imgNum / 3);\n\n    return image;\n}\n\nexport function parseGalleryNode(GalleryNode) {\n    return {\n        figure: (nodeElem) => {\n            // Koenig gallery card\n            if (nodeElem.classList?.contains('kg-gallery-card')) {\n                return {\n                    conversion(domNode) {\n                        const payload = {};\n                        const imgs = Array.from(domNode.querySelectorAll('img'));\n\n                        payload.images = imgs.map(readGalleryImageAttributesFromElement);\n                        payload.caption = readCaptionFromElement(domNode);\n\n                        const node = new GalleryNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n\n            return null;\n        },\n        div: (nodeElem) => {\n            // Medium \"graf\" galleries\n            function isGrafGallery(node) {\n                return node.tagName === 'DIV'\n                        && node.dataset?.paragraphCount\n                        && node.querySelectorAll('img').length > 0;\n            }\n\n            if (isGrafGallery(nodeElem)) {\n                return {\n                    conversion(domNode) {\n                        const payload = {\n                            caption: readCaptionFromElement(domNode)\n                        };\n\n                        // These galleries exist as a series of divs containing multiple figure+img.\n                        // Grab the first set of imgs...\n                        let imgs = Array.from(domNode.querySelectorAll('img'));\n\n                        // ...and then iterate over any remaining divs until we run out of matches\n                        let nextNode = domNode.nextElementSibling;\n                        while (nextNode && isGrafGallery(nextNode)) {\n                            let currentNode = nextNode;\n                            imgs = imgs.concat(Array.from(currentNode.querySelectorAll('img')));\n\n                            const currentNodeCaption = readCaptionFromElement(currentNode);\n                            if (currentNodeCaption) {\n                                payload.caption = `${payload.caption} / ${currentNodeCaption}`;\n                            }\n\n                            nextNode = currentNode.nextElementSibling;\n\n                            // remove nodes as we go so that they don't go through the parser\n                            currentNode.remove();\n                        }\n\n                        payload.images = imgs.map(readGalleryImageAttributesFromElement);\n\n                        const node = new GalleryNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n\n            // Squarespace SQS galleries\n            function isSqsGallery(node) {\n                return node.tagName === 'DIV'\n                        && node.className.match(/sqs-gallery-container/)\n                        && !node.className.match(/summary-/);\n            }\n\n            if (isSqsGallery(nodeElem)) {\n                return {\n                    conversion(domNode) {\n                        const payload = {};\n\n                        // Each image exists twice...\n                        // The first image is wrapped in `<noscript>`\n                        // The second image contains image dimensions but the src property needs to be taken from `data-src`.\n                        let imgs = Array.from(domNode.querySelectorAll('img.thumb-image'));\n\n                        imgs = imgs.map((img) => {\n                            if (!img.getAttribute('src')) {\n                                if (img.previousElementSibling.tagName === 'NOSCRIPT' && img.previousElementSibling.getElementsByTagName('img').length) {\n                                    const prevNode = img.previousElementSibling;\n                                    img.setAttribute('src', img.getAttribute('data-src'));\n                                    prevNode.remove();\n                                } else {\n                                    return undefined;\n                                }\n                            }\n\n                            return img;\n                        }).filter(img => img !== undefined);\n\n                        // Process nodes into the payload\n                        payload.images = imgs.map(readGalleryImageAttributesFromElement);\n\n                        payload.caption = readCaptionFromElement(domNode, {selector: '.meta-title'});\n\n                        const node = new GalleryNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n\n            return null;\n        }\n    };\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {getAvailableImageWidths} from '../../utils/get-available-image-widths';\nimport {isLocalContentImage} from '../../utils/is-local-content-image';\nimport {isUnsplashImage} from '../../utils/is-unsplash-image';\nimport {getResizedImageDimensions} from '../../utils/get-resized-image-dimensions';\nimport {setSrcsetAttribute} from '../../utils/srcset-attribute';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nconst MAX_IMG_PER_ROW = 3;\n\nfunction isValidImage(image) {\n    return image.fileName\n        && image.src\n        && image.width\n        && image.height;\n}\n\nfunction buildStructure(images) {\n    const rows = [];\n    const noOfImages = images.length;\n\n    images.forEach((image, idx) => {\n        let row = image.row;\n\n        if (noOfImages > 1 && (noOfImages % MAX_IMG_PER_ROW === 1) && (idx === (noOfImages - 2))) {\n            row = row + 1;\n        }\n        if (!rows[row]) {\n            rows[row] = [];\n        }\n\n        rows[row].push(image);\n    });\n\n    return rows;\n}\n\nexport function renderGalleryNode(node, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const validImages = node.images.filter(isValidImage);\n    if (!validImages.length) {\n        return renderEmptyContainer(document);\n    }\n\n    const figure = document.createElement('figure');\n    figure.setAttribute('class', 'kg-card kg-gallery-card kg-width-wide');\n\n    const container = document.createElement('div');\n    container.setAttribute('class', 'kg-gallery-container');\n    figure.appendChild(container);\n\n    const rows = buildStructure(validImages);\n\n    rows.forEach((row) => {\n        const rowDiv = document.createElement('div');\n        rowDiv.setAttribute('class', 'kg-gallery-row');\n\n        row.forEach((image) => {\n            const imgDiv = document.createElement('div');\n            imgDiv.setAttribute('class', 'kg-gallery-image');\n\n            const img = document.createElement('img');\n            img.setAttribute('src', image.src);\n            img.setAttribute('width', image.width);\n            img.setAttribute('height', image.height);\n            img.setAttribute('loading', 'lazy');\n            img.setAttribute('alt', image.alt || '');\n            if (image.title) {\n                img.setAttribute('title', image.title);\n            }\n\n            // images can be resized to max width, if that's the case output\n            // the resized width/height attrs to ensure 3rd party gallery plugins\n            // aren't affected by differing sizes\n            const {canTransformImage} = options;\n            const {defaultMaxWidth} = options.imageOptimization || {};\n            if (\n                defaultMaxWidth &&\n                image.width > defaultMaxWidth &&\n                isLocalContentImage(image.src, options.siteUrl) &&\n                canTransformImage &&\n                canTransformImage(image.src)\n            ) {\n                const {width, height} = getResizedImageDimensions(image, {width: defaultMaxWidth});\n                img.setAttribute('width', width);\n                img.setAttribute('height', height);\n            }\n\n            // add srcset+sizes except for email clients which do not have good support for either\n            if (options.target !== 'email') {\n                setSrcsetAttribute(img, image, options);\n\n                if (img.getAttribute('srcset') && image.width >= 720) {\n                    if (rows.length === 1 && row.length === 1 && image.width >= 1200) {\n                        img.setAttribute('sizes', '(min-width: 1200px) 1200px');\n                    } else {\n                        img.setAttribute('sizes', '(min-width: 720px) 720px');\n                    }\n                }\n            }\n\n            // Outlook is unable to properly resize images without a width/height\n            // so we modify those to fit max width (600px) and use appropriately\n            // resized images if available\n            if (options.target === 'email') {\n                // only resize if needed, width/height always exists for gallery image unline image cards\n                if (image.width > 600) {\n                    const newImageDimensions = getResizedImageDimensions(image, {width: 600});\n                    img.setAttribute('width', newImageDimensions.width);\n                    img.setAttribute('height', newImageDimensions.height);\n                }\n\n                if (isLocalContentImage(image.src, options.siteUrl) && options.canTransformImage && options.canTransformImage(image.src)) {\n                    // find available image size next up from 2x600 so we can use it for the \"retina\" src\n                    const availableImageWidths = getAvailableImageWidths(image, options.imageOptimization.contentImageSizes);\n                    const srcWidth = availableImageWidths.find(width => width >= 1200);\n\n                    if (!srcWidth || srcWidth === image.width) {\n                        // do nothing, width is smaller than retina or matches the original payload src\n                    } else {\n                        const [, imagesPath, filename] = image.src.match(/(.*\\/content\\/images)\\/(.*)/);\n                        img.setAttribute('src', `${imagesPath}/size/w${srcWidth}/${filename}`);\n                    }\n                }\n\n                if (isUnsplashImage(image.src)) {\n                    const unsplashUrl = new URL(image.src);\n                    unsplashUrl.searchParams.set('w', 1200);\n                    img.setAttribute('src', unsplashUrl.href);\n                }\n            }\n\n            if (image.href) {\n                const a = document.createElement('a');\n                a.setAttribute('href', image.href);\n                a.appendChild(img);\n                imgDiv.appendChild(a);\n            } else {\n                imgDiv.appendChild(img);\n            }\n            rowDiv.appendChild(imgDiv);\n        });\n\n        container.appendChild(rowDiv);\n    });\n\n    if (node.caption) {\n        let figcaption = document.createElement('figcaption');\n        figcaption.innerHTML = node.caption;\n        figure.appendChild(figcaption);\n        figure.setAttribute('class', `${figure.getAttribute('class')} kg-card-hascaption`);\n    }\n\n    return {element: figure};\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {parseGalleryNode} from './gallery-parser';\nimport {renderGalleryNode} from './gallery-renderer';\nexport class GalleryNode extends generateDecoratorNode({\n    nodeType: 'gallery',\n    properties: [\n        {name: 'images', default: []},\n        {name: 'caption', default: '', wordCount: true}\n    ],\n    defaultRenderFn: renderGalleryNode\n}) {\n    /* override */\n    static get urlTransformMap() {\n        return {\n            caption: 'html',\n            images: {\n                src: 'url',\n                caption: 'html'\n            }\n        };\n    }\n\n    static importDOM() {\n        return parseGalleryNode(this);\n    }\n\n    hasEditMode() {\n        return false;\n    }\n}\n\nexport const $createGalleryNode = (dataset) => {\n    return new GalleryNode(dataset);\n};\n\nexport function $isGalleryNode(node) {\n    return node instanceof GalleryNode;\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {removeCodeWrappersFromHelpers, removeSpaces, wrapReplacementStrings} from '../../utils/replacement-strings';\nimport {escapeHtml} from '../../utils/escape-html';\nimport {renderEmptyContainer} from '../../utils/render-empty-container';\n\nexport function renderEmailCtaNode(node, options = {}) {\n    addCreateDocumentOption(options);\n\n    const document = options.createDocument();\n    const {html, buttonText, buttonUrl, showButton, alignment, segment, showDividers} = node;\n    const hasButton = showButton && !!buttonText && !!buttonUrl;\n\n    if ((!html && !hasButton) || options.target !== 'email') {\n        return renderEmptyContainer(document);\n    }\n\n    const element = document.createElement('div');\n\n    if (segment) {\n        element.setAttribute('data-gh-segment', segment);\n    }\n\n    if (alignment === 'center') {\n        element.setAttribute('class', 'align-center');\n    }\n\n    if (showDividers) {\n        element.appendChild(document.createElement('hr'));\n    }\n\n    const cleanedHtml = wrapReplacementStrings(removeCodeWrappersFromHelpers(removeSpaces(html),document));\n    element.innerHTML = element.innerHTML + cleanedHtml;\n\n    if (hasButton) {\n        const buttonTemplate = `\n            <div class=\"btn btn-accent\">\n                <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"${escapeHtml(alignment)}\">\n                    <tbody>\n                        <tr>\n                            <td align=\"center\">\n                                <a href=\"${escapeHtml(buttonUrl)}\">${escapeHtml(buttonText)}</a>\n                            </td>\n                        </tr>\n                    </tbody>\n                </table>\n            </div>\n            <p></p>\n        `; // the inline <p> element is so we get a line break if there's no separators/hr used\n\n        const cleanedButton = wrapReplacementStrings(removeCodeWrappersFromHelpers(removeSpaces(buttonTemplate),document));\n        element.innerHTML = element.innerHTML + cleanedButton;\n    }\n\n    if (showDividers) {\n        element.appendChild(document.createElement('hr'));\n    }\n\n    return {element};\n}","/* eslint-disable ghost/filenames/match-exported-class */\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderEmailCtaNode} from './email-cta-renderer';\n\nexport class EmailCtaNode extends generateDecoratorNode({\n    nodeType: 'email-cta',\n    properties: [\n        {name: 'alignment', default: 'left'},\n        {name: 'buttonText', default: ''},\n        {name: 'buttonUrl', default: '', urlType: 'url'},\n        {name: 'html', default: '', urlType: 'html'},\n        {name: 'segment', default: 'status:free'},\n        {name: 'showButton', default: false},\n        {name: 'showDividers', default: true}\n    ],\n    defaultRenderFn: renderEmailCtaNode\n}) {\n}\n\nexport const $createEmailCtaNode = (dataset) => {\n    return new EmailCtaNode(dataset);\n};\n\nexport function $isEmailCtaNode(node) {\n    return node instanceof EmailCtaNode;\n}\n","import {rgbToHex} from '../../utils/rgb-to-hex';\n\nfunction getLayout(domNode) {\n    if (domNode.classList.contains('kg-layout-split')) {\n        return 'split';\n    } else if (domNode.classList.contains('kg-layout-full')) {\n        return 'full';\n    } else if (domNode.classList.contains('kg-layout-wide')) {\n        return 'wide';\n    } else {\n        return 'regular';\n    }\n}\n\nexport function signupParser(SignupNode) {\n    return {\n        div: (nodeElem) => {\n            const isSignupNode = nodeElem.dataset?.lexicalSignupForm === '';\n            if (nodeElem.tagName === 'DIV' && isSignupNode) {\n                return {\n                    conversion(domNode) {\n                        const layout = getLayout(domNode);\n                        const header = domNode.querySelector('h2')?.textContent || '';\n                        const subheader = domNode.querySelector('h3')?.textContent || '';\n                        const disclaimer = domNode.querySelector('p')?.textContent || '';\n                        const backgroundImageSrc = domNode.querySelector('.kg-signup-card-image')?.getAttribute('src');\n                        const backgroundColor = domNode.style.backgroundColor || '';\n                        const buttonColor = domNode.querySelector('.kg-signup-card-button')?.style.backgroundColor || '';\n                        const buttonText = domNode.querySelector('.kg-signup-card-button-default')?.textContent?.trim() || 'Subscribe';\n                        const buttonTextColor = domNode.querySelector('.kg-signup-card-button')?.style.color || '';\n                        const textColor = domNode.querySelector('.kg-signup-card-success')?.style.color || '';\n                        const alignment = domNode.querySelector('.kg-signup-card-text')?.classList.contains('kg-align-center') ? 'center' : 'left';\n                        const successMessage = domNode.querySelector('.kg-signup-card-success')?.textContent?.trim() || '';\n                        const labels = [...domNode.querySelectorAll('input[data-members-label]')].map(input => input.value);\n\n                        const isAccentBackground = domNode.classList?.contains('kg-style-accent') ?? false;\n                        const isAccentButton = domNode.querySelector('.kg-signup-card-button')?.classList?.contains('kg-style-accent') ?? false;\n\n                        const isSwapped = domNode.classList.contains('kg-swapped');\n                        const backgroundSize = domNode.classList.contains('kg-content-wide') ? 'contain' : 'cover';\n\n                        const payload = {\n                            layout,\n                            buttonText,\n                            header,\n                            subheader,\n                            disclaimer,\n                            backgroundImageSrc,\n                            backgroundSize,\n                            backgroundColor: isAccentBackground ? 'accent' : (rgbToHex(backgroundColor) || '#ffffff'),\n                            buttonColor: isAccentButton ? 'accent' : (rgbToHex(buttonColor) || '#ffffff'),\n                            textColor: rgbToHex(textColor) || '#ffffff',\n                            buttonTextColor: rgbToHex(buttonTextColor) || '#000000',\n                            alignment,\n                            successMessage,\n                            labels,\n                            swapped: isSwapped\n                        };\n\n                        const node = new SignupNode(payload);\n                        return {node};\n                    },\n                    priority: 1\n                };\n            }\n            return null;\n        }\n    };\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\n\n// ref https://ghost.org/docs/themes/members#signup-forms\n\nfunction cardTemplate(nodeData) {\n    const cardClasses = getCardClasses(nodeData).join(' ');\n\n    const backgroundAccent = getAccentClass(nodeData); // don't apply accent style if there's a background image\n    const buttonAccent = nodeData.buttonColor === 'accent' ? 'kg-style-accent' : '';\n    const buttonStyle = nodeData.buttonColor !== 'accent' ? `background-color: ${nodeData.buttonColor};` : ``;\n    const alignment = nodeData.alignment === 'center' ? 'kg-align-center' : '';\n    const backgroundImageStyle = nodeData.backgroundColor !== 'accent' && (!nodeData.backgroundImageSrc || nodeData.layout === 'split') ? `background-color: ${nodeData.backgroundColor}` : '';\n\n    const imgTemplate = nodeData.backgroundImageSrc ? `\n        <picture><img class=\"kg-signup-card-image\" src=\"${nodeData.backgroundImageSrc}\" alt=\"\" /></picture>\n    ` : ``;\n\n    const formTemplate = `\n        <form class=\"kg-signup-card-form\" data-members-form=\"signup\">\n            ${nodeData.labels.map(label => `<input data-members-label type=\"hidden\" value=\"${label}\" />`).join('\\n')}\n            <div class=\"kg-signup-card-fields\">\n                <input class=\"kg-signup-card-input\" id=\"email\" data-members-email=\"\" type=\"email\" required=\"true\" placeholder=\"Your email\" />\n                <button class=\"kg-signup-card-button ${buttonAccent}\" style=\"${buttonStyle}color: ${nodeData.buttonTextColor};\" type=\"submit\">\n                    <span class=\"kg-signup-card-button-default\">${nodeData.buttonText || 'Subscribe'}</span>\n                    <span class=\"kg-signup-card-button-loading\">${loadingIcon()}</span>\n                </button>\n            </div>\n            <div class=\"kg-signup-card-success\" ${nodeData.textColor ? `style=\"color: ${nodeData.textColor};\"` : ''}>\n                ${nodeData.successMessage || 'Thanks! Now check your email to confirm.'}\n            </div>\n            <div class=\"kg-signup-card-error\" ${nodeData.textColor ? `style=\"color: ${nodeData.textColor};\"` : ''} data-members-error></div>\n        </form>\n        `;\n\n    return `\n        <div class=\"${cardClasses} ${backgroundAccent}\" data-lexical-signup-form style=\"${backgroundImageStyle}; display: none;\">\n            ${nodeData.layout !== 'split' ? imgTemplate : ''}\n            <div class=\"kg-signup-card-content\">\n                ${nodeData.layout === 'split' ? imgTemplate : ''}\n                <div class=\"kg-signup-card-text ${alignment}\">\n                    <h2 class=\"kg-signup-card-heading\" ${nodeData.textColor ? `style=\"color: ${nodeData.textColor};\"` : ''}>${nodeData.header}</h2>\n                    <p class=\"kg-signup-card-subheading\" ${nodeData.textColor ? `style=\"color: ${nodeData.textColor};\"` : ''}>${nodeData.subheader}</p>\n                    ${formTemplate}\n                    <p class=\"kg-signup-card-disclaimer\" ${nodeData.textColor ? `style=\"color: ${nodeData.textColor};\"` : ''}>${nodeData.disclaimer}</p>\n                </div>\n            </div>\n        </div>\n        `;\n}\n\nfunction loadingIcon() {\n    return `<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24\" width=\"24\" viewBox=\"0 0 24 24\">\n        <g stroke-linecap=\"round\" stroke-width=\"2\" fill=\"currentColor\" stroke=\"none\" stroke-linejoin=\"round\" class=\"nc-icon-wrapper\">\n            <g class=\"nc-loop-dots-4-24-icon-o\">\n                <circle cx=\"4\" cy=\"12\" r=\"3\"></circle>\n                <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>\n                <circle cx=\"20\" cy=\"12\" r=\"3\"></circle>\n            </g>\n            <style data-cap=\"butt\">\n                .nc-loop-dots-4-24-icon-o{--animation-duration:0.8s}\n                .nc-loop-dots-4-24-icon-o *{opacity:.4;transform:scale(.75);animation:nc-loop-dots-4-anim var(--animation-duration) infinite}\n                .nc-loop-dots-4-24-icon-o :nth-child(1){transform-origin:4px 12px;animation-delay:-.3s;animation-delay:calc(var(--animation-duration)/-2.666)}\n                .nc-loop-dots-4-24-icon-o :nth-child(2){transform-origin:12px 12px;animation-delay:-.15s;animation-delay:calc(var(--animation-duration)/-5.333)}\n                .nc-loop-dots-4-24-icon-o :nth-child(3){transform-origin:20px 12px}\n                @keyframes nc-loop-dots-4-anim{0%,100%{opacity:.4;transform:scale(.75)}50%{opacity:1;transform:scale(1)}}\n            </style>\n        </g>\n    </svg>`;\n}\n\nexport function renderSignupCardToDOM(dataset, options = {}) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    const node = {\n        alignment: dataset.__alignment,\n        buttonText: dataset.__buttonText,\n        header: dataset.__header,\n        subheader: dataset.__subheader,\n        disclaimer: dataset.__disclaimer,\n        backgroundImageSrc: dataset.__backgroundImageSrc,\n        backgroundSize: dataset.__backgroundSize,\n        backgroundColor: dataset.__backgroundColor,\n        buttonColor: dataset.__buttonColor,\n        labels: dataset.__labels,\n        layout: dataset.__layout,\n        textColor: dataset.__textColor,\n        buttonTextColor: dataset.__buttonTextColor,\n        successMessage: dataset.__successMessage,\n        swapped: dataset.__swapped\n    };\n\n    if (options.target === 'email') {\n        return {element: document.createElement('div')}; // Return an empty element since we don't want to render the card in email\n    }\n\n    const htmlString = cardTemplate(node);\n\n    const element = document.createElement('div');\n    element.innerHTML = htmlString?.trim();\n\n    if (node.header === '') {\n        const h2Element = element.querySelector('.kg-signup-card-heading');\n        if (h2Element) {\n            h2Element.remove();\n        }\n    }\n\n    if (node.subheader === '') {\n        const h3Element = element.querySelector('.kg-signup-card-subheading');\n        if (h3Element) {\n            h3Element.remove();\n        }\n    }\n\n    if (node.disclaimer === '') {\n        const pElement = element.querySelector('.kg-signup-card-disclaimer');\n        if (pElement) {\n            pElement.remove();\n        }\n    }\n    return {element: element.firstElementChild};\n}\n\nexport function getCardClasses(nodeData) {\n    let cardClasses = ['kg-card kg-signup-card'];\n\n    if (nodeData.layout && nodeData.layout !== 'split') {\n        cardClasses.push(`kg-width-${nodeData.layout}`);\n    }\n\n    if (nodeData.layout === 'split') {\n        cardClasses.push('kg-layout-split kg-width-full');\n    }\n\n    if (nodeData.swapped && nodeData.layout === 'split') {\n        cardClasses.push('kg-swapped');\n    }\n\n    if (nodeData.layout && nodeData.layout === 'full') {\n        cardClasses.push(`kg-content-wide`);\n    }\n\n    if (nodeData.layout === 'split') {\n        if (nodeData.backgroundSize === 'contain') {\n            cardClasses.push('kg-content-wide');\n        }\n    }\n\n    return cardClasses;\n}\n\n// In general, we don't want to apply the accent style if there's a background image\n//  but with the split format we display both an image and a background color\nconst getAccentClass = (nodeData) => {\n    if (nodeData.layout === 'split' && nodeData.backgroundColor === 'accent') {\n        return 'kg-style-accent';\n    } else if (nodeData.layout !== 'split' && !nodeData.backgroundImageSrc && nodeData.backgroundColor === 'accent') {\n        return 'kg-style-accent';\n    } else {\n        return '';\n    }\n};","/* eslint-disable ghost/filenames/match-exported-class */\nimport {signupParser} from './signup-parser';\nimport {renderSignupCardToDOM} from './signup-renderer';\nimport {generateDecoratorNode} from '../../generate-decorator-node';\n\nexport class SignupNode extends generateDecoratorNode({\n    nodeType: 'signup',\n    properties: [\n        {name: 'alignment', default: 'left'},\n        {name: 'backgroundColor', default: '#F0F0F0'},\n        {name: 'backgroundImageSrc', default: ''},\n        {name: 'backgroundSize', default: 'cover'},\n        {name: 'textColor', default: ''},\n        {name: 'buttonColor', default: 'accent'},\n        {name: 'buttonTextColor', default: '#FFFFFF'},\n        {name: 'buttonText', default: 'Subscribe'},\n        {name: 'disclaimer', default: '', wordCount: true},\n        {name: 'header', default: '', wordCount: true},\n        {name: 'labels', default: []},\n        {name: 'layout', default: 'wide'},\n        {name: 'subheader', default: '', wordCount: true},\n        {name: 'successMessage', default: 'Email sent! Check your inbox to complete your signup.'},\n        {name: 'swapped', default: false}\n    ],\n    defaultRenderFn: renderSignupCardToDOM\n}) {\n    /* override */\n    constructor({alignment, backgroundColor, backgroundImageSrc, backgroundSize, textColor, buttonColor, buttonTextColor, buttonText, disclaimer, header, labels, layout, subheader, successMessage, swapped} = {}, key) {\n        super(key);\n        this.__alignment = alignment || 'left';\n        this.__backgroundColor = backgroundColor || '#F0F0F0';\n        this.__backgroundImageSrc = backgroundImageSrc || '';\n        this.__backgroundSize = backgroundSize || 'cover';\n        this.__textColor = (backgroundColor === 'transparent' && (layout === 'split' || !backgroundImageSrc)) ? '' : textColor || '#000000'; // text color should inherit with a transparent bg color unless we're using an image for the background (which supercedes the bg color)\n        this.__buttonColor = buttonColor || 'accent';\n        this.__buttonTextColor = buttonTextColor || '#FFFFFF';\n        this.__buttonText = buttonText || 'Subscribe';\n        this.__disclaimer = disclaimer || '';\n        this.__header = header || '';\n        this.__labels = labels || [];\n        this.__layout = layout || 'wide';\n        this.__subheader = subheader || '';\n        this.__successMessage = successMessage || 'Email sent! Check your inbox to complete your signup.';\n        this.__swapped = swapped || false;\n    }\n\n    static importDOM() {\n        return signupParser(this);\n    }\n\n    // keeping some custom methods for labels as it requires some special handling\n\n    setLabels(labels) {\n        if (!Array.isArray(labels) || !labels.every(item => typeof item === 'string')) {\n            throw new Error('Invalid argument: Expected an array of strings.'); // eslint-disable-line\n        }\n\n        const writable = this.getWritable();\n        writable.__labels = labels;\n    }\n\n    addLabel(label) {\n        const writable = this.getWritable();\n        writable.__labels.push(label);\n    }\n\n    removeLabel(label) {\n        const writable = this.getWritable();\n        writable.__labels = writable.__labels.filter(l => l !== label);\n    }\n}\n\nexport const $createSignupNode = (dataset) => {\n    return new SignupNode(dataset);\n};\n\nexport function $isSignupNode(node) {\n    return node instanceof SignupNode;\n}\n","/**\n * Builds an inline script tag that reads `data-src` from the first iframe\n * in the script's parent element, detects the nearest non-transparent ancestor\n * background color, appends it as a `background` query param, and sets `src`\n * to trigger a single load with the correct background.\n *\n * Uses `document.currentScript` to scope to the containing card, so multiple\n * instances on the same page each target their own iframe.\n *\n * @param {Document} document\n * @returns {HTMLScriptElement} A script element\n */\nexport function buildSrcBackgroundScript(document) {\n    function setSrcBackgroundFromParent() {\n        const script = document.currentScript;\n        if (!script) {\n            return;\n        }\n\n        const el = script.parentElement.querySelector('iframe[data-src]');\n        if (!el) {\n            return;\n        }\n\n        const baseSrc = el.getAttribute('data-src');\n\n        function colorToRgb(color) {\n            const canvas = document.createElement('canvas');\n            canvas.width = 1;\n            canvas.height = 1;\n            const ctx = canvas.getContext('2d');\n            ctx.fillStyle = color;\n            ctx.fillRect(0, 0, 1, 1);\n            const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;\n            return {r, g, b, a};\n        }\n\n        let node = el.parentElement;\n        let bg;\n        while (node) {\n            bg = window.getComputedStyle(node).backgroundColor;\n            if (bg && bg !== 'transparent') {\n                const {a} = colorToRgb(bg);\n                if (a > 0) {\n                    break;\n                }\n            }\n            node = node.parentElement;\n        }\n\n        if (!node || !bg || bg === 'transparent') {\n            el.src = baseSrc;\n            return;\n        }\n\n        const {r, g, b, a} = colorToRgb(bg);\n        if (a === 0) {\n            el.src = baseSrc;\n            return;\n        }\n\n        const hex = [r, g, b].map(c => c.toString(16).padStart(2, '0')).join('');\n        const u = new URL(baseSrc);\n        u.searchParams.set('background', hex);\n        el.src = u.toString();\n    }\n\n    const script = document.createElement('script');\n    script.innerHTML = `(${setSrcBackgroundFromParent.toString()})()`;\n    return script;\n}\n","import {addCreateDocumentOption} from '../../utils/add-create-document-option';\nimport {buildSrcBackgroundScript} from '../../utils/set-src-background-from-parent';\nimport {renderWithVisibility} from '../../utils/visibility';\n\n/**\n * @param {HTMLIFrameElement} iframe\n */\nfunction setIframeAttributes(iframe) {\n    iframe.setAttribute('width', '100%');\n    iframe.setAttribute('height', '180');\n    iframe.setAttribute('frameborder', 'no');\n    iframe.setAttribute('scrolling', 'no');\n    iframe.setAttribute('seamless', '');\n}\n\nexport function renderTransistorNode(node, options) {\n    addCreateDocumentOption(options);\n    const document = options.createDocument();\n\n    // {uuid} placeholder will be replaced server-side with the member's UUID\n    const baseUrl = 'https://partner.transistor.fm/ghost/embed/{uuid}';\n    const params = new URLSearchParams();\n\n    if (options.siteUuid) {\n        params.set('ctx', options.siteUuid);\n    }\n\n    const queryString = params.toString();\n    const embedUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl;\n\n    const iframe = document.createElement('iframe');\n    setIframeAttributes(iframe);\n    iframe.setAttribute('data-src', embedUrl);\n\n    const figure = document.createElement('figure');\n    figure.setAttribute('class', 'kg-card kg-transistor-card');\n    figure.appendChild(iframe);\n    figure.insertAdjacentElement('beforeend', buildSrcBackgroundScript(document));\n\n    const noscript = document.createElement('noscript');\n    const fallbackIframe = document.createElement('iframe');\n    setIframeAttributes(fallbackIframe);\n    fallbackIframe.setAttribute('src', embedUrl);\n    noscript.appendChild(fallbackIframe);\n    figure.appendChild(noscript);\n\n    return renderWithVisibility({element: figure, type: 'inner'}, node.visibility, options);\n}\n","// eslint-disable-next-line ghost/filenames/match-exported-class\nimport cloneDeep from 'lodash/cloneDeep';\nimport {generateDecoratorNode} from '../../generate-decorator-node';\nimport {renderTransistorNode} from './transistor-renderer';\nimport {ALL_MEMBERS_SEGMENT} from '../../utils/visibility';\n\n// Default visibility for Transistor: members only (no public visitors)\n// since the embed requires a member UUID to function\nconst TRANSISTOR_DEFAULT_VISIBILITY = {\n    web: {\n        nonMember: false, // Hide from public visitors - requires member UUID\n        memberSegment: ALL_MEMBERS_SEGMENT // Show to all members (free + paid)\n    },\n    email: {\n        memberSegment: ALL_MEMBERS_SEGMENT\n    }\n};\n\nexport class TransistorNode extends generateDecoratorNode({\n    nodeType: 'transistor',\n    hasVisibility: true,\n    properties: [\n        {name: 'accentColor', default: ''}, // Player accent color (text/buttons) - hex value\n        {name: 'backgroundColor', default: ''} // Player background color - hex value\n    ],\n    defaultRenderFn: renderTransistorNode\n}) {\n    constructor(data = {}, key) {\n        super(data, key);\n        if (!data.visibility) {\n            this.__visibility = cloneDeep(TRANSISTOR_DEFAULT_VISIBILITY);\n        }\n    }\n\n    static getPropertyDefaults() {\n        const defaults = super.getPropertyDefaults();\n        defaults.visibility = cloneDeep(TRANSISTOR_DEFAULT_VISIBILITY);\n        return defaults;\n    }\n\n    isEmpty() {\n        return false; // Transistor card is never empty as it has a fixed URL\n    }\n\n    hasEditMode() {\n        return true;\n    }\n}\n\nexport const $createTransistorNode = (dataset) => {\n    return new TransistorNode(dataset);\n};\n\nexport const $isTransistorNode = (node) => {\n    return node instanceof TransistorNode;\n};\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {$isTextNode, TextNode} from 'lexical';\n\n// Since the TextNode is foundational to all Lexical packages, including the\n// plain text use case. Handling any rich text logic is undesirable. This creates\n// the need to override the TextNode to handle serialization and deserialization\n// of HTML/CSS styling properties to achieve full fidelity between JSON <-> HTML.\n//\n// https://lexical.dev/docs/concepts/serialization#handling-extended-html-styling\n\nexport const extendedTextNodeReplacement = {replace: TextNode, with: node => new ExtendedTextNode(node.__text)};\n\nexport class ExtendedTextNode extends TextNode {\n    constructor(text, key) {\n        super(text, key);\n    }\n\n    static getType() {\n        return 'extended-text';\n    }\n\n    static clone(node) {\n        return new ExtendedTextNode(node.__text, node.__key);\n    }\n\n    static importDOM() {\n        const importers = TextNode.importDOM();\n        return {\n            ...importers,\n            span: () => ({\n                conversion: patchConversion(importers?.span, convertSpanElement),\n                priority: 1\n            })\n        };\n    }\n\n    static importJSON(serializedNode) {\n        return TextNode.importJSON(serializedNode);\n    }\n\n    exportJSON() {\n        const json = super.exportJSON();\n        json.type = 'extended-text';\n        return json;\n    }\n\n    isSimpleText() {\n        return (\n            (this.__type === 'text' || this.__type === 'extended-text') &&\n            this.__mode === 0\n        );\n    }\n\n    isInline() {\n        return true;\n    }\n}\n\nfunction patchConversion(originalDOMConverter, convertFn) {\n    return (node) => {\n        const original = originalDOMConverter?.(node);\n        if (!original) {\n            return null;\n        }\n        const originalOutput = original.conversion(node);\n\n        if (!originalOutput) {\n            return originalOutput;\n        }\n\n        return {\n            ...originalOutput,\n            forChild: (lexicalNode, parent) => {\n                const originalForChild = originalOutput?.forChild ?? (x => x);\n                const result = originalForChild(lexicalNode, parent);\n                if ($isTextNode(result)) {\n                    return convertFn(result, node);\n                }\n                return result;\n            }\n        };\n    };\n}\n\nfunction convertSpanElement(lexicalNode, domNode) {\n    const span = domNode;\n\n    // Word uses span tags + font-weight for bold text\n    const hasBoldFontWeight = span.style.fontWeight === 'bold' || span.parentElement?.style.fontWeight === 'bold';\n    // Word uses span tags + font-style for italic text\n    const hasItalicFontStyle = span.style.fontStyle === 'italic' || span.parentElement?.style.fontStyle === 'italic';\n    // Word uses span tags + text-decoration for underline text\n    const hasUnderlineTextDecoration = span.style.textDecoration === 'underline' || span.parentElement?.style.textDecoration === 'underline';\n    // Word uses span tags + \"Strikethrough\" class for strikethrough text\n    const hasStrikethroughClass = span.classList.contains('Strikethrough') || span.parentElement?.classList.contains('Strikethrough');\n    // Word uses span tags + \"Highlight\" class for highlighted text\n    const hasHighlightClass = span.classList.contains('Highlight') || span.parentElement?.classList.contains('Highlight');\n\n    if (hasBoldFontWeight && !lexicalNode.hasFormat('bold')) {\n        lexicalNode = lexicalNode.toggleFormat('bold');\n    }\n\n    if (hasItalicFontStyle && !lexicalNode.hasFormat('italic')) {\n        lexicalNode = lexicalNode.toggleFormat('italic');\n    }\n\n    if (hasUnderlineTextDecoration && !lexicalNode.hasFormat('underline')) {\n        lexicalNode = lexicalNode.toggleFormat('underline');\n    }\n\n    if (hasStrikethroughClass && !lexicalNode.hasFormat('strikethrough')) {\n        lexicalNode = lexicalNode.toggleFormat('strikethrough');\n    }\n\n    if (hasHighlightClass && !lexicalNode.hasFormat('highlight')) {\n        lexicalNode = lexicalNode.toggleFormat('highlight');\n    }\n\n    return lexicalNode;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {HeadingNode} from '@lexical/rich-text';\n\n// Since the HeadingNode is foundational to Lexical rich-text, only using a\n// custom HeadingNode is undesirable as it means every package would need to\n// be updated to work with the custom node. Instead we can use Lexical's node\n// override/replacement mechanism to extend the default with our custom parsing\n// logic.\n//\n// https://lexical.dev/docs/concepts/serialization#handling-extended-html-styling\n\nexport const extendedHeadingNodeReplacement = {replace: HeadingNode, with: node => new ExtendedHeadingNode(node.__tag)};\n\nexport class ExtendedHeadingNode extends HeadingNode {\n    constructor(tag, key) {\n        super(tag, key);\n    }\n\n    static getType() {\n        return 'extended-heading';\n    }\n\n    static clone(node) {\n        return new ExtendedHeadingNode(node.__tag, node.__key);\n    }\n\n    static importDOM() {\n        const importers = HeadingNode.importDOM();\n        return {\n            ...importers,\n            p: patchParagraphConversion(importers?.p)\n        };\n    }\n\n    static importJSON(serializedNode) {\n        return HeadingNode.importJSON(serializedNode);\n    }\n\n    exportJSON() {\n        const json = super.exportJSON();\n        json.type = 'extended-heading';\n        return json;\n    }\n}\n\nfunction patchParagraphConversion(originalDOMConverter) {\n    return (node) => {\n        // Original matches Google Docs p node to a null conversion so it's\n        // child span is parsed as a heading. Don't prevent that here\n        const original = originalDOMConverter?.(node);\n        if (original) {\n            return original;\n        }\n\n        const p = node;\n\n        // Word uses paragraphs with role=\"heading\" to represent headings\n        // and an aria-level=\"x\" to represent the heading level\n        const hasAriaHeadingRole = p.getAttribute('role') === 'heading';\n        const hasAriaLevel = p.getAttribute('aria-level');\n\n        if (hasAriaHeadingRole && hasAriaLevel) {\n            const level = parseInt(hasAriaLevel, 10);\n            if (level > 0 && level < 7) {\n                return {\n                    conversion: () => {\n                        return {\n                            node: new ExtendedHeadingNode(`h${level}`)\n                        };\n                    },\n                    priority: 1\n                };\n            }\n        }\n\n        return null;\n    };\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {QuoteNode} from '@lexical/rich-text';\nimport {$createLineBreakNode, $isParagraphNode} from 'lexical';\n\n// Since the QuoteNode is foundational to Lexical rich-text, only using a\n// custom QuoteNode is undesirable as it means every package would need to\n// be updated to work with the custom node. Instead we can use Lexical's node\n// override/replacement mechanism to extend the default with our custom parsing\n// logic.\n//\n// https://lexical.dev/docs/concepts/serialization#handling-extended-html-styling\n\nexport const extendedQuoteNodeReplacement = {replace: QuoteNode, with: () => new ExtendedQuoteNode()};\n\nexport class ExtendedQuoteNode extends QuoteNode {\n    constructor(key) {\n        super(key);\n    }\n\n    static getType() {\n        return 'extended-quote';\n    }\n\n    static clone(node) {\n        return new ExtendedQuoteNode(node.__key);\n    }\n\n    static importDOM() {\n        const importers = QuoteNode.importDOM();\n        return {\n            ...importers,\n            blockquote: convertBlockquoteElement\n        };\n    }\n\n    static importJSON(serializedNode) {\n        return QuoteNode.importJSON(serializedNode);\n    }\n\n    exportJSON() {\n        const json = super.exportJSON();\n        json.type = 'extended-quote';\n        return json;\n    }\n\n    /* c8 ignore start */\n    extractWithChild() {\n        return true;\n    }\n    /* c8 ignore end */\n}\n\nfunction convertBlockquoteElement() {\n    return {\n        conversion: () => {\n            const node = new ExtendedQuoteNode();\n            return {\n                node,\n                after: (childNodes) => {\n                    // Blockquotes can have nested paragraphs. In our original mobiledoc\n                    // editor we parsed all of the nested paragraphs into a single blockquote\n                    // separating each paragraph with two line breaks. We replicate that\n                    // here so we don't have a breaking change in conversion behaviour.\n                    const newChildNodes = [];\n\n                    childNodes.forEach((child) => {\n                        if ($isParagraphNode(child)) {\n                            if (newChildNodes.length > 0) {\n                                newChildNodes.push($createLineBreakNode());\n                                newChildNodes.push($createLineBreakNode());\n                            }\n\n                            newChildNodes.push(...child.getChildren());\n                        } else {\n                            newChildNodes.push(child);\n                        }\n                    });\n\n                    return newChildNodes;\n                }\n            };\n        },\n        priority: 1\n    };\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {$applyNodeReplacement, TextNode} from 'lexical';\n\nexport class TKNode extends TextNode {\n    static getType() {\n        return 'tk';\n    }\n\n    static clone(node) {\n        return new TKNode(node.__text, node.__key);\n    }\n\n    constructor(text, key) {\n        super(text, key);\n    }\n\n    createDOM(config) {\n        const element = super.createDOM(config);\n        const classes = config.theme.tk?.split(' ') || [];\n        element.classList.add(...classes);\n        element.dataset.kgTk = true;\n        return element;\n    }\n\n    static importJSON(serializedNode) {\n        const node = $createTKNode(serializedNode.text);\n        node.setFormat(serializedNode.format);\n        node.setDetail(serializedNode.detail);\n        node.setMode(serializedNode.mode);\n        node.setStyle(serializedNode.style);\n        return node;\n    }\n\n    exportJSON() {\n        return {\n            ...super.exportJSON(),\n            type: 'tk'\n        };\n    }\n\n    canInsertTextBefore() {\n        return false;\n    }\n\n    isTextEntity() {\n        return true;\n    }\n}\n\n/**\n * Generates a TKNode, which is a string following the format of a # followed by some text, eg. #lexical.\n * @param text - The text used inside the TKNode.\n * @returns - The TKNode with the embedded text.\n */\nexport function $createTKNode(text) {\n    return $applyNodeReplacement(new TKNode(text));\n}\n\n/**\n * Determines if node is a TKNode.\n * @param node - The node to be checked.\n * @returns true if node is a TKNode, false otherwise.\n */\nexport function $isTKNode(node) {\n    return node instanceof TKNode;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {$applyNodeReplacement, ElementNode} from 'lexical';\nimport linkSVG from './kg-link.svg';\n// Container element for a link search query. Temporary node used only inside\n// the editor that will be replaced with a LinkNode when the search is complete.\nexport class AtLinkNode extends ElementNode {\n    // We keep track of the format that was applied to the original '@' character\n    // so we can re-apply that when converting to a LinkNode\n    __linkFormat = null;\n\n    static getType() {\n        return 'at-link';\n    }\n\n    constructor(linkFormat, key) {\n        super(key);\n        this.__linkFormat = linkFormat;\n    }\n\n    static clone(node) {\n        return new AtLinkNode(node.__linkFormat, node.__key);\n    }\n\n    // This is a temporary node, it should never be serialized but we need\n    // to implement just in case and to match expected types. The AtLinkPlugin\n    // should take care of replacing this node with it's children when needed.\n    static importJSON({linkFormat}) {\n        return $createAtLinkNode(linkFormat);\n    }\n\n    exportJSON() {\n        return {\n            ...super.exportJSON(),\n            type: 'at-link',\n            version: 1,\n            linkFormat: this.__linkFormat\n        };\n    }\n\n    createDOM(config) {\n        const span = document.createElement('span');\n        const atLinkClasses = (config.theme.atLink || '').split(' ').filter(Boolean);\n        const atLinkIconClasses = (config.theme.atLinkIcon || '').split(' ').filter(Boolean);\n\n        span.classList.add(...atLinkClasses);\n\n        const svgElement = new DOMParser().parseFromString(linkSVG, 'image/svg+xml').documentElement;\n        svgElement.classList.add(...atLinkIconClasses);\n\n        span.appendChild(svgElement);\n\n        return span;\n    }\n\n    updateDOM() {\n        return false;\n    }\n\n    // should not render anything - this is a placeholder node\n    exportDOM() {\n        return null;\n    }\n\n    /* c8 ignore next 3 */\n    static importDOM() {\n        return null;\n    }\n\n    getTextContent() {\n        return '';\n    }\n\n    isInline() {\n        return true;\n    }\n\n    canBeEmpty() {\n        return false;\n    }\n\n    setLinkFormat(linkFormat) {\n        const self = this.getWritable();\n        self.__linkFormat = linkFormat;\n    }\n\n    getLinkFormat() {\n        const self = this.getLatest();\n        return self.__linkFormat;\n    }\n}\n\nexport function $createAtLinkNode(linkFormat) {\n    return $applyNodeReplacement(new AtLinkNode(linkFormat));\n}\n\nexport function $isAtLinkNode(node) {\n    return node instanceof AtLinkNode;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {$applyNodeReplacement, TextNode} from 'lexical';\n\n// Represents the search query string inside an AtLinkNode. Used in place of a\n// regular TextNode to allow for :after styling to be applied to work as a placeholder\nexport class AtLinkSearchNode extends TextNode {\n    __placeholder = null;\n\n    defaultPlaceholder = 'Find a post, tag or author';\n\n    static getType() {\n        return 'at-link-search';\n    }\n\n    constructor(text, placeholder, key) {\n        super(text, key);\n        this.__placeholder = placeholder;\n    }\n\n    static clone(node) {\n        return new AtLinkSearchNode(\n            node.__text,\n            node.__placeholder,\n            node.__key\n        );\n    }\n\n    // This is a temporary node, it should never be serialized but we need\n    // to implement just in case and to match expected types. The AtLinkPlugin\n    // should take care of replacing this node when needed.\n    static importJSON({text, placeholder}) {\n        return $createAtLinkSearchNode(text, placeholder);\n    }\n\n    exportJSON() {\n        return {\n            ...super.exportJSON(),\n            type: 'at-link-search',\n            version: 1,\n            placeholder: this.__placeholder\n        };\n    }\n\n    createDOM(config) {\n        const span = super.createDOM(config);\n        span.dataset.placeholder = '';\n        if (!this.__text) {\n            span.dataset.placeholder =\n                this.__placeholder ?? this.defaultPlaceholder;\n        } else {\n            span.dataset.placeholder = this.__placeholder || '';\n        }\n        span.classList.add(...config.theme.atLinkSearch.split(' '));\n\n        return span;\n    }\n\n    updateDOM(prevNode, dom) {\n        if (this.__text) {\n            dom.dataset.placeholder = this.__placeholder ?? '';\n        }\n\n        return super.updateDOM(...arguments);\n    }\n\n    // should not render anything - this is a placeholder node\n    exportDOM() {\n        return null;\n    }\n\n    /* c8 ignore next 3 */\n    static importDOM() {\n        return null;\n    }\n\n    canHaveFormat() {\n        return false;\n    }\n\n    setPlaceholder(text) {\n        const self = this.getWritable();\n        self.__placeholder = text;\n    }\n\n    getPlaceholder() {\n        const self = this.getLatest();\n        return self.__placeholder;\n    }\n\n    // Lexical will incorrectly pick up this node as an element node when the\n    // cursor is placed by the SVG icon element in the parent AtLinkNode. We\n    // need these methods to avoid throwing errors in that case but otherwise\n    // behaviour is unaffected.\n    getChildrenSize() {\n        return 0;\n    }\n\n    getChildAtIndex() {\n        return null;\n    }\n}\n\nexport function $createAtLinkSearchNode(text = '', placeholder = null) {\n    return $applyNodeReplacement(new AtLinkSearchNode(text, placeholder));\n}\n\nexport function $isAtLinkSearchNode(node) {\n    return node instanceof AtLinkSearchNode;\n}\n","/* eslint-disable ghost/filenames/match-exported-class */\nimport {TextNode} from 'lexical';\n\n// This is used in places where we need an extra cursor position at the\n// beginning of an element node as it prevents Lexical normalizing the\n// cursor position to the end of the previous node.\nexport class ZWNJNode extends TextNode {\n    static getType() {\n        return 'zwnj';\n    }\n\n    static clone(node) {\n        return new ZWNJNode('', node.__key);\n    }\n\n    createDOM(config) {\n        const span = super.createDOM(config);\n        span.innerHTML = '&zwnj;';\n        return span;\n    }\n\n    updateDOM() {\n        return false;\n    }\n\n    exportJSON() {\n        return {\n            ...super.exportJSON(),\n            type: 'zwnj',\n            version: 1\n        };\n    }\n\n    getTextContent() {\n        return '';\n    }\n\n    isToken() {\n        return true;\n    }\n}\n\nexport function $createZWNJNode() {\n    return new ZWNJNode('');\n}\n\nexport function $isZWNJNode(node) {\n    return node instanceof ZWNJNode;\n}\n","export default {\n    import: {\n        br: (node) => {\n            const isGoogleDocs = !!node.closest('[id^=\"docs-internal-guid-\"]');\n            const previousNodeName = node.previousElementSibling?.nodeName;\n            const nextNodeName = node.nextElementSibling?.nodeName;\n            const headings = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];\n            const lists = ['UL', 'OL', 'DL'];\n\n            // Remove empty paragraphs when copy/pasting from Google docs:\n            // - Between two paragraphs (P and P)\n            // - Between multiple linebreaks (BR and BR)\n            // - Between a list and a paragraph (UL/OL/DL and P), and vice versa\n            // - Between a heading and a paragraph (H1-H6 and P), and vice versa\n            if (isGoogleDocs) {\n                if (\n                    (previousNodeName === 'P' && nextNodeName === 'P') ||\n                    (previousNodeName === 'BR' || nextNodeName === 'BR') ||\n                    ([...headings, ...lists].includes(previousNodeName) && nextNodeName === 'P') ||\n                    (previousNodeName === 'P' && [...headings, ...lists].includes(nextNodeName))\n                ) {\n                    return {\n                        conversion: () => null,\n                        priority: 1\n                    };\n                }\n            }\n\n            // allow lower priority converter to handle (i.e. default LineBreakNode.importDOM)\n            return null;\n        }\n    }\n};\n","export default {\n    import: {\n        p: (node) => {\n            const isGoogleDocs = !!node.closest('[id^=\"docs-internal-guid-\"]');\n\n            // Google docs wraps dividers in paragraphs, without text content\n            // Remove them to avoid creating empty paragraphs in the editor\n            if (isGoogleDocs && node.textContent === '') {\n                return {\n                    conversion: () => null,\n                    priority: 1\n                };\n            }\n\n            return null;\n        }\n    }\n};\n","import * as image from './nodes/image/ImageNode';\nimport * as codeblock from './nodes/codeblock/CodeBlockNode';\nimport * as markdown from './nodes/markdown/MarkdownNode';\nimport * as video from './nodes/video/VideoNode';\nimport * as audio from './nodes/audio/AudioNode';\nimport * as callout from './nodes/callout/CalloutNode';\nimport * as callToAction from './nodes/call-to-action/CallToActionNode';\nimport * as aside from './nodes/aside/AsideNode';\nimport * as horizontalrule from './nodes/horizontalrule/HorizontalRuleNode';\nimport * as html from './nodes/html/HtmlNode';\nimport * as toggle from './nodes/toggle/ToggleNode';\nimport * as button from './nodes/button/ButtonNode';\nimport * as bookmark from './nodes/bookmark/BookmarkNode';\nimport * as file from './nodes/file/FileNode';\nimport * as header from './nodes/header/HeaderNode';\nimport * as paywall from './nodes/paywall/PaywallNode';\nimport * as product from './nodes/product/ProductNode';\nimport * as embed from './nodes/embed/EmbedNode';\nimport * as email from './nodes/email/EmailNode';\nimport * as gallery from './nodes/gallery/GalleryNode';\nimport * as emailCta from './nodes/email-cta/EmailCtaNode';\nimport * as signup from './nodes/signup/SignupNode';\nimport * as transistor from './nodes/transistor/TransistorNode';\nimport * as textnode from './nodes/ExtendedTextNode';\nimport * as headingnode from './nodes/ExtendedHeadingNode';\nimport * as quotenode from './nodes/ExtendedQuoteNode';\nimport * as tk from './nodes/TKNode';\nimport * as atLink from './nodes/at-link/index.js';\nimport * as zwnj from './nodes/zwnj/ZWNJNode.js';\n\nimport linebreakSerializers from './serializers/linebreak';\nimport paragraphSerializers from './serializers/paragraph';\n\n// re-export everything for easier importing\nexport * from './KoenigDecoratorNode';\nexport * from './nodes/image/ImageNode';\nexport * from './nodes/codeblock/CodeBlockNode';\nexport * from './nodes/markdown/MarkdownNode';\nexport * from './nodes/video/VideoNode';\nexport * from './nodes/audio/AudioNode';\nexport * from './nodes/callout/CalloutNode';\nexport * from './nodes/aside/AsideNode';\nexport * from './nodes/horizontalrule/HorizontalRuleNode';\nexport * from './nodes/html/HtmlNode';\nexport * from './nodes/toggle/ToggleNode';\nexport * from './nodes/button/ButtonNode';\nexport * from './nodes/bookmark/BookmarkNode';\nexport * from './nodes/file/FileNode';\nexport * from './nodes/header/HeaderNode';\nexport * from './nodes/paywall/PaywallNode';\nexport * from './nodes/product/ProductNode';\nexport * from './nodes/embed/EmbedNode';\nexport * from './nodes/email/EmailNode';\nexport * from './nodes/gallery/GalleryNode';\nexport * from './nodes/email-cta/EmailCtaNode';\nexport * from './nodes/signup/SignupNode';\nexport * from './nodes/transistor/TransistorNode';\nexport * from './nodes/call-to-action/CallToActionNode';\nexport * from './nodes/ExtendedTextNode';\nexport * from './nodes/ExtendedHeadingNode';\nexport * from './nodes/ExtendedQuoteNode';\nexport * from './nodes/TKNode';\nexport * from './nodes/at-link/index.js';\nexport * from './nodes/zwnj/ZWNJNode';\n\n// export utility functions that are useful in other packages or tests\nimport * as visibilityUtils from './utils/visibility';\nimport * as taggedTemplateFns from './utils/tagged-template-fns.mjs';\nimport {generateDecoratorNode} from './generate-decorator-node.js';\nimport {rgbToHex} from './utils/rgb-to-hex.js';\nexport const utils = {\n    generateDecoratorNode,\n    visibility: visibilityUtils,\n    rgbToHex,\n    taggedTemplateFns\n};\n\nexport const serializers = {\n    linebreak: linebreakSerializers,\n    paragraph: paragraphSerializers\n};\n\nexport const DEFAULT_CONFIG = {\n    html: {\n        import: {\n            ...serializers.linebreak.import,\n            ...serializers.paragraph.import\n        }\n    }\n};\n\n// export convenience objects for use elsewhere\nexport const DEFAULT_NODES = [\n    textnode.ExtendedTextNode,\n    textnode.extendedTextNodeReplacement,\n    headingnode.ExtendedHeadingNode,\n    headingnode.extendedHeadingNodeReplacement,\n    quotenode.ExtendedQuoteNode,\n    quotenode.extendedQuoteNodeReplacement,\n    codeblock.CodeBlockNode,\n    image.ImageNode,\n    markdown.MarkdownNode,\n    video.VideoNode,\n    audio.AudioNode,\n    callout.CalloutNode,\n    callToAction.CallToActionNode,\n    aside.AsideNode,\n    horizontalrule.HorizontalRuleNode,\n    html.HtmlNode,\n    file.FileNode,\n    toggle.ToggleNode,\n    button.ButtonNode,\n    header.HeaderNode,\n    bookmark.BookmarkNode,\n    paywall.PaywallNode,\n    product.ProductNode,\n    embed.EmbedNode,\n    email.EmailNode,\n    gallery.GalleryNode,\n    emailCta.EmailCtaNode,\n    signup.SignupNode,\n    transistor.TransistorNode,\n    tk.TKNode,\n    atLink.AtLinkNode,\n    atLink.AtLinkSearchNode,\n    zwnj.ZWNJNode\n];\n"]}