@planu/cli 0.55.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/license-plans.json +2 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts +7 -1
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts.map +1 -1
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js +16 -3
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js.map +1 -1
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts +5 -2
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts.map +1 -1
- package/dist/engine/doc-generator/executive-summary/html-template.js +7 -3
- package/dist/engine/doc-generator/executive-summary/html-template.js.map +1 -1
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts +5 -3
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts.map +1 -1
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.js +27 -6
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.js.map +1 -1
- package/dist/engine/doc-generator/portal/analytics-page.d.ts +8 -0
- package/dist/engine/doc-generator/portal/analytics-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/analytics-page.js +265 -0
- package/dist/engine/doc-generator/portal/analytics-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/architecture-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/architecture-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/architecture-page.js +250 -0
- package/dist/engine/doc-generator/portal/architecture-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/changelog-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/changelog-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/changelog-page.js +204 -0
- package/dist/engine/doc-generator/portal/changelog-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts +11 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js +24 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts +9 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js +31 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts +10 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js +77 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts +9 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js +31 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/decision-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/decision-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/decision-page.js +169 -0
- package/dist/engine/doc-generator/portal/decision-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts +8 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.js +131 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.js.map +1 -0
- package/dist/engine/doc-generator/portal/index.d.ts +19 -0
- package/dist/engine/doc-generator/portal/index.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/index.js +21 -0
- package/dist/engine/doc-generator/portal/index.js.map +1 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts +8 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.js +140 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts +27 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +139 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts +8 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.js +177 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-navbar.d.ts +15 -0
- package/dist/engine/doc-generator/portal/portal-navbar.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-navbar.js +143 -0
- package/dist/engine/doc-generator/portal/portal-navbar.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +22 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.js +58 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-theme.d.ts +7 -0
- package/dist/engine/doc-generator/portal/portal-theme.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-theme.js +53 -0
- package/dist/engine/doc-generator/portal/portal-theme.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts +5 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.js +80 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts +11 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.js +181 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-page.d.ts +7 -0
- package/dist/engine/doc-generator/portal/risk-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-page.js +219 -0
- package/dist/engine/doc-generator/portal/risk-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/roadmap-page.d.ts +7 -0
- package/dist/engine/doc-generator/portal/roadmap-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/roadmap-page.js +204 -0
- package/dist/engine/doc-generator/portal/roadmap-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts +4 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js +50 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts +16 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js +45 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts +16 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.js +159 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts +7 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js +52 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts +8 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +126 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.d.ts +10 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.js +93 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts +7 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js +31 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts +12 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.js +230 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts +8 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +32 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts +14 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +248 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts +13 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.js +423 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.d.ts +4 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.js +194 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.js.map +1 -0
- package/dist/engine/pdf/browser-finder.d.ts +5 -0
- package/dist/engine/pdf/browser-finder.d.ts.map +1 -0
- package/dist/engine/pdf/browser-finder.js +119 -0
- package/dist/engine/pdf/browser-finder.js.map +1 -0
- package/dist/engine/pdf/html-to-pdf.d.ts +3 -0
- package/dist/engine/pdf/html-to-pdf.d.ts.map +1 -0
- package/dist/engine/pdf/html-to-pdf.js +114 -0
- package/dist/engine/pdf/html-to-pdf.js.map +1 -0
- package/dist/engine/pdf/index.d.ts +6 -0
- package/dist/engine/pdf/index.d.ts.map +1 -0
- package/dist/engine/pdf/index.js +4 -0
- package/dist/engine/pdf/index.js.map +1 -0
- package/dist/engine/pdf/pdf-options.d.ts +6 -0
- package/dist/engine/pdf/pdf-options.d.ts.map +1 -0
- package/dist/engine/pdf/pdf-options.js +34 -0
- package/dist/engine/pdf/pdf-options.js.map +1 -0
- package/dist/engine/spec-summary-html.d.ts.map +1 -1
- package/dist/engine/spec-summary-html.js +17 -5
- package/dist/engine/spec-summary-html.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/export-pdf.d.ts +3 -0
- package/dist/tools/export-pdf.d.ts.map +1 -0
- package/dist/tools/export-pdf.js +82 -0
- package/dist/tools/export-pdf.js.map +1 -0
- package/dist/tools/generate-proposal.d.ts +3 -0
- package/dist/tools/generate-proposal.d.ts.map +1 -0
- package/dist/tools/generate-proposal.js +166 -0
- package/dist/tools/generate-proposal.js.map +1 -0
- package/dist/types/docs.d.ts +41 -0
- package/dist/types/docs.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/pdf.d.ts +42 -0
- package/dist/types/pdf.d.ts.map +1 -0
- package/dist/types/pdf.js +3 -0
- package/dist/types/pdf.js.map +1 -0
- package/dist/types/portal.d.ts +128 -0
- package/dist/types/portal.d.ts.map +1 -0
- package/dist/types/portal.js +3 -0
- package/dist/types/portal.js.map +1 -0
- package/dist/types/proposal.d.ts +57 -0
- package/dist/types/proposal.d.ts.map +1 -0
- package/dist/types/proposal.js +2 -0
- package/dist/types/proposal.js.map +1 -0
- package/package.json +1 -1
- package/src/config/license-plans.json +2 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { scaleLinear, svgText, CHART_COLORS, escapeXml } from './chart-utils.js';
|
|
2
|
+
const PADDING = { top: 40, right: 20, bottom: 50, left: 50 };
|
|
3
|
+
/**
|
|
4
|
+
* Build a responsive SVG line chart for one or two series.
|
|
5
|
+
* When a second series is passed via options it is drawn with a dashed line.
|
|
6
|
+
* Returns empty string when points array is empty.
|
|
7
|
+
*/
|
|
8
|
+
export function buildSvgLineChart(points, options) {
|
|
9
|
+
if (points.length === 0) {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
const vbW = options?.width ?? 500;
|
|
13
|
+
const vbH = options?.height ?? 300;
|
|
14
|
+
const title = options?.title ?? '';
|
|
15
|
+
const showDots = options?.showDots ?? true;
|
|
16
|
+
const innerW = vbW - PADDING.left - PADDING.right;
|
|
17
|
+
const innerH = vbH - PADDING.top - PADDING.bottom;
|
|
18
|
+
const xs = points.map((p) => p.x);
|
|
19
|
+
const ys = points.map((p) => p.y);
|
|
20
|
+
const minX = Math.min(...xs);
|
|
21
|
+
const maxX = Math.max(...xs, minX + 1);
|
|
22
|
+
const maxY = Math.max(...ys, 1);
|
|
23
|
+
const xScale = scaleLinear([minX, maxX], [0, innerW]);
|
|
24
|
+
const yScale = scaleLinear([0, maxY], [innerH, 0]);
|
|
25
|
+
const color0 = CHART_COLORS[0] ?? '#e94560';
|
|
26
|
+
const pathD = points
|
|
27
|
+
.map((p, i) => {
|
|
28
|
+
const px = (PADDING.left + xScale(p.x)).toFixed(1);
|
|
29
|
+
const py = (PADDING.top + yScale(p.y)).toFixed(1);
|
|
30
|
+
return `${i === 0 ? 'M' : 'L'} ${px} ${py}`;
|
|
31
|
+
})
|
|
32
|
+
.join(' ');
|
|
33
|
+
const dotsHtml = showDots
|
|
34
|
+
? points
|
|
35
|
+
.map((p) => {
|
|
36
|
+
const cx = (PADDING.left + xScale(p.x)).toFixed(1);
|
|
37
|
+
const cy = (PADDING.top + yScale(p.y)).toFixed(1);
|
|
38
|
+
const dotLabel = p.label
|
|
39
|
+
? svgText(Number(cx), Number(cy) - 8, p.label, {
|
|
40
|
+
fontSize: 9,
|
|
41
|
+
anchor: 'middle',
|
|
42
|
+
fill: '#6b7280',
|
|
43
|
+
})
|
|
44
|
+
: '';
|
|
45
|
+
return `<circle cx="${cx}" cy="${cy}" r="4" fill="${escapeXml(color0)}"/>${dotLabel}`;
|
|
46
|
+
})
|
|
47
|
+
.join('\n ')
|
|
48
|
+
: '';
|
|
49
|
+
const yTicks = buildYTicks(maxY, innerW, PADDING, innerH, yScale);
|
|
50
|
+
const xTicks = buildXTicks(points, xScale, PADDING, vbH);
|
|
51
|
+
const titleEl = title
|
|
52
|
+
? svgText(vbW / 2, 20, title, { fontSize: 13, anchor: 'middle', fill: '#1a1a2e' })
|
|
53
|
+
: '';
|
|
54
|
+
return `<svg viewBox="0 0 ${vbW} ${vbH}" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:${vbW}px">
|
|
55
|
+
${titleEl}
|
|
56
|
+
${yTicks}
|
|
57
|
+
${xTicks}
|
|
58
|
+
<path d="${pathD}" fill="none" stroke="${escapeXml(color0)}" stroke-width="2.5" stroke-linejoin="round"/>
|
|
59
|
+
${dotsHtml}
|
|
60
|
+
<line x1="${PADDING.left}" y1="${PADDING.top}" x2="${PADDING.left}" y2="${PADDING.top + innerH}" stroke="#e9ecef" stroke-width="1"/>
|
|
61
|
+
<line x1="${PADDING.left}" y1="${PADDING.top + innerH}" x2="${PADDING.left + innerW}" y2="${PADDING.top + innerH}" stroke="#e9ecef" stroke-width="1"/>
|
|
62
|
+
</svg>`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build a dual-series SVG line chart (real vs ideal).
|
|
66
|
+
* Returns empty string when either series is empty.
|
|
67
|
+
*/
|
|
68
|
+
export function buildSvgDualLineChart(series1, series2, options) {
|
|
69
|
+
if (series1.length === 0 && series2.length === 0) {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
const vbW = options?.width ?? 500;
|
|
73
|
+
const vbH = options?.height ?? 300;
|
|
74
|
+
const title = options?.title ?? '';
|
|
75
|
+
const showDots = options?.showDots ?? true;
|
|
76
|
+
const innerW = vbW - PADDING.left - PADDING.right;
|
|
77
|
+
const innerH = vbH - PADDING.top - PADDING.bottom;
|
|
78
|
+
const allPoints = [...series1, ...series2];
|
|
79
|
+
const xs = allPoints.map((p) => p.x);
|
|
80
|
+
const ys = allPoints.map((p) => p.y);
|
|
81
|
+
const minX = Math.min(...xs, 0);
|
|
82
|
+
const maxX = Math.max(...xs, minX + 1);
|
|
83
|
+
const maxY = Math.max(...ys, 1);
|
|
84
|
+
const xScale = scaleLinear([minX, maxX], [0, innerW]);
|
|
85
|
+
const yScale = scaleLinear([0, maxY], [innerH, 0]);
|
|
86
|
+
const color0 = CHART_COLORS[0] ?? '#e94560';
|
|
87
|
+
const color1 = CHART_COLORS[1] ?? '#0891b2';
|
|
88
|
+
const makePath = (pts, color, dashed) => {
|
|
89
|
+
if (pts.length === 0) {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
const d = pts
|
|
93
|
+
.map((p, i) => {
|
|
94
|
+
const px = (PADDING.left + xScale(p.x)).toFixed(1);
|
|
95
|
+
const py = (PADDING.top + yScale(p.y)).toFixed(1);
|
|
96
|
+
return `${i === 0 ? 'M' : 'L'} ${px} ${py}`;
|
|
97
|
+
})
|
|
98
|
+
.join(' ');
|
|
99
|
+
const dash = dashed ? ' stroke-dasharray="6 3"' : '';
|
|
100
|
+
return `<path d="${d}" fill="none" stroke="${escapeXml(color)}" stroke-width="2.5" stroke-linejoin="round"${dash}/>`;
|
|
101
|
+
};
|
|
102
|
+
const makeDots = (pts, color) => {
|
|
103
|
+
if (!showDots) {
|
|
104
|
+
return '';
|
|
105
|
+
}
|
|
106
|
+
return pts
|
|
107
|
+
.map((p) => {
|
|
108
|
+
const cx = (PADDING.left + xScale(p.x)).toFixed(1);
|
|
109
|
+
const cy = (PADDING.top + yScale(p.y)).toFixed(1);
|
|
110
|
+
return `<circle cx="${cx}" cy="${cy}" r="3" fill="${escapeXml(color)}"/>`;
|
|
111
|
+
})
|
|
112
|
+
.join('\n ');
|
|
113
|
+
};
|
|
114
|
+
const label1 = options?.label1 ?? 'Real';
|
|
115
|
+
const label2 = options?.label2 ?? 'Ideal';
|
|
116
|
+
const legendY = vbH - 8;
|
|
117
|
+
const legend = `${svgText(PADDING.left, legendY, label1, { fontSize: 10, anchor: 'start', fill: color0 })}
|
|
118
|
+
${svgText(PADDING.left + 80, legendY, label2, { fontSize: 10, anchor: 'start', fill: color1 })}`;
|
|
119
|
+
const yTicks = buildYTicks(maxY, innerW, PADDING, innerH, yScale);
|
|
120
|
+
const titleEl = title
|
|
121
|
+
? svgText(vbW / 2, 20, title, { fontSize: 13, anchor: 'middle', fill: '#1a1a2e' })
|
|
122
|
+
: '';
|
|
123
|
+
return `<svg viewBox="0 0 ${vbW} ${vbH}" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:${vbW}px">
|
|
124
|
+
${titleEl}
|
|
125
|
+
${yTicks}
|
|
126
|
+
${makePath(series1, color0, false)}
|
|
127
|
+
${makePath(series2, color1, true)}
|
|
128
|
+
${makeDots(series1, color0)}
|
|
129
|
+
${makeDots(series2, color1)}
|
|
130
|
+
${legend}
|
|
131
|
+
<line x1="${PADDING.left}" y1="${PADDING.top}" x2="${PADDING.left}" y2="${PADDING.top + innerH}" stroke="#e9ecef" stroke-width="1"/>
|
|
132
|
+
<line x1="${PADDING.left}" y1="${PADDING.top + innerH}" x2="${PADDING.left + innerW}" y2="${PADDING.top + innerH}" stroke="#e9ecef" stroke-width="1"/>
|
|
133
|
+
</svg>`;
|
|
134
|
+
}
|
|
135
|
+
function buildYTicks(maxVal, innerW, padding, _innerH, yScale) {
|
|
136
|
+
const tickCount = 4;
|
|
137
|
+
return Array.from({ length: tickCount + 1 }, (_, i) => {
|
|
138
|
+
const val = (maxVal / tickCount) * i;
|
|
139
|
+
const y = padding.top + yScale(val);
|
|
140
|
+
const label = Number.isInteger(val) ? String(val) : val.toFixed(1);
|
|
141
|
+
return `<line x1="${padding.left}" y1="${y.toFixed(1)}" x2="${(padding.left + innerW).toFixed(1)}" y2="${y.toFixed(1)}" stroke="#f3f4f6" stroke-width="1"/>
|
|
142
|
+
${svgText(padding.left - 6, y + 4, label, { fontSize: 9, anchor: 'end', fill: '#9ca3af' })}`;
|
|
143
|
+
}).join('\n ');
|
|
144
|
+
}
|
|
145
|
+
function buildXTicks(points, xScale, padding, vbH) {
|
|
146
|
+
const maxTicks = 6;
|
|
147
|
+
const step = Math.max(1, Math.ceil(points.length / maxTicks));
|
|
148
|
+
return points
|
|
149
|
+
.filter((_, i) => i % step === 0)
|
|
150
|
+
.map((p) => {
|
|
151
|
+
const x = padding.left + xScale(p.x);
|
|
152
|
+
const y = vbH - padding.bottom + 14;
|
|
153
|
+
const lbl = p.label ?? String(p.x);
|
|
154
|
+
const short = lbl.length > 8 ? lbl.slice(0, 7) + '…' : lbl;
|
|
155
|
+
return svgText(x, y, short, { fontSize: 9, anchor: 'middle', fill: '#9ca3af' });
|
|
156
|
+
})
|
|
157
|
+
.join('\n ');
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=line-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-chart.js","sourceRoot":"","sources":["../../../../../src/engine/doc-generator/portal/svg-charts/line-chart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PieSlice } from '../../../../types/portal.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a responsive SVG pie chart.
|
|
4
|
+
* Returns empty string when slices array is empty or all values are zero.
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildSvgPieChart(slices: PieSlice[], size?: number): string;
|
|
7
|
+
//# sourceMappingURL=pie-chart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../../../src/engine/doc-generator/portal/svg-charts/pie-chart.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAG5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CA0D1E"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { svgText, escapeXml } from './chart-utils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a responsive SVG pie chart.
|
|
4
|
+
* Returns empty string when slices array is empty or all values are zero.
|
|
5
|
+
*/
|
|
6
|
+
export function buildSvgPieChart(slices, size) {
|
|
7
|
+
if (slices.length === 0) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
const total = slices.reduce((s, p) => s + p.value, 0);
|
|
11
|
+
if (total === 0) {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
const vbSize = size ?? 220;
|
|
15
|
+
const cx = vbSize / 2;
|
|
16
|
+
const cy = vbSize / 2;
|
|
17
|
+
const r = (vbSize / 2) * 0.65;
|
|
18
|
+
let startAngle = -Math.PI / 2; // start at top
|
|
19
|
+
const paths = [];
|
|
20
|
+
for (const slice of slices) {
|
|
21
|
+
const angle = (slice.value / total) * 2 * Math.PI;
|
|
22
|
+
const endAngle = startAngle + angle;
|
|
23
|
+
const largeArc = angle > Math.PI ? 1 : 0;
|
|
24
|
+
const x1 = cx + r * Math.cos(startAngle);
|
|
25
|
+
const y1 = cy + r * Math.sin(startAngle);
|
|
26
|
+
const x2 = cx + r * Math.cos(endAngle);
|
|
27
|
+
const y2 = cy + r * Math.sin(endAngle);
|
|
28
|
+
const d = [
|
|
29
|
+
`M ${cx.toFixed(1)} ${cy.toFixed(1)}`,
|
|
30
|
+
`L ${x1.toFixed(2)} ${y1.toFixed(2)}`,
|
|
31
|
+
`A ${r.toFixed(1)} ${r.toFixed(1)} 0 ${largeArc} 1 ${x2.toFixed(2)} ${y2.toFixed(2)}`,
|
|
32
|
+
'Z',
|
|
33
|
+
].join(' ');
|
|
34
|
+
paths.push(`<path d="${d}" fill="${escapeXml(slice.color)}" stroke="white" stroke-width="1.5"/>`);
|
|
35
|
+
startAngle = endAngle;
|
|
36
|
+
}
|
|
37
|
+
// Legend below the pie
|
|
38
|
+
const legendItems = slices.map((s, i) => {
|
|
39
|
+
const lx = 8;
|
|
40
|
+
const ly = vbSize + 14 + i * 16;
|
|
41
|
+
const pct = ((s.value / total) * 100).toFixed(1);
|
|
42
|
+
const short = s.label.length > 20 ? s.label.slice(0, 19) + '…' : s.label;
|
|
43
|
+
return `<rect x="${lx}" y="${ly - 9}" width="10" height="10" fill="${escapeXml(s.color)}" rx="2"/>
|
|
44
|
+
${svgText(lx + 14, ly, `${short}: ${pct}%`, { fontSize: 10, anchor: 'start', fill: '#4b5563' })}`;
|
|
45
|
+
});
|
|
46
|
+
const totalHeight = vbSize + 14 + slices.length * 16;
|
|
47
|
+
return `<svg viewBox="0 0 ${vbSize} ${totalHeight}" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:${vbSize}px">
|
|
48
|
+
${paths.join('\n ')}
|
|
49
|
+
${legendItems.join('\n ')}
|
|
50
|
+
</svg>`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=pie-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-chart.js","sourceRoot":"","sources":["../../../../../src/engine/doc-generator/portal/svg-charts/pie-chart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Spec } from '../../../types/index.js';
|
|
2
|
+
import type { ProposalPhase } from '../../../types/docs.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build a CSS Grid Gantt chart from specs and optional phases.
|
|
5
|
+
* Returns an HTML string with the full Gantt visualization.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildGanttChart(specs: Spec[], phases?: ProposalPhase[], _startDate?: string): string;
|
|
8
|
+
//# sourceMappingURL=proposal-gantt-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-gantt-builder.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-gantt-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,wBAAwB,CAAC;AA6FtE;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,CAAC,EAAE,aAAa,EAAE,EACxB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAyCR"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const PHASE_COLORS = [
|
|
2
|
+
'#7c3aed',
|
|
3
|
+
'#0891b2',
|
|
4
|
+
'#059669',
|
|
5
|
+
'#d97706',
|
|
6
|
+
'#e94560',
|
|
7
|
+
'#6366f1',
|
|
8
|
+
'#0f766e',
|
|
9
|
+
'#b45309',
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* Assign specs to weeks using a simple sequential schedule with parallelism.
|
|
13
|
+
* Each spec duration = ceil(totalHours / 40) weeks (1 week = 40 dev hours).
|
|
14
|
+
*/
|
|
15
|
+
function assignWeeks(specs, phases) {
|
|
16
|
+
if (specs.length === 0) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const phaseColorMap = new Map();
|
|
20
|
+
if (phases && phases.length > 0) {
|
|
21
|
+
phases.forEach((p, i) => {
|
|
22
|
+
phaseColorMap.set(p.name, PHASE_COLORS[i % PHASE_COLORS.length] ?? '#7c3aed');
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
let currentWeek = 1;
|
|
26
|
+
const rows = [];
|
|
27
|
+
const specWeekMap = new Map();
|
|
28
|
+
// Build dependency map
|
|
29
|
+
const specMap = new Map(specs.map((s) => [s.id, s]));
|
|
30
|
+
for (const spec of specs) {
|
|
31
|
+
const totalHours = spec.estimation.devHours + spec.estimation.reviewHours;
|
|
32
|
+
const durationWeeks = Math.max(1, Math.ceil(totalHours / 40));
|
|
33
|
+
// Determine start: after all dependencies
|
|
34
|
+
let startWeek = currentWeek;
|
|
35
|
+
for (const dep of spec.dependencies) {
|
|
36
|
+
const depEnd = specWeekMap.get(dep)?.end ?? 0;
|
|
37
|
+
startWeek = Math.max(startWeek, depEnd + 1);
|
|
38
|
+
}
|
|
39
|
+
if (!spec.dependencies.length) {
|
|
40
|
+
startWeek = currentWeek;
|
|
41
|
+
}
|
|
42
|
+
specWeekMap.set(spec.id, { start: startWeek, end: startWeek + durationWeeks - 1 });
|
|
43
|
+
// Find phase name
|
|
44
|
+
let phaseName = 'Default';
|
|
45
|
+
let color = PHASE_COLORS[0] ?? '#7c3aed';
|
|
46
|
+
if (phases && phases.length > 0) {
|
|
47
|
+
const foundPhase = phases.find((p) => p.specIds.includes(spec.id));
|
|
48
|
+
if (foundPhase) {
|
|
49
|
+
phaseName = foundPhase.name;
|
|
50
|
+
const phaseIdx = phases.indexOf(foundPhase);
|
|
51
|
+
color = foundPhase.color ?? PHASE_COLORS[phaseIdx % PHASE_COLORS.length] ?? '#7c3aed';
|
|
52
|
+
phaseColorMap.set(phaseName, color);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Color by index
|
|
57
|
+
const idx = rows.length;
|
|
58
|
+
color = PHASE_COLORS[idx % PHASE_COLORS.length] ?? '#7c3aed';
|
|
59
|
+
}
|
|
60
|
+
rows.push({
|
|
61
|
+
id: spec.id,
|
|
62
|
+
label: `${spec.id}: ${spec.title.length > 30 ? spec.title.slice(0, 30) + '…' : spec.title}`,
|
|
63
|
+
color,
|
|
64
|
+
startWeek,
|
|
65
|
+
durationWeeks,
|
|
66
|
+
phase: phaseName,
|
|
67
|
+
});
|
|
68
|
+
// Advance current week only when no dependencies (sequential default)
|
|
69
|
+
if (!spec.dependencies.length) {
|
|
70
|
+
currentWeek = startWeek + durationWeeks;
|
|
71
|
+
}
|
|
72
|
+
// Cross-dep: track if we need to reset
|
|
73
|
+
const depSpec = specMap.get(spec.id);
|
|
74
|
+
if (!depSpec?.dependencies.length) {
|
|
75
|
+
currentWeek = startWeek + durationWeeks;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return rows;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Build a CSS Grid Gantt chart from specs and optional phases.
|
|
82
|
+
* Returns an HTML string with the full Gantt visualization.
|
|
83
|
+
*/
|
|
84
|
+
export function buildGanttChart(specs, phases, _startDate) {
|
|
85
|
+
if (specs.length === 0) {
|
|
86
|
+
return '';
|
|
87
|
+
}
|
|
88
|
+
const rows = assignWeeks(specs, phases);
|
|
89
|
+
if (rows.length === 0) {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
const totalWeeks = Math.max(...rows.map((r) => r.startWeek + r.durationWeeks - 1), 4);
|
|
93
|
+
// Week headers
|
|
94
|
+
const weekHeaders = Array.from({ length: totalWeeks }, (_, i) => `<div class="gantt-week">W${String(i + 1)}</div>`).join('');
|
|
95
|
+
// Gantt rows
|
|
96
|
+
const ganttRows = rows.map((row) => {
|
|
97
|
+
const startPct = ((row.startWeek - 1) / totalWeeks) * 100;
|
|
98
|
+
const widthPct = (row.durationWeeks / totalWeeks) * 100;
|
|
99
|
+
return `<div class="gantt-row">
|
|
100
|
+
<div class="gantt-label" title="${escapeHtml(row.label)}">${escapeHtml(row.label)}</div>
|
|
101
|
+
<div class="gantt-track">
|
|
102
|
+
<div class="gantt-bar" style="left:${startPct.toFixed(1)}%;width:${widthPct.toFixed(1)}%;background:${escapeHtml(row.color)};">
|
|
103
|
+
${String(row.durationWeeks)}w
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>`;
|
|
107
|
+
});
|
|
108
|
+
return `<div class="gantt-container">
|
|
109
|
+
<div class="gantt-header">
|
|
110
|
+
<div class="gantt-header-label"></div>
|
|
111
|
+
<div class="gantt-header-weeks">${weekHeaders}</div>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="gantt-grid">
|
|
114
|
+
${ganttRows.join('\n')}
|
|
115
|
+
</div>
|
|
116
|
+
</div>`;
|
|
117
|
+
}
|
|
118
|
+
// Internal helper
|
|
119
|
+
function escapeHtml(str) {
|
|
120
|
+
return str
|
|
121
|
+
.replace(/&/g, '&')
|
|
122
|
+
.replace(/</g, '<')
|
|
123
|
+
.replace(/>/g, '>')
|
|
124
|
+
.replace(/"/g, '"');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=proposal-gantt-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-gantt-builder.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-gantt-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProposalData } from '../../../types/docs.js';
|
|
2
|
+
/** Canonical section IDs for includeSections / excludeSections filtering. */
|
|
3
|
+
export declare const SECTION_IDS: readonly ["hero", "executive-summary", "scope", "spec-breakdown", "timeline", "budget", "investment-summary", "architecture", "risk", "decisions", "impact-analysis", "gap-analysis", "team-resources", "pricing-methodology", "design-system", "quality-metrics", "living-spec", "assumptions", "alternatives", "post-launch", "module-mapping"];
|
|
4
|
+
/**
|
|
5
|
+
* Generate a self-contained HTML proposal document.
|
|
6
|
+
* All sections are conditional — empty string returned when data is insufficient.
|
|
7
|
+
* Sections can be filtered via ProposalConfig.includeSections / excludeSections.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateProposal(data: ProposalData): string;
|
|
10
|
+
//# sourceMappingURL=proposal-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-generator.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,wBAAwB,CAAC;AA4BtE,6EAA6E;AAC7E,eAAO,MAAM,WAAW,mVAsBd,CAAC;AAwDX;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAoB3D"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { buildHeroSection, buildExecutiveSummarySection, buildScopeSection, buildSpecBreakdownSection, buildTimelineSection, buildBudgetSection, buildInvestmentSummarySection, buildArchitectureSection, buildRiskSection, buildDecisionsSection, buildImpactAnalysisSection, buildGapAnalysisSection, buildTeamResourcesSection, buildPricingMethodologySection, buildDesignSystemSection, buildQualityMetricsSection, buildLivingSpecSection, buildAssumptionsSection, buildAlternativesSection, buildPostLaunchSection, buildModuleMappingSection, buildFooterSection, } from './proposal-section-builders.js';
|
|
2
|
+
import { wrapProposalHtml } from './proposal-html-wrapper.js';
|
|
3
|
+
/** Canonical section IDs for includeSections / excludeSections filtering. */
|
|
4
|
+
export const SECTION_IDS = [
|
|
5
|
+
'hero',
|
|
6
|
+
'executive-summary',
|
|
7
|
+
'scope',
|
|
8
|
+
'spec-breakdown',
|
|
9
|
+
'timeline',
|
|
10
|
+
'budget',
|
|
11
|
+
'investment-summary',
|
|
12
|
+
'architecture',
|
|
13
|
+
'risk',
|
|
14
|
+
'decisions',
|
|
15
|
+
'impact-analysis',
|
|
16
|
+
'gap-analysis',
|
|
17
|
+
'team-resources',
|
|
18
|
+
'pricing-methodology',
|
|
19
|
+
'design-system',
|
|
20
|
+
'quality-metrics',
|
|
21
|
+
'living-spec',
|
|
22
|
+
'assumptions',
|
|
23
|
+
'alternatives',
|
|
24
|
+
'post-launch',
|
|
25
|
+
'module-mapping',
|
|
26
|
+
];
|
|
27
|
+
/** Build a section filter based on include/exclude lists. */
|
|
28
|
+
function makeSectionFilter(include, exclude) {
|
|
29
|
+
if (include && include.length > 0) {
|
|
30
|
+
return (id) => include.includes(id);
|
|
31
|
+
}
|
|
32
|
+
if (exclude && exclude.length > 0) {
|
|
33
|
+
return (id) => !exclude.includes(id);
|
|
34
|
+
}
|
|
35
|
+
return () => true;
|
|
36
|
+
}
|
|
37
|
+
function buildCoreSections(data, isEnabled) {
|
|
38
|
+
return [
|
|
39
|
+
isEnabled('executive-summary') ? buildExecutiveSummarySection(data) : '',
|
|
40
|
+
isEnabled('scope') ? buildScopeSection(data) : '',
|
|
41
|
+
isEnabled('spec-breakdown') ? buildSpecBreakdownSection(data) : '',
|
|
42
|
+
isEnabled('timeline') ? buildTimelineSection(data) : '',
|
|
43
|
+
isEnabled('budget') ? buildBudgetSection(data) : '',
|
|
44
|
+
isEnabled('investment-summary') ? buildInvestmentSummarySection(data) : '',
|
|
45
|
+
isEnabled('architecture') ? buildArchitectureSection(data) : '',
|
|
46
|
+
isEnabled('risk') ? buildRiskSection(data) : '',
|
|
47
|
+
isEnabled('decisions') ? buildDecisionsSection(data) : '',
|
|
48
|
+
isEnabled('impact-analysis') ? buildImpactAnalysisSection(data) : '',
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
function buildAdvancedSections(data, isEnabled) {
|
|
52
|
+
return [
|
|
53
|
+
isEnabled('gap-analysis') ? buildGapAnalysisSection(data) : '',
|
|
54
|
+
isEnabled('team-resources') ? buildTeamResourcesSection(data) : '',
|
|
55
|
+
isEnabled('pricing-methodology') ? buildPricingMethodologySection(data) : '',
|
|
56
|
+
isEnabled('design-system') ? buildDesignSystemSection(data) : '',
|
|
57
|
+
isEnabled('quality-metrics') ? buildQualityMetricsSection(data) : '',
|
|
58
|
+
isEnabled('living-spec') ? buildLivingSpecSection(data) : '',
|
|
59
|
+
isEnabled('assumptions') ? buildAssumptionsSection(data) : '',
|
|
60
|
+
isEnabled('alternatives') ? buildAlternativesSection(data) : '',
|
|
61
|
+
isEnabled('post-launch') ? buildPostLaunchSection(data) : '',
|
|
62
|
+
isEnabled('module-mapping') ? buildModuleMappingSection(data) : '',
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
/** Build all content sections (everything except hero and footer). */
|
|
66
|
+
function buildContentSections(data, isEnabled) {
|
|
67
|
+
return [...buildCoreSections(data, isEnabled), ...buildAdvancedSections(data, isEnabled)]
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.join('\n');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Generate a self-contained HTML proposal document.
|
|
73
|
+
* All sections are conditional — empty string returned when data is insufficient.
|
|
74
|
+
* Sections can be filtered via ProposalConfig.includeSections / excludeSections.
|
|
75
|
+
*/
|
|
76
|
+
export function generateProposal(data) {
|
|
77
|
+
const { includeSections, excludeSections, theme, language } = data.config;
|
|
78
|
+
const isEnabled = makeSectionFilter(includeSections, excludeSections);
|
|
79
|
+
const hero = isEnabled('hero') ? buildHeroSection(data) : '';
|
|
80
|
+
const contentSections = buildContentSections(data, isEnabled);
|
|
81
|
+
const body = [
|
|
82
|
+
hero,
|
|
83
|
+
contentSections ? `<div class="content">\n${contentSections}\n</div>` : '',
|
|
84
|
+
buildFooterSection(data),
|
|
85
|
+
]
|
|
86
|
+
.filter(Boolean)
|
|
87
|
+
.join('\n');
|
|
88
|
+
const docTitle = data.config.title ?? data.projectName;
|
|
89
|
+
const docTheme = theme ?? 'light';
|
|
90
|
+
const docLang = language ?? 'en';
|
|
91
|
+
return wrapProposalHtml(docTitle, body, docTheme, docLang);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=proposal-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-generator.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ProposalTheme } from './proposal-themes.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap body content in a full self-contained HTML document for the proposal.
|
|
4
|
+
* Includes inline CSS (theme), print styles, and responsive layout.
|
|
5
|
+
*/
|
|
6
|
+
export declare function wrapProposalHtml(title: string, bodyContent: string, theme?: ProposalTheme, lang?: string): string;
|
|
7
|
+
//# sourceMappingURL=proposal-html-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-html-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-html-wrapper.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,aAAuB,EAC9B,IAAI,SAAO,GACV,MAAM,CAsBR"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Planu — HTML wrapper for project proposal documents
|
|
2
|
+
import { getProposalThemeCSS } from './proposal-themes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Wrap body content in a full self-contained HTML document for the proposal.
|
|
5
|
+
* Includes inline CSS (theme), print styles, and responsive layout.
|
|
6
|
+
*/
|
|
7
|
+
export function wrapProposalHtml(title, bodyContent, theme = 'light', lang = 'en') {
|
|
8
|
+
const escapedTitle = title
|
|
9
|
+
.replace(/&/g, '&')
|
|
10
|
+
.replace(/</g, '<')
|
|
11
|
+
.replace(/>/g, '>')
|
|
12
|
+
.replace(/"/g, '"');
|
|
13
|
+
const css = getProposalThemeCSS(theme);
|
|
14
|
+
return `<!DOCTYPE html>
|
|
15
|
+
<html lang="${escapeAttr(lang)}">
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="UTF-8"/>
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
19
|
+
<meta name="generator" content="Planu — Spec Driven Development"/>
|
|
20
|
+
<title>${escapedTitle}</title>
|
|
21
|
+
<style>${css}</style>
|
|
22
|
+
</head>
|
|
23
|
+
<body>
|
|
24
|
+
${bodyContent}
|
|
25
|
+
</body>
|
|
26
|
+
</html>`;
|
|
27
|
+
}
|
|
28
|
+
function escapeAttr(str) {
|
|
29
|
+
return str.replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=proposal-html-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-html-wrapper.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-html-wrapper.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,mBAAmB,EAAsB,MAAM,sBAAsB,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,WAAmB,EACnB,QAAuB,OAAO,EAC9B,IAAI,GAAG,IAAI;IAEX,MAAM,YAAY,GAAG,KAAK;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE3B,MAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAEvC,OAAO;cACK,UAAU,CAAC,IAAI,CAAC;;;;;WAKnB,YAAY;WACZ,GAAG;;;EAGZ,WAAW;;QAEL,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ProposalLang, TranslationKey } from '../../../types/docs.js';
|
|
2
|
+
export type { ProposalLang, TranslationKey };
|
|
3
|
+
/**
|
|
4
|
+
* Get all translation strings for the given language.
|
|
5
|
+
* Falls back to English for unknown keys.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getTranslations(lang?: string): Record<TranslationKey, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Translate a single key.
|
|
10
|
+
*/
|
|
11
|
+
export declare function t(lang: string, key: string): string;
|
|
12
|
+
//# sourceMappingURL=proposal-i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-i18n.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/proposal/proposal-i18n.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE3E,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC;AA6N7C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAO,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAE3E;AAED;;GAEG;AACH,wBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD"}
|