@lotics/xlsx 0.1.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/package.json +30 -0
- package/src/auto_sum.test.ts +71 -0
- package/src/auto_sum.ts +83 -0
- package/src/canvas_cf.ts +135 -0
- package/src/canvas_chart.ts +687 -0
- package/src/canvas_fill.ts +156 -0
- package/src/canvas_images.ts +99 -0
- package/src/canvas_layout.test.ts +159 -0
- package/src/canvas_layout.ts +239 -0
- package/src/canvas_renderer.ts +1010 -0
- package/src/canvas_shape.ts +242 -0
- package/src/canvas_sparkline.ts +163 -0
- package/src/canvas_text.ts +454 -0
- package/src/cell_editor.ts +558 -0
- package/src/clipboard.test.ts +145 -0
- package/src/clipboard.ts +341 -0
- package/src/command_history.ts +102 -0
- package/src/csv_parser.test.ts +130 -0
- package/src/csv_parser.ts +172 -0
- package/src/data_validation.test.ts +95 -0
- package/src/data_validation.ts +114 -0
- package/src/editing_layer.test.ts +309 -0
- package/src/excel_cf_evaluate.test.ts +293 -0
- package/src/excel_cf_evaluate.ts +719 -0
- package/src/excel_cf_icons.ts +108 -0
- package/src/excel_cf_types.ts +67 -0
- package/src/excel_numfmt.test.ts +607 -0
- package/src/excel_numfmt.ts +1033 -0
- package/src/excel_parser.test.ts +1061 -0
- package/src/excel_parser.ts +393 -0
- package/src/excel_pattern_fills.ts +64 -0
- package/src/excel_table_styles.ts +160 -0
- package/src/excel_utils.test.ts +108 -0
- package/src/excel_utils.ts +162 -0
- package/src/fast-formula-parser.d.ts +53 -0
- package/src/fill_logic.ts +257 -0
- package/src/fill_patterns.test.ts +90 -0
- package/src/fill_patterns.ts +71 -0
- package/src/flash_fill.test.ts +75 -0
- package/src/flash_fill.ts +221 -0
- package/src/formula_deps.ts +189 -0
- package/src/formula_engine.test.ts +348 -0
- package/src/formula_engine.ts +401 -0
- package/src/formula_highlight.test.ts +81 -0
- package/src/formula_highlight.ts +139 -0
- package/src/formula_suggest.ts +100 -0
- package/src/hidden_sheets.test.ts +49 -0
- package/src/index.ts +149 -0
- package/src/keyboard_nav.test.ts +394 -0
- package/src/keyboard_nav.ts +891 -0
- package/src/move_logic.ts +63 -0
- package/src/numfmt_type.test.ts +158 -0
- package/src/numfmt_type.ts +231 -0
- package/src/ooxml_cell_format.ts +70 -0
- package/src/ooxml_chart.test.ts +85 -0
- package/src/ooxml_chart.ts +347 -0
- package/src/ooxml_chart_types.ts +207 -0
- package/src/ooxml_color.ts +339 -0
- package/src/ooxml_drawing.test.ts +87 -0
- package/src/ooxml_drawing.ts +287 -0
- package/src/ooxml_pivot.test.ts +195 -0
- package/src/ooxml_pivot.ts +468 -0
- package/src/ooxml_pivot_types.ts +165 -0
- package/src/ooxml_shape.ts +355 -0
- package/src/ooxml_sheet.ts +1271 -0
- package/src/ooxml_styles.ts +556 -0
- package/src/ooxml_table.test.ts +70 -0
- package/src/ooxml_table.ts +131 -0
- package/src/ooxml_workbook.test.ts +40 -0
- package/src/ooxml_workbook.ts +259 -0
- package/src/ooxml_zip.ts +33 -0
- package/src/pivot_model.ts +237 -0
- package/src/pivot_recompute.test.ts +210 -0
- package/src/pivot_recompute.ts +413 -0
- package/src/selection_model.ts +364 -0
- package/src/spreadsheet_commands.test.ts +772 -0
- package/src/spreadsheet_commands.ts +1805 -0
- package/src/structured_refs.test.ts +128 -0
- package/src/structured_refs.ts +160 -0
- package/src/style_helpers.test.ts +33 -0
- package/src/style_helpers.ts +30 -0
- package/src/template_builder.test.ts +139 -0
- package/src/template_builder.ts +36 -0
- package/src/types.ts +239 -0
- package/src/workbook_model.test.ts +536 -0
- package/src/workbook_model.ts +911 -0
- package/src/xlsx_round_trip.test.ts +279 -0
- package/src/xlsx_writer.test.ts +488 -0
- package/src/xlsx_writer.ts +1549 -0
- package/src/xml_entities.ts +23 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline SVG icons for conditional formatting icon sets.
|
|
3
|
+
* Each icon is a small 16x16 SVG returned as a data URI.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const SVG_PREFIX = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">';
|
|
7
|
+
const SVG_SUFFIX = "</svg>";
|
|
8
|
+
|
|
9
|
+
function svg(body: string): string {
|
|
10
|
+
return `data:image/svg+xml,${encodeURIComponent(SVG_PREFIX + body + SVG_SUFFIX)}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Arrow icons
|
|
14
|
+
const arrowUp = (color: string) => svg(`<path d="M8 2l5 8H3z" fill="${color}"/>`);
|
|
15
|
+
const arrowRight = (color: string) => svg(`<path d="M2 4h8l-4 8z" fill="${color}" transform="rotate(-90 8 8)"/>`);
|
|
16
|
+
const arrowDown = (color: string) => svg(`<path d="M8 14l5-8H3z" fill="${color}"/>`);
|
|
17
|
+
const arrowUpRight = (color: string) => svg(`<path d="M4 12L12 4M12 4H6M12 4v6" stroke="${color}" stroke-width="2" fill="none"/>`);
|
|
18
|
+
const arrowDownRight = (color: string) => svg(`<path d="M4 4L12 12M12 12H6M12 12V6" stroke="${color}" stroke-width="2" fill="none"/>`);
|
|
19
|
+
|
|
20
|
+
// Circle/traffic light icons
|
|
21
|
+
const circle = (color: string) => svg(`<circle cx="8" cy="8" r="6" fill="${color}"/>`);
|
|
22
|
+
|
|
23
|
+
// Flag icons
|
|
24
|
+
const flag = (color: string) => svg(`<path d="M3 2v12M3 2h8l-2 3 2 3H3" fill="${color}" stroke="${color}" stroke-width="1"/>`);
|
|
25
|
+
|
|
26
|
+
// Star icons
|
|
27
|
+
const star = (color: string) => svg(
|
|
28
|
+
`<path d="M8 1l2.2 4.5 5 .7-3.6 3.5.9 5L8 12.5 3.5 14.7l.9-5L0.8 6.2l5-.7z" fill="${color}"/>`,
|
|
29
|
+
);
|
|
30
|
+
const starEmpty = svg(
|
|
31
|
+
`<path d="M8 1l2.2 4.5 5 .7-3.6 3.5.9 5L8 12.5 3.5 14.7l.9-5L0.8 6.2l5-.7z" fill="none" stroke="#999" stroke-width="1"/>`,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// Diamond icons
|
|
35
|
+
const diamond = (color: string) => svg(`<path d="M8 1L15 8L8 15L1 8z" fill="${color}"/>`);
|
|
36
|
+
|
|
37
|
+
// Triangle icons
|
|
38
|
+
const triangleUp = (color: string) => svg(`<path d="M8 3l5 10H3z" fill="${color}"/>`);
|
|
39
|
+
const triangleDash = (color: string) => svg(`<rect x="2" y="6" width="12" height="4" rx="1" fill="${color}"/>`);
|
|
40
|
+
const triangleDown = (color: string) => svg(`<path d="M8 13l5-10H3z" fill="${color}"/>`);
|
|
41
|
+
|
|
42
|
+
// Quarter icons (pie chart segments)
|
|
43
|
+
const quarter0 = svg(`<circle cx="8" cy="8" r="6" fill="none" stroke="#666" stroke-width="1.5"/>`);
|
|
44
|
+
const quarter1 = svg(`<circle cx="8" cy="8" r="6" fill="none" stroke="#666" stroke-width="1.5"/><path d="M8 2a6 6 0 0 1 6 6H8z" fill="#666"/>`);
|
|
45
|
+
const quarter2 = svg(`<circle cx="8" cy="8" r="6" fill="none" stroke="#666" stroke-width="1.5"/><path d="M8 2a6 6 0 0 1 0 12V2z" fill="#666"/>`);
|
|
46
|
+
const quarter3 = svg(`<circle cx="8" cy="8" r="6" fill="none" stroke="#666" stroke-width="1.5"/><path d="M8 2a6 6 0 0 1 0 12A6 6 0 0 1 2 8h6z" fill="#666"/>`);
|
|
47
|
+
const quarter4 = svg(`<circle cx="8" cy="8" r="6" fill="#666"/>`);
|
|
48
|
+
|
|
49
|
+
// Box icons (rating bars)
|
|
50
|
+
const box = (fill: boolean) => fill
|
|
51
|
+
? svg(`<rect x="1" y="4" width="14" height="8" rx="1" fill="#666"/>`)
|
|
52
|
+
: svg(`<rect x="1" y="4" width="14" height="8" rx="1" fill="none" stroke="#999" stroke-width="1"/>`);
|
|
53
|
+
|
|
54
|
+
// Sign icons
|
|
55
|
+
const signTriangle = (color: string) => svg(`<path d="M8 2l6.5 12H1.5z" fill="${color}"/>`);
|
|
56
|
+
const signCircle = (color: string) => svg(`<circle cx="8" cy="8" r="7" fill="${color}"/>`);
|
|
57
|
+
|
|
58
|
+
// Symbol icons (check/exclamation/X)
|
|
59
|
+
const symbolCheck = (color: string) => svg(`<circle cx="8" cy="8" r="7" fill="${color}"/><path d="M4.5 8l2 2 5-5" stroke="white" stroke-width="2" fill="none"/>`);
|
|
60
|
+
const symbolExcl = (color: string) => svg(`<circle cx="8" cy="8" r="7" fill="${color}"/><text x="8" y="12" text-anchor="middle" fill="white" font-size="11" font-weight="bold">!</text>`);
|
|
61
|
+
const symbolX = (color: string) => svg(`<circle cx="8" cy="8" r="7" fill="${color}"/><path d="M5 5l6 6M11 5l-6 6" stroke="white" stroke-width="2"/>`);
|
|
62
|
+
|
|
63
|
+
// =============================================================================
|
|
64
|
+
// Icon set definitions
|
|
65
|
+
// =============================================================================
|
|
66
|
+
|
|
67
|
+
type IconSetDef = string[];
|
|
68
|
+
|
|
69
|
+
const ICON_SETS: Record<string, IconSetDef> = {
|
|
70
|
+
// 3-icon sets
|
|
71
|
+
"3Arrows": [arrowDown("#F44336"), arrowRight("#FFC107"), arrowUp("#4CAF50")],
|
|
72
|
+
"3ArrowsGray": [arrowDown("#666"), arrowRight("#999"), arrowUp("#333")],
|
|
73
|
+
"3Flags": [flag("#F44336"), flag("#FFC107"), flag("#4CAF50")],
|
|
74
|
+
"3Signs": [diamond("#F44336"), signTriangle("#FFC107"), signCircle("#4CAF50")],
|
|
75
|
+
"3Stars": [starEmpty, star("#FFC107"), star("#FFC107")],
|
|
76
|
+
"3Symbols": [symbolX("#F44336"), symbolExcl("#FFC107"), symbolCheck("#4CAF50")],
|
|
77
|
+
"3Symbols2": [symbolX("#F44336"), symbolExcl("#FFC107"), symbolCheck("#4CAF50")],
|
|
78
|
+
"3TrafficLights1": [circle("#F44336"), circle("#FFC107"), circle("#4CAF50")],
|
|
79
|
+
"3TrafficLights2": [circle("#F44336"), circle("#FFC107"), circle("#4CAF50")],
|
|
80
|
+
"3Triangles": [triangleDown("#F44336"), triangleDash("#FFC107"), triangleUp("#4CAF50")],
|
|
81
|
+
|
|
82
|
+
// 4-icon sets
|
|
83
|
+
"4Arrows": [arrowDown("#F44336"), arrowDownRight("#FF9800"), arrowUpRight("#FFC107"), arrowUp("#4CAF50")],
|
|
84
|
+
"4ArrowsGray": [arrowDown("#666"), arrowDownRight("#888"), arrowUpRight("#AAA"), arrowUp("#333")],
|
|
85
|
+
"4Rating": [box(false), box(true), box(true), box(true)],
|
|
86
|
+
"4RedToBlack": [circle("#000"), circle("#666"), circle("#FF9800"), circle("#F44336")],
|
|
87
|
+
"4TrafficLights": [circle("#000"), circle("#F44336"), circle("#FFC107"), circle("#4CAF50")],
|
|
88
|
+
|
|
89
|
+
// 5-icon sets
|
|
90
|
+
"5Arrows": [arrowDown("#F44336"), arrowDownRight("#FF9800"), arrowRight("#FFC107"), arrowUpRight("#8BC34A"), arrowUp("#4CAF50")],
|
|
91
|
+
"5ArrowsGray": [arrowDown("#666"), arrowDownRight("#777"), arrowRight("#888"), arrowUpRight("#999"), arrowUp("#333")],
|
|
92
|
+
"5Boxes": [box(false), box(true), box(true), box(true), box(true)],
|
|
93
|
+
"5Quarters": [quarter0, quarter1, quarter2, quarter3, quarter4],
|
|
94
|
+
"5Rating": [box(false), box(true), box(true), box(true), box(true)],
|
|
95
|
+
|
|
96
|
+
// NoIcons - empty set
|
|
97
|
+
NoIcons: [],
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the SVG data URI for a specific icon in an icon set.
|
|
102
|
+
* Returns undefined if the icon set or index is invalid.
|
|
103
|
+
*/
|
|
104
|
+
export function getCfIcon(iconSet: string, index: number): string | undefined {
|
|
105
|
+
const icons = ICON_SETS[iconSet];
|
|
106
|
+
if (!icons || index < 0 || index >= icons.length) return undefined;
|
|
107
|
+
return icons[index];
|
|
108
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export interface ParsedConditionalFormat {
|
|
2
|
+
ref: string;
|
|
3
|
+
rules: ParsedCfRule[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type ParsedCfRule =
|
|
7
|
+
| ParsedColorScaleRule
|
|
8
|
+
| ParsedDataBarRule
|
|
9
|
+
| ParsedIconSetRule
|
|
10
|
+
| ParsedStyleRule;
|
|
11
|
+
|
|
12
|
+
export interface CfThreshold {
|
|
13
|
+
type: "percentile" | "percent" | "num" | "min" | "max" | "formula" | "autoMin" | "autoMax";
|
|
14
|
+
value?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ParsedColorScaleRule {
|
|
18
|
+
ruleType: "colorScale";
|
|
19
|
+
priority: number;
|
|
20
|
+
/** Excel's <cfRule stopIfTrue="1">: when this rule matches a cell, lower-
|
|
21
|
+
* priority rules on the same cell are skipped. */
|
|
22
|
+
stopIfTrue?: boolean;
|
|
23
|
+
colors: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ParsedDataBarRule {
|
|
27
|
+
ruleType: "dataBar";
|
|
28
|
+
priority: number;
|
|
29
|
+
stopIfTrue?: boolean;
|
|
30
|
+
color: string;
|
|
31
|
+
minLength: number;
|
|
32
|
+
maxLength: number;
|
|
33
|
+
showValue: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ParsedIconSetRule {
|
|
37
|
+
ruleType: "iconSet";
|
|
38
|
+
priority: number;
|
|
39
|
+
stopIfTrue?: boolean;
|
|
40
|
+
iconSet: string;
|
|
41
|
+
thresholds: CfThreshold[];
|
|
42
|
+
showValue: boolean;
|
|
43
|
+
reverse: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ParsedStyleRule {
|
|
47
|
+
ruleType: "style";
|
|
48
|
+
priority: number;
|
|
49
|
+
stopIfTrue?: boolean;
|
|
50
|
+
type: "cellIs" | "containsText" | "top10" | "aboveAverage" | "timePeriod" | "expression";
|
|
51
|
+
operator?: string;
|
|
52
|
+
formulae?: unknown[];
|
|
53
|
+
text?: string;
|
|
54
|
+
rank?: number;
|
|
55
|
+
percent?: boolean;
|
|
56
|
+
bottom?: boolean;
|
|
57
|
+
aboveAverage?: boolean;
|
|
58
|
+
timePeriod?: string;
|
|
59
|
+
style?: ParsedCfStyle;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ParsedCfStyle {
|
|
63
|
+
fontBold?: boolean;
|
|
64
|
+
fontItalic?: boolean;
|
|
65
|
+
fontColor?: string;
|
|
66
|
+
backgroundColor?: string;
|
|
67
|
+
}
|