{
  "name": "ezGPT - Markdown HTML Preview",
  "active": false,
  "nodes": [
    {
      "id": "trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {}
    },
    {
      "id": "sample-draft",
      "name": "Sample Draft",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const markdown = `# Учебная сводка\n\n**Статус:** черновик.\n\n## Следующие шаги\n\n1. Проверить цифры.\n2. Согласовать текст.\n\n## Проверка пакета\n\n| Этап | Статус |\n| --- | --- |\n| Проверка | Готово |\n| Отправка | Не выполнена |\n\n[Термины](https://ezgpt.ru/glossary)\n`;\nreturn [{ json: { draft_id: 'md-demo-001', markdown } }];"
      }
    },
    {
      "id": "check-draft",
      "name": "Check Draft",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('one_draft_required');\nconst row = items[0].json;\nif (row.draft_id !== 'md-demo-001') throw new Error('draft_id_invalid');\nif (typeof row.markdown !== 'string' || !row.markdown.trim()) {\n  throw new Error('markdown_text_required');\n}\nif (Buffer.byteLength(row.markdown, 'utf8') > 16384) throw new Error('markdown_too_large');\nreturn [{ json: { draft_id: row.draft_id, markdown: row.markdown } }];"
      }
    },
    {
      "id": "render",
      "name": "Render HTML",
      "type": "n8n-nodes-base.markdown",
      "typeVersion": 1,
      "position": [
        900,
        300
      ],
      "parameters": {
        "mode": "markdownToHtml",
        "markdown": "={{ $json.markdown }}",
        "destinationKey": "html",
        "options": {
          "headerLevelStart": 2,
          "tables": true,
          "noHeaderId": true,
          "completeHTMLDocument": false,
          "ghCodeBlocks": true,
          "simpleLineBreaks": false
        }
      }
    },
    {
      "id": "check-html",
      "name": "Check HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('one_html_item_required');\nconst row = items[0].json;\nconst original = $('Check Draft').first().json;\nif (Object.keys(row).sort().join('|') !== 'draft_id|html|markdown') {\n  throw new Error('html_fields_mismatch');\n}\nif (row.draft_id !== original.draft_id || row.markdown !== original.markdown) {\n  throw new Error('draft_changed');\n}\nif (typeof row.html !== 'string' || !row.html.trim() || row.html === row.markdown) {\n  throw new Error('html_text_required');\n}\nif (Buffer.byteLength(row.html, 'utf8') > 32768) throw new Error('html_too_large');\nreturn items;"
      }
    },
    {
      "id": "inspect",
      "name": "Inspect HTML",
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        1340,
        300
      ],
      "parameters": {
        "operation": "extractHtmlContent",
        "sourceData": "json",
        "dataPropertyName": "html",
        "extractionValues": {
          "values": [
            {
              "key": "headings",
              "cssSelector": "h2",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "sections",
              "cssSelector": "h3",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "steps",
              "cssSelector": "ol > li",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "strong",
              "cssSelector": "strong",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "headers",
              "cssSelector": "th",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "cells",
              "cssSelector": "td",
              "returnValue": "text",
              "returnArray": true
            },
            {
              "key": "links",
              "cssSelector": "a",
              "returnValue": "attribute",
              "attribute": "href",
              "returnArray": true
            }
          ]
        },
        "options": {
          "trimValues": true,
          "cleanUpText": true
        }
      }
    },
    {
      "id": "draft-preview",
      "name": "Draft Preview",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1560,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('one_inspection_required');\nconst row = items[0].json;\nconst expected = {\n  headings: ['Учебная сводка'],\n  sections: ['Следующие шаги', 'Проверка пакета'],\n  steps: ['Проверить цифры.', 'Согласовать текст.'],\n  strong: ['Статус:'],\n  headers: ['Этап', 'Статус'],\n  cells: ['Проверка', 'Готово', 'Отправка', 'Не выполнена'],\n  links: ['https://ezgpt.ru/glossary'],\n};\nfor (const [key, value] of Object.entries(expected)) {\n  if (JSON.stringify(row[key]) !== JSON.stringify(value)) throw new Error(key + '_mismatch');\n}\nconst rendered = $('Check HTML').first().json;\nreturn [{ json: {\n  draft_id: rendered.draft_id,\n  status: 'needs_review',\n  html: rendered.html,\n  checks: { heading_h2: 1, sections_h3: 2, ordered_steps: 2, table_rows: 2, links: 1 },\n  approved: false,\n  action_performed: false,\n} }];"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Sample Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample Draft": {
      "main": [
        [
          {
            "node": "Check Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Draft": {
      "main": [
        [
          {
            "node": "Render HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Render HTML": {
      "main": [
        [
          {
            "node": "Check HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check HTML": {
      "main": [
        [
          {
            "node": "Inspect HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Inspect HTML": {
      "main": [
        [
          {
            "node": "Draft Preview",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataSuccessExecution": "all",
    "saveDataErrorExecution": "all"
  },
  "pinData": {}
}
