{"spec_id":"barcode-ean13","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// barcode-ean13: EAN-13 Barcode\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 87/100 | Created: 2026-09-01\n\nconst t = window.ANYPLOT_TOKENS;\n\n// A physical barcode's marks must stay dark-on-light regardless of display\n// theme to remain machine-scannable — fixed, not theme-adaptive like chrome.\nconst BARCODE_INK = \"#1A1A17\";\nconst BARCODE_CARD = \"#FAF8F1\";\n\n// --- EAN-13 encoding tables (GS1 standard) ----------------------------------\nconst L_CODE = [\n  \"0001101\", \"0011001\", \"0010011\", \"0111101\", \"0100011\",\n  \"0110001\", \"0101111\", \"0111011\", \"0110111\", \"0001011\",\n];\nconst G_CODE = [\n  \"0100111\", \"0110011\", \"0011011\", \"0100001\", \"0011101\",\n  \"0111001\", \"0000101\", \"0010001\", \"0001001\", \"0010111\",\n];\nconst R_CODE = L_CODE.map((pattern) => pattern.replace(/[01]/g, (bit) => (bit === \"0\" ? \"1\" : \"0\")));\nconst PARITY_TABLE = [\n  \"LLLLLL\", \"LLGLGG\", \"LLGGLG\", \"LLGGGL\", \"LGLLGG\",\n  \"LGGLLG\", \"LGGGLL\", \"LGLGLG\", \"LGLGGL\", \"LGGLGL\",\n];\n\nfunction checkDigit(twelveDigits) {\n  const sum = twelveDigits.reduce((total, digit, i) => total + digit * (i % 2 === 0 ? 1 : 3), 0);\n  return (10 - (sum % 10)) % 10;\n}\n\nfunction encodeEAN13(digits) {\n  const parity = PARITY_TABLE[digits[0]];\n  const leftDigits = digits.slice(1, 7);\n  const rightDigits = digits.slice(7, 13);\n  const modules = [1, 0, 1]; // start guard\n  leftDigits.forEach((digit, i) => {\n    const pattern = parity[i] === \"L\" ? L_CODE[digit] : G_CODE[digit];\n    pattern.split(\"\").forEach((bit) => modules.push(Number(bit)));\n  });\n  modules.push(0, 1, 0, 1, 0); // center guard\n  rightDigits.forEach((digit) => {\n    R_CODE[digit].split(\"\").forEach((bit) => modules.push(Number(bit)));\n  });\n  modules.push(1, 0, 1); // end guard\n  return modules;\n}\n\n// --- Data: a specialty-tea retail product code ------------------------------\nconst productCode = [8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\nconst digits = [...productCode, checkDigit(productCode)];\nconst modules = encodeEAN13(digits);\n\nconst START_GUARD = new Set([0, 1, 2]);\nconst CENTER_GUARD = new Set([45, 46, 47, 48, 49]);\nconst END_GUARD = new Set([92, 93, 94]);\nconst DIGIT_HEIGHT = 1.0;\nconst GUARD_HEIGHT = 1.15;\nconst MAX_HEIGHT = GUARD_HEIGHT;\n\nconst barData = modules.map((bit, i) => {\n  const isGuard = START_GUARD.has(i) || CENTER_GUARD.has(i) || END_GUARD.has(i);\n  const height = isGuard ? GUARD_HEIGHT : DIGIT_HEIGHT;\n  return { x: i, y: bit ? height : 0 };\n});\nconst spacerData = modules.map((bit, i) => {\n  const isGuard = START_GUARD.has(i) || CENTER_GUARD.has(i) || END_GUARD.has(i);\n  const height = isGuard ? GUARD_HEIGHT : DIGIT_HEIGHT;\n  return { x: i, y: bit ? MAX_HEIGHT - height : MAX_HEIGHT };\n});\n\n// Human-readable digits: leading digit stands alone in the left quiet zone,\n// the remaining 12 digits center under their own 7-module encoding block.\nconst digitLabels = [{ x: -5, text: String(digits[0]) }];\nfor (let i = 0; i < 6; i += 1) {\n  digitLabels.push({ x: 3 + 7 * i + 3.5, text: String(digits[1 + i]) });\n}\nfor (let j = 0; j < 6; j += 1) {\n  digitLabels.push({ x: 50 + 7 * j + 3.5, text: String(digits[7 + j]) });\n}\n\n// --- Chart -------------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"column\",\n    backgroundColor: \"transparent\",\n    plotBackgroundColor: BARCODE_CARD,\n    plotBorderWidth: 0,\n    plotShadow: false,\n    animation: false,\n    marginBottom: 90,\n    style: { fontFamily: \"inherit\" },\n  },\n  credits: { enabled: false },\n  title: {\n    text: \"barcode-ean13 · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n    margin: 30,\n  },\n  xAxis: {\n    min: -13,\n    max: 106,\n    visible: false,\n  },\n  yAxis: {\n    min: 0,\n    max: MAX_HEIGHT,\n    visible: false,\n    reversedStacks: false,\n  },\n  legend: { enabled: false },\n  tooltip: { enabled: false },\n  plotOptions: {\n    column: {\n      stacking: \"normal\",\n      pointPadding: 0,\n      groupPadding: 0,\n      borderWidth: 0,\n      pointRange: 1,\n      animation: false,\n    },\n    series: { animation: false, enableMouseTracking: false },\n  },\n  series: [\n    {\n      name: \"Quiet space\",\n      type: \"column\",\n      data: spacerData,\n      color: \"transparent\",\n      dataLabels: { enabled: false },\n    },\n    {\n      name: \"Bars\",\n      type: \"column\",\n      data: barData,\n      color: BARCODE_INK,\n      dataLabels: { enabled: false },\n    },\n    {\n      name: \"Digits\",\n      type: \"scatter\",\n      data: digitLabels.map((d) => ({ x: d.x, y: 0, name: d.text })),\n      marker: { enabled: false },\n      dataLabels: {\n        enabled: true,\n        format: \"{point.name}\",\n        crop: false,\n        overflow: \"allow\",\n        verticalAlign: \"bottom\",\n        y: 34,\n        align: \"center\",\n        style: {\n          color: t.inkSoft,\n          fontSize: \"20px\",\n          fontWeight: \"500\",\n          textOutline: \"none\",\n        },\n      },\n    },\n  ],\n});\n"}