Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| from pathlib import Path | |
| import re | |
| ROOT = Path(__file__).resolve().parents[1] | |
| TEMPLATE_ROOT = ROOT / "modules/chart_engine/template/d3-js" | |
| DRAW_VERTICAL = ''' chartUtils.legend.draw(svg, groups, { | |
| color: group => groupColors[group], | |
| colorResolver, | |
| colors, | |
| }, { | |
| x: size - 150, | |
| y: 50, | |
| direction: "vertical", | |
| markerShape: "rect", | |
| markerSize: 15, | |
| labelGap: 5, | |
| rowGap: 10, | |
| itemHeight: 25, | |
| fontSize: typography.label.font_size, | |
| fontFamily: typography.label.font_family, | |
| fontWeight: typography.label.font_weight, | |
| textColor: colorResolver.text({ fallback: "#333333" }).value, | |
| });''' | |
| BOXED_RADIAL = ''' chartUtils.legend.boxedVertical(svg, legendItems, { | |
| color: d => getColor(d), | |
| colorResolver, | |
| colors, | |
| }, { | |
| x: legendX, | |
| y: legendY, | |
| padding: legendPadding, | |
| itemHeight: legendItemHeight, | |
| markerSize: 15, | |
| labelGap: 10, | |
| fontSize: 12, | |
| textColor: colorResolver.text({ fallback: "#333333" }).value, | |
| });''' | |
| ROSE_DRAW = ''' chartUtils.legend.draw(svg, groups, { | |
| colorScale, | |
| colorResolver, | |
| colors, | |
| }, { | |
| y: 15, | |
| maxWidth: width - 40, | |
| align: "center", | |
| markerShape: "circle", | |
| markerSize: 12, | |
| labelGap: 5, | |
| itemGap: 15, | |
| rowGap: 5, | |
| fontSize: 12, | |
| textColor: colorResolver.text({ fallback: "#333333" }).value, | |
| });''' | |
| GAUGE_DRAW = ''' chartUtils.legend.draw(svg, categoryData.map(d => d.category), { | |
| colorScale, | |
| colorResolver, | |
| colors, | |
| }, { | |
| y: 15, | |
| maxWidth: width - 40, | |
| align: "center", | |
| markerShape: "circle", | |
| markerSize: 12, | |
| labelGap: 5, | |
| itemGap: 15, | |
| rowGap: 5, | |
| fontSize: 12, | |
| textColor: colorResolver.text({ fallback: "#333" }).value, | |
| });''' | |
| def replace_block(text: str, start: str, end: str, replacement: str) -> str: | |
| i = text.find(start) | |
| if i < 0: | |
| return text | |
| j = text.find(end, i + len(start)) | |
| if j < 0: | |
| return text | |
| return text[:i] + replacement + text[j:] | |
| def migrate_labeled_strip(text: str, rel: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| markers = [ | |
| "// ---------- 11. 创建新样式图例", | |
| "// ---------- 9. 创建新样式图例", | |
| ] | |
| start = None | |
| for m in markers: | |
| if m in text: | |
| start = text.find(m) | |
| break | |
| if start is None: | |
| return text | |
| end_markers = ["return svg.node();", "// ---------- 9. 创建主图表组", "// ---------- 工具函数 ----------"] | |
| end = None | |
| for m in end_markers: | |
| pos = text.find(m, start) | |
| if pos > start: | |
| end = pos | |
| break | |
| if end is None: | |
| return text | |
| show_number = "horizontal_group_bar_chart_12" in rel | |
| pattern_fill = show_number | |
| width_expr = "width" if "width" in text[start:end] else "size" | |
| y_expr = "height - margin.bottom + 20" if "legendStartY = height" in text else "size - margin.bottom * 0.8 + 10" | |
| fill = ( | |
| "(group, index) => index % 2 === 0 ? \"url(#pattern-sketch-left)\" : \"url(#pattern-sketch-right)\"" | |
| if pattern_fill else "group => getGroupColor(group)" | |
| ) | |
| wrap = "wrapLabel: (node, label, w) => wrapText(node, label, w, 1.1)," if "function wrapText" in text else "" | |
| num = "showNumber: true," if show_number else "" | |
| font = ( | |
| "labelFontFamily: \"'Comic Sans MS', cursive\",\n" | |
| " numberFontFamily: \"'Comic Sans MS', cursive\"," | |
| if pattern_fill else | |
| "labelFontFamily: typography.annotation.font_family,\n" | |
| " numberFontFamily: typography.label.font_family," | |
| ) | |
| if not show_number and "grouped_circular" in rel: | |
| font = ( | |
| "labelFontFamily: typography.annotation.font_family,\n" | |
| " numberFontFamily: typography.label.font_family," | |
| ) | |
| num = "showNumber: true," | |
| replacement = ( | |
| f" const equalGroupRectWidth = Math.min(innerWidth / groups.length, {width_expr} * 0.8 / groups.length);\n" | |
| f" chartUtils.legend.labeledStrip(svg, groups.map((group, index) => ({{\n" | |
| f" label: group,\n" | |
| f" fill: {fill},\n" | |
| f" }})), {{\n" | |
| f" centerWidth: {width_expr},\n" | |
| f" y: {y_expr},\n" | |
| f" itemWidth: equalGroupRectWidth,\n" | |
| f" {num}\n" | |
| f" {font}\n" | |
| f" labelFontSize: 12,\n" | |
| f" textColor: colorResolver.text({{ fallback: \"#333333\" }}).value,\n" | |
| f" {wrap}\n" | |
| f" }});\n\n" | |
| ) | |
| return text[:start] + replacement + text[end:] | |
| def migrate_simple_vertical(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*// 添加图例\s*\n" | |
| r"\s*const legend = svg\.append\(\"g\"\)\s*\n" | |
| r"(?:\s*\.attr\(\"class\", \"other\"\)\s*\n)?" | |
| r"\s*\.attr\(\"transform\", `translate\(\$\{size - 150\}, 50\}\)`\);\s*\n" | |
| r"\s*groups\.forEach\(\(group, i\) => \{\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| return pattern.sub("\n" + DRAW_VERTICAL + "\n", text, count=1) | |
| def migrate_radial_boxed(text: str) -> str: | |
| if "chartUtils.legend." in text or "legendItemHeight = 20" not in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legend = svg\.append\(\"g\"\)\s*\n" | |
| r"\s*\.attr\(\"transform\", `translate\(\$\{legendX\}, \$\{legendY\}\)`\);\s*\n" | |
| r"\s*// 添加图例背景[\s\S]*?" | |
| r"\s*(?:stackedSeries|legendItems)\.forEach\(\([^)]+\) => \{\s*\n" | |
| r"\s*const legendItem = legend\.append\(\"g\"\)\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| return pattern.sub("\n" + BOXED_RADIAL + "\n", text, count=1) | |
| def migrate_step_line(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*// 添加图例 - 整体居中\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*legendGroup\.attr\(\"transform\", `translate\(\$\{\(chartWidth - totalLegendWidth\)/2\}, 60\}`\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n chartUtils.legend.stepLineCentered(g, {\n" | |
| " centerX: chartWidth / 2,\n" | |
| " y: 60,\n" | |
| " fieldName: dataColumns[1].label || dataColumns[1].name,\n" | |
| " areaColor,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_bump(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendGroup = g\.append\(\"g\"\)\s*\n" | |
| r"\s*\.attr\(\"class\", \"chart-legend\"\)\s*\n" | |
| r"\s*\.attr\(\"transform\", `translate\(\$\{legendStartX\}, \$\{legendY\}\)`\);\s*\n" | |
| r"\s*let currentLegendX = 0;\s*\n" | |
| r"\s*categoryGroups\.forEach\(\(cg, index\) => \{\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*currentLegendX \+= itemWidth \+ legendColumnPadding;\s*\n" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n chartUtils.legend.draw(g, categoryGroups, {\n" | |
| " color: cg => colorScale(cg),\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: legendStartX,\n" | |
| " y: legendY,\n" | |
| " maxWidth: innerWidth,\n" | |
| " fitToWidth: true,\n" | |
| " minFontSize: 8,\n" | |
| " markerShape: \"rect\",\n" | |
| " markerSize: legendSquareSize,\n" | |
| " labelGap: legendItemPadding,\n" | |
| " itemGap: legendColumnPadding,\n" | |
| " fontSize: finalLegendFontSize,\n" | |
| " fontFamily: legendFontFamily,\n" | |
| " fontWeight: legendFontWeight,\n" | |
| " textColor: legendColor,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_rose(text: str) -> str: | |
| if "chartUtils.legend." in text or "legendConfig.maxWidth" not in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendGroup = svg\.append\(\"g\"\)\.attr\(\"class\", \"other\"\);\s*\n" | |
| r"\s*const legendConfig = \{[\s\S]*?\n\s*tempText\.remove\(\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| return pattern.sub("\n" + ROSE_DRAW + "\n", text, count=1) | |
| def migrate_gauge_sm(text: str) -> str: | |
| if "chartUtils.legend." in text or "legendConfig.maxWidth" not in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendGroup = svg\.append\(\"g\"\)\.attr\(\"class\", \"other\"\);\s*\n" | |
| r"\s*const legendConfig = \{[\s\S]*?\n\s*tempText\.remove\(\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| return pattern.sub("\n" + GAUGE_DRAW + "\n", text, count=1) | |
| def migrate_type18(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendY = margin\.top - 30;[\s\S]*?" | |
| r"\s*currentX \+= legendWidths\[i\] \+ \(i < legendData\.length - 1 \? 5 : 0\);\s*\n" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n const legendY = margin.top - 30;\n" | |
| " chartUtils.legend.segmentsCentered(svg, [\n" | |
| " { type: \"rect\", size: 12, color: colorScale(categories[0]) },\n" | |
| " { type: \"rect\", size: 12, color: colorScale(categories[1]) },\n" | |
| " { type: \"text\", label: valueField },\n" | |
| " { type: \"circle\", size: 12, radius: 6, color: colorScale(categories[0]) },\n" | |
| " { type: \"text\", label: valueField2 },\n" | |
| " ], {\n" | |
| " centerX: margin.left + innerWidth / 2,\n" | |
| " y: legendY,\n" | |
| " itemGap: 5,\n" | |
| " sectionGap: 5,\n" | |
| " fontSize: 12,\n" | |
| " fontFamily: typography.annotation.font_family,\n" | |
| " textColor: colorResolver.text({ fallback: \"#333333\" }).value,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_vg7(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendY = margin\.top / 4\*3;[\s\S]*?" | |
| r"\s*\.text\(secondaryMetricName\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| s = "legendSquareSize" | |
| repl = ( | |
| f"\n const legendY = margin.top / 4 * 3;\n" | |
| f" const legendSquareSize = 12;\n" | |
| f" const swatchPath = size => [\n" | |
| f" `M0,0 L${{size}},0 L0,${{size}} Z`,\n" | |
| f" `M${{size}},${{size}} L0,${{size}} L${{size}},0 Z`,\n" | |
| f" ];\n" | |
| f" chartUtils.legend.segmentsCentered(svg, [\n" | |
| f" {{ type: \"path\", size: legendSquareSize, d: swatchPath(legendSquareSize)[0], color: legendG1Color1, transform: `translate(0, ${{-legendSquareSize / 2}})` }},\n" | |
| f" {{ type: \"path\", size: 0, d: swatchPath(legendSquareSize)[1], color: legendG1Color2, transform: `translate(0, ${{-legendSquareSize / 2}})` }},\n" | |
| f" {{ type: \"text\", label: primaryMetricName }},\n" | |
| f" {{ type: \"path\", size: legendSquareSize, d: swatchPath(legendSquareSize)[0], color: legendG1Color1, transform: `translate(0, ${{-legendSquareSize / 2}})` }},\n" | |
| f" {{ type: \"path\", size: 0, d: swatchPath(legendSquareSize)[1], color: legendG1Color2, transform: `translate(0, ${{-legendSquareSize / 2}})` }},\n" | |
| f" {{ type: \"text\", label: secondaryMetricName }},\n" | |
| f" ], {{\n" | |
| f" centerX: margin.left + innerWidth / 2,\n" | |
| f" y: legendY,\n" | |
| f" itemGap: legendItemPadding,\n" | |
| f" sectionGap: legendPadding,\n" | |
| f" fontSize: legendFontSize,\n" | |
| f" fontFamily: legendFontFamily,\n" | |
| f" fontWeight: legendFontWeight,\n" | |
| f" textColor: colorResolver.text({{ fallback: \"#000000\" }}).value,\n" | |
| f" }});\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_scatter(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendGroup = svg\.append\(\"g\"\)\.attr\(\"class\", \"chart-legend\"\);\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*currentX \+= legendSquareSize \+ legendItemPadding \+ textWidth \+ legendColumnPadding;\s*\n" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n const legendTitleText = groupField;\n" | |
| " const titleWidth = chartUtils.text.measure(svg, legendTitleText, {\n" | |
| " fontSize: legendFontSize + 1,\n" | |
| " fontFamily: legendFontFamily,\n" | |
| " fontWeight: \"bold\",\n" | |
| " }).width;\n" | |
| " const legendDraw = chartUtils.legend.draw(svg, groups, {\n" | |
| " color: group => colorScale(group),\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: margin.left + titleWidth + 15,\n" | |
| " y: legendY,\n" | |
| " markerShape: \"rect\",\n" | |
| " markerSize: legendSquareSize,\n" | |
| " labelGap: legendItemPadding,\n" | |
| " itemGap: legendColumnPadding,\n" | |
| " fontSize: legendFontSize,\n" | |
| " fontFamily: legendFontFamily,\n" | |
| " fontWeight: legendFontWeight,\n" | |
| " textColor: legendColor,\n" | |
| " });\n" | |
| " const legendBgWidth = titleWidth + 15 + legendDraw.width + 20;\n" | |
| " const legendBgHeight = legendSquareSize + 20;\n" | |
| " const legendBgX = margin.left - 10;\n" | |
| " const legendBgY = legendY - legendBgHeight / 2;\n" | |
| " const legendGroup = svg.insert(\"g\", \".chart-legend\").attr(\"class\", \"chart-legend\");\n" | |
| " legendGroup.append(\"rect\")\n" | |
| " .attr(\"class\", \"legend-background\")\n" | |
| " .attr(\"x\", legendBgX)\n" | |
| " .attr(\"y\", legendBgY)\n" | |
| " .attr(\"width\", legendBgWidth)\n" | |
| " .attr(\"height\", legendBgHeight)\n" | |
| " .attr(\"fill\", \"white\")\n" | |
| " .attr(\"stroke\", \"#ddd\")\n" | |
| " .attr(\"rx\", 4)\n" | |
| " .attr(\"ry\", 4);\n" | |
| " legendGroup.append(\"text\")\n" | |
| " .attr(\"class\", \"legend-title\")\n" | |
| " .attr(\"x\", margin.left)\n" | |
| " .attr(\"y\", legendY)\n" | |
| " .attr(\"dominant-baseline\", \"middle\")\n" | |
| " .style(\"font-family\", legendFontFamily)\n" | |
| " .style(\"font-size\", `${legendFontSize + 1}px`)\n" | |
| " .style(\"font-weight\", \"bold\")\n" | |
| " .style(\"fill\", legendColor)\n" | |
| " .text(legendTitleText);\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_proportional(text: str) -> str: | |
| if "chartUtils.legend." in text or "legendG.append" not in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendG = svg\.append\(\"g\"\)\s*\n" | |
| r"\s*\.attr\(\"class\", \"legend\"\)\s*\n" | |
| r"\s*\.attr\(\"transform\", `translate\(\$\{legendMargin\.left\}, \$\{legendMargin\.top\}\)`\);\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*legendItems\.forEach\(\(item, i\) => \{\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n const legendItemsForSide = uniqueCategories.map(category => ({\n" | |
| " label: category,\n" | |
| " color: categoryColors[category],\n" | |
| " raw: {\n" | |
| " imageHref: images.field && images.field[category] ? images.field[category] : null,\n" | |
| " },\n" | |
| " }));\n" | |
| " chartUtils.legend.sideDetail(svg, legendItemsForSide, {\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: legendMargin.left,\n" | |
| " y: legendMargin.top,\n" | |
| " fontSize: legendFontSize,\n" | |
| " fontFamily: legendFontFamily,\n" | |
| " textColor: colorResolver.text({ fallback: \"#333333\" }).value,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_stacked_area(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legendGroup = g\.append\(\"g\"\)\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*legendGroup\.attr\(\"transform\", `translate\(\$\{\(chartWidth - totalLegendWidth\)/2\}, 60\}`\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n chartUtils.legend.draw(g, groups, {\n" | |
| " color: group => getColor(group),\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: (chartWidth - chartUtils.legend.layout(groups, { color: group => getColor(group), colorResolver, colors, context: g, markerShape: \"line\", markerSize: 30 }).width) / 2,\n" | |
| " y: 60,\n" | |
| " markerShape: \"line\",\n" | |
| " markerSize: 30,\n" | |
| " labelGap: 10,\n" | |
| " itemGap: 20,\n" | |
| " fontSize: typography.label.font_size,\n" | |
| " fontFamily: typography.label.font_family,\n" | |
| " fontWeight: typography.label.font_weight,\n" | |
| " textColor: colorResolver.text({ fallback: \"#333333\" }).value,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_line_box(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| pattern = re.compile( | |
| r"\n\s*const legend = svg\.append\(\"g\"\)\s*\n" | |
| r"\s*\.attr\(\"transform\", `translate\(\$\{legendX\}, \$\{legendY\}\)`\);\s*\n" | |
| r"\s*legend\.append\(\"rect\"\)[\s\S]*?" | |
| r"\s*legendItems\.forEach\(\(item, i\) => \{\s*\n" | |
| r"[\s\S]*?" | |
| r"\s*\}\);\s*\n", | |
| re.MULTILINE, | |
| ) | |
| repl = ( | |
| "\n const legendLayout = chartUtils.legend.layout(legendItems, {\n" | |
| " color: item => getColor(item),\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " context: svg,\n" | |
| " direction: \"vertical\",\n" | |
| " markerShape: \"line\",\n" | |
| " markerSize: legendLineWidth,\n" | |
| " labelGap: legendTextOffset,\n" | |
| " rowGap: legendItemHeight,\n" | |
| " itemHeight: legendItemHeight,\n" | |
| " fontSize: typography.label.font_size,\n" | |
| " fontFamily: typography.label.font_family,\n" | |
| " });\n" | |
| " const legend = svg.append(\"g\").attr(\"transform\", `translate(${legendX}, ${legendY})`);\n" | |
| " legend.append(\"rect\")\n" | |
| " .attr(\"width\", legendWidth)\n" | |
| " .attr(\"height\", legendHeight)\n" | |
| " .attr(\"fill\", \"white\")\n" | |
| " .attr(\"stroke\", \"#ccc\")\n" | |
| " .attr(\"opacity\", 0.9);\n" | |
| " chartUtils.legend.draw(legend, legendItems, {\n" | |
| " color: item => getColor(item),\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: legendPadding,\n" | |
| " y: legendPadding,\n" | |
| " direction: \"vertical\",\n" | |
| " markerShape: \"line\",\n" | |
| " markerSize: legendLineWidth,\n" | |
| " labelGap: legendTextOffset,\n" | |
| " rowGap: legendItemSpacing,\n" | |
| " itemHeight: legendItemHeight,\n" | |
| " fontSize: typography.label.font_size,\n" | |
| " fontFamily: typography.label.font_family,\n" | |
| " fontWeight: typography.label.font_weight,\n" | |
| " textColor: colorResolver.text({ fallback: \"#333333\" }).value,\n" | |
| " });\n" | |
| ) | |
| return pattern.sub(repl, text, count=1) | |
| def migrate_vg4(text: str) -> str: | |
| if "chartUtils.legend." in text: | |
| return text | |
| if "legendItems.find" not in text: | |
| return text | |
| start = text.find("// 添加图例") | |
| if start < 0: | |
| start = text.find("const legendItems = [];") | |
| end = text.find("// ---------- 8.", start) | |
| if end < 0: | |
| end = text.find("return svg.node();", start) | |
| if start < 0 or end < 0: | |
| return text | |
| repl = ( | |
| " chartUtils.legend.draw(svg, legendItems.map(item => item.label), {\n" | |
| " color: (_, i) => legendItems[i].color,\n" | |
| " colorResolver,\n" | |
| " colors,\n" | |
| " }, {\n" | |
| " x: width - legendTotalWidth,\n" | |
| " y: margin.top - 50,\n" | |
| " direction: \"vertical\",\n" | |
| " markerShape: \"rect\",\n" | |
| " markerSize: legendRectSize,\n" | |
| " labelGap: spaceBetweenRectAndText,\n" | |
| " rowGap: legendItemHeight - legendRectSize,\n" | |
| " itemHeight: legendItemHeight,\n" | |
| " fontSize: typography.label.font_size,\n" | |
| " fontFamily: typography.label.font_family,\n" | |
| " fontWeight: typography.label.font_weight,\n" | |
| " textColor: colorResolver.text({ fallback: \"#333333\" }).value,\n" | |
| " });\n\n" | |
| ) | |
| pre = text[:start] | |
| post = text[end:] | |
| pre = re.sub( | |
| r"\n\s*const legendItems = \[\];\s*\n[\s\S]*?const legendTotalWidth = [^;]+;\s*\n", | |
| "\n const legendItems = [];\n group1Values.forEach(g1 => {\n group2Values.forEach(g2 => {\n legendItems.push({ label: `${g2} / ${g1}`, color: getColor(g1, g2) });\n });\n });\n const legendTotalWidth = 180;\n", | |
| pre, | |
| count=1, | |
| ) | |
| return pre + repl + post | |
| def process(path: Path) -> bool: | |
| original = path.read_text(encoding="utf-8") | |
| if "chartUtils.legend." in original: | |
| return False | |
| rel = str(path.relative_to(TEMPLATE_ROOT)) | |
| text = original | |
| text = migrate_labeled_strip(text, rel) | |
| text = migrate_simple_vertical(text) | |
| text = migrate_radial_boxed(text) | |
| text = migrate_step_line(text) | |
| text = migrate_bump(text) | |
| text = migrate_rose(text) | |
| text = migrate_gauge_sm(text) | |
| text = migrate_type18(text) | |
| text = migrate_vg7(text) | |
| text = migrate_scatter(text) | |
| text = migrate_proportional(text) | |
| text = migrate_stacked_area(text) | |
| text = migrate_line_box(text) | |
| text = migrate_vg4(text) | |
| if text != original: | |
| path.write_text(text, encoding="utf-8") | |
| return True | |
| return False | |
| def main() -> None: | |
| changed = [] | |
| for path in sorted(TEMPLATE_ROOT.rglob("*.js")): | |
| if process(path): | |
| changed.append(str(path.relative_to(TEMPLATE_ROOT))) | |
| print(f"migrated {len(changed)} files") | |
| for f in changed: | |
| print(f) | |
| if __name__ == "__main__": | |
| main() | |