{"spec_id":"barcode-code128","library":"d3","language":"javascript","code":"// anyplot.ai\n// barcode-code128: Code 128 Barcode\n// Library: d3 7.9.0 | JavaScript 22.23.2\n// Quality: 89/100 | Created: 2026-09-01\n\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\nconst { width, height } = window.ANYPLOT_SIZE;\n\n// --- Code 128 Subset B symbol table -----------------------------------------\n// Module-width patterns (bar,space,bar,space,bar,space) for symbol values\n// 0-102, plus Start A/B/C (103/104/105) and Stop (106). Subset B maps ASCII\n// 32-127 to values 0-95 via value = charCode - 32.\nconst CODE128_B = [\n  \"212222\", \"222122\", \"222221\", \"121223\", \"121322\",\n  \"131222\", \"122213\", \"122312\", \"132212\", \"221213\",\n  \"221312\", \"231212\", \"112232\", \"122132\", \"122231\",\n  \"113222\", \"123122\", \"123221\", \"223211\", \"221132\",\n  \"221231\", \"213212\", \"223112\", \"312131\", \"311222\",\n  \"321122\", \"321221\", \"312212\", \"322112\", \"322211\",\n  \"212123\", \"212321\", \"232121\", \"111323\", \"131123\",\n  \"131321\", \"112313\", \"132113\", \"132311\", \"211313\",\n  \"231113\", \"231311\", \"112133\", \"112331\", \"132131\",\n  \"113123\", \"113321\", \"133121\", \"313121\", \"211331\",\n  \"231131\", \"213113\", \"213311\", \"213131\", \"311123\",\n  \"311321\", \"331121\", \"312113\", \"312311\", \"332111\",\n  \"314111\", \"221411\", \"431111\", \"111224\", \"111422\",\n  \"121124\", \"121421\", \"141122\", \"141221\", \"112214\",\n  \"112412\", \"122114\", \"122411\", \"142112\", \"142211\",\n  \"241211\", \"221114\", \"413111\", \"241112\", \"134111\",\n  \"111242\", \"121142\", \"121241\", \"114212\", \"124112\",\n  \"124211\", \"411212\", \"421112\", \"421211\", \"212141\",\n  \"214121\", \"412121\", \"111143\", \"111341\", \"131141\",\n  \"114113\", \"114311\", \"411113\", \"411311\", \"113141\",\n  \"114131\", \"311141\", \"411131\", \"211412\", \"211214\",\n  \"211232\", \"2331112\",\n].map((pattern) => pattern.split(\"\").map(Number));\n\nconst START_B = 104;\nconst STOP = 106;\n\n// --- Data: encode a shipping-label style payload with Code Set B -----------\nconst content = \"SHIP-2024-ABC123\";\nconst dataValues = Array.from(content).map((ch) => ch.charCodeAt(0) - 32);\n\nlet checksum = START_B;\ndataValues.forEach((value, i) => {\n  checksum += value * (i + 1);\n});\nchecksum %= 103;\n\nconst symbolValues = [START_B, ...dataValues, checksum, STOP];\n\n// Flatten symbols into a sequence of bar/space elements (bar first, alternating)\nconst elements = symbolValues.flatMap((symbol) =>\n  CODE128_B[symbol].map((moduleWidth, i) => ({ moduleWidth, dark: i % 2 === 0 }))\n);\n\n// --- Layout ------------------------------------------------------------------\nconst QUIET_MODULES = 10; // minimum quiet zone per Code 128 spec, each side\nconst totalModules = elements.reduce((sum, e) => sum + e.moduleWidth, 0) + QUIET_MODULES * 2;\n\nconst marginX = 100;\nconst moduleSize = Math.floor((width - marginX * 2) / totalModules);\nconst barcodeWidth = moduleSize * totalModules;\nconst barcodeX = (width - barcodeWidth) / 2;\n\n// Shifted down from the top so the whitespace above the barcode block\n// balances the whitespace below the caption (see review feedback).\nconst barTop = 242;\nconst barHeight = 380;\n\n// --- SVG mount ----------------------------------------------------------------\nconst svg = d3.select(\"#container\").append(\"svg\").attr(\"width\", width).attr(\"height\", height);\n\n// --- Bars ---------------------------------------------------------------------\n// Bars use theme-adaptive ink (rather than a fixed data color) — the bar\n// pattern IS the encoded content, not a categorical series, so it follows\n// chrome contrast rules: dark ink on the light surface, light ink on the\n// dark surface, always maximally contrasted against the page background.\n// Module position (in module units, not pixels) maps to pixel-x through an\n// idiomatic D3 linear scale, rather than accumulating raw pixel offsets.\nconst moduleScale = d3.scaleLinear().domain([0, totalModules]).range([barcodeX, barcodeX + barcodeWidth]);\n\nlet modulePos = QUIET_MODULES;\nconst bars = [];\nfor (const el of elements) {\n  if (el.dark) {\n    bars.push({\n      x: moduleScale(modulePos),\n      w: moduleScale(modulePos + el.moduleWidth) - moduleScale(modulePos),\n    });\n  }\n  modulePos += el.moduleWidth;\n}\n\nsvg.selectAll(\"rect.bar\").data(bars).join(\"rect\")\n  .attr(\"class\", \"bar\")\n  .attr(\"x\", (d) => d.x)\n  .attr(\"y\", barTop)\n  .attr(\"width\", (d) => d.w)\n  .attr(\"height\", barHeight)\n  .attr(\"fill\", t.ink);\n\n// --- Human-readable text below the barcode -------------------------------\nsvg.append(\"text\")\n  .attr(\"x\", width / 2)\n  .attr(\"y\", barTop + barHeight + 56)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-family\", \"monospace\")\n  .style(\"font-size\", \"34px\")\n  .style(\"font-weight\", \"600\")\n  .style(\"letter-spacing\", \"6px\")\n  .text(content);\n\n// --- Caption: encoding metadata ------------------------------------------\nsvg.append(\"text\")\n  .attr(\"x\", width / 2)\n  .attr(\"y\", barTop + barHeight + 96)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"20px\")\n  .text(\n    `Code Set B · ${content.length} characters · check digit ${checksum} (mod 103) · ${symbolValues.length} symbols`\n  );\n\n// --- Title ---------------------------------------------------------------\nsvg.append(\"text\")\n  .attr(\"x\", width / 2)\n  .attr(\"y\", 60)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"22px\")\n  .style(\"font-weight\", \"600\")\n  .text(\"barcode-code128 · javascript · d3 · anyplot.ai\");\n"}