@rowsncolumns/utils 9.5.7 → 9.6.1
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/cjs/cell-data-helpers.d.ts +8 -2
- package/dist/cjs/cell-data-helpers.d.ts.map +1 -1
- package/dist/cjs/cell-data-helpers.js +11 -3
- package/dist/cjs/cjk-number-format.d.ts +11 -0
- package/dist/cjs/cjk-number-format.d.ts.map +1 -0
- package/dist/cjs/cjk-number-format.js +533 -0
- package/dist/cjs/color.d.ts +9 -0
- package/dist/cjs/color.d.ts.map +1 -1
- package/dist/cjs/color.js +55 -1
- package/dist/cjs/formatter.d.ts +42 -0
- package/dist/cjs/formatter.d.ts.map +1 -1
- package/dist/cjs/formatter.js +179 -6
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/cell-data-helpers.d.ts +8 -2
- package/dist/esm/cell-data-helpers.d.ts.map +1 -1
- package/dist/esm/cell-data-helpers.js +9 -2
- package/dist/esm/cjk-number-format.d.ts +11 -0
- package/dist/esm/cjk-number-format.d.ts.map +1 -0
- package/dist/esm/cjk-number-format.js +494 -0
- package/dist/esm/color.d.ts +9 -0
- package/dist/esm/color.d.ts.map +1 -1
- package/dist/esm/color.js +53 -0
- package/dist/esm/formatter.d.ts +42 -0
- package/dist/esm/formatter.d.ts.map +1 -1
- package/dist/esm/formatter.js +162 -4
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/esm/formatter.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { addLocale, format, formatColor, getFormatDateInfo, getLocale, isDateFormat, isTextFormat, } from "numfmt";
|
|
2
|
+
import { prepareCjkNumberFormat } from "./cjk-number-format";
|
|
2
3
|
import { IndexedColors } from "./colors";
|
|
3
4
|
import { excelNumberPrePass, splitFormatSections, } from "./excel-number-format";
|
|
4
5
|
/**
|
|
@@ -498,6 +499,153 @@ const withWorkbookSeparatorsCached = (code, locale) => {
|
|
|
498
499
|
return rewritten;
|
|
499
500
|
};
|
|
500
501
|
export const ssfFormat = (pattern, value, locale) => {
|
|
502
|
+
// East Asian tokens numfmt does not render (`[DBNumN]`, Japanese era `g`/`e`,
|
|
503
|
+
// `aaa` weekdays): rewrite the code to plain literals, then convert the
|
|
504
|
+
// rendered digits to the `[DBNumN]` numeral system (see cjk-number-format).
|
|
505
|
+
if (typeof value === "number") {
|
|
506
|
+
const cjk = prepareCjkNumberFormat(pattern, value, locale);
|
|
507
|
+
if (cjk)
|
|
508
|
+
return cjk.finish(ssfFormatBase(cjk.code, value, locale));
|
|
509
|
+
}
|
|
510
|
+
return ssfFormatBase(pattern, value, locale);
|
|
511
|
+
};
|
|
512
|
+
const LAYOUT_FILL_MARK = "\uE000";
|
|
513
|
+
const LAYOUT_SKIP_MARK = "\uE001";
|
|
514
|
+
const LAYOUT_LITERAL_SPACE = "\uE002";
|
|
515
|
+
const LAYOUT_DIGIT_PAD = "\u00a0";
|
|
516
|
+
/**
|
|
517
|
+
* Quote every literal space of `code` as a private-use sentinel so that,
|
|
518
|
+
* rendered with numfmt's `nbsp` option, the only non-breaking spaces left
|
|
519
|
+
* in the output are the `?` digit pads.
|
|
520
|
+
*/
|
|
521
|
+
const markLiteralSpaces = (code) => {
|
|
522
|
+
let out = "";
|
|
523
|
+
let inQuotes = false;
|
|
524
|
+
let inBrackets = false;
|
|
525
|
+
for (let i = 0; i < code.length; i++) {
|
|
526
|
+
const char = code[i];
|
|
527
|
+
if (inQuotes) {
|
|
528
|
+
if (char === '"')
|
|
529
|
+
inQuotes = false;
|
|
530
|
+
out += char === " " ? LAYOUT_LITERAL_SPACE : char;
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (inBrackets) {
|
|
534
|
+
if (char === "]")
|
|
535
|
+
inBrackets = false;
|
|
536
|
+
out += char;
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
if (char === '"') {
|
|
540
|
+
inQuotes = true;
|
|
541
|
+
}
|
|
542
|
+
else if (char === "[") {
|
|
543
|
+
inBrackets = true;
|
|
544
|
+
}
|
|
545
|
+
else if (char === "\\" && code[i + 1] === " ") {
|
|
546
|
+
out += `"${LAYOUT_LITERAL_SPACE}"`;
|
|
547
|
+
i++;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
else if (char === "\\" || char === "_" || char === "*") {
|
|
551
|
+
out += char + (code[i + 1] ?? "");
|
|
552
|
+
i++;
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
else if (char === " ") {
|
|
556
|
+
out += `"${LAYOUT_LITERAL_SPACE}"`;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
out += char;
|
|
560
|
+
}
|
|
561
|
+
return out;
|
|
562
|
+
};
|
|
563
|
+
/** Does the pattern carry a `*` fill, `_` skip or `?` placeholder at all? */
|
|
564
|
+
const LAYOUT_TOKEN_REGEX = /[*_?]/;
|
|
565
|
+
/**
|
|
566
|
+
* Excel's width-aware number-format output: `*x` repeats `x` to the cell's
|
|
567
|
+
* width, `_x` reserves the width of `x` and `?` reserves a digit's width
|
|
568
|
+
* ("Number format codes", support.microsoft.com). A plain formatted string
|
|
569
|
+
* cannot carry that — `ssfFormat` drops the fill and renders the reserves as
|
|
570
|
+
* single spaces — so the painter asks for the parts and expands them with
|
|
571
|
+
* measured glyph widths.
|
|
572
|
+
*
|
|
573
|
+
* Returns `undefined` when the pattern has none of those tokens (the plain
|
|
574
|
+
* string is already exact), and for East Asian numeral codes. The parts'
|
|
575
|
+
* plain text ({@link numberFormatLayoutText}) equals `ssfFormat`'s output;
|
|
576
|
+
* callers compare it against the string they paint and ignore the layout
|
|
577
|
+
* when the two disagree.
|
|
578
|
+
*/
|
|
579
|
+
export const ssfFormatLayout = (pattern, value, locale) => {
|
|
580
|
+
if (!pattern || !LAYOUT_TOKEN_REGEX.test(pattern))
|
|
581
|
+
return undefined;
|
|
582
|
+
if (typeof value === "number" && prepareCjkNumberFormat(pattern, value, locale)) {
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
const raw = ssfFormatBase(pattern, value, locale, {
|
|
586
|
+
nbsp: true,
|
|
587
|
+
fillChar: LAYOUT_FILL_MARK,
|
|
588
|
+
skipChar: LAYOUT_SKIP_MARK,
|
|
589
|
+
transform: markLiteralSpaces,
|
|
590
|
+
});
|
|
591
|
+
if (raw === undefined)
|
|
592
|
+
return undefined;
|
|
593
|
+
// A locale whose group separator is itself a non-breaking space makes the
|
|
594
|
+
// digit pads ambiguous: keep those as plain spaces.
|
|
595
|
+
const digitPads = separatorsFor(locale).group !== LAYOUT_DIGIT_PAD;
|
|
596
|
+
const parts = [];
|
|
597
|
+
let text = "";
|
|
598
|
+
const flush = () => {
|
|
599
|
+
if (text)
|
|
600
|
+
parts.push({ type: "text", text });
|
|
601
|
+
text = "";
|
|
602
|
+
};
|
|
603
|
+
for (let i = 0; i < raw.length; i++) {
|
|
604
|
+
const char = raw[i];
|
|
605
|
+
if (char === LAYOUT_FILL_MARK || char === LAYOUT_SKIP_MARK) {
|
|
606
|
+
const next = raw[i + 1] ?? " ";
|
|
607
|
+
flush();
|
|
608
|
+
parts.push({
|
|
609
|
+
type: char === LAYOUT_FILL_MARK ? "fill" : "skip",
|
|
610
|
+
char: next,
|
|
611
|
+
});
|
|
612
|
+
i++;
|
|
613
|
+
}
|
|
614
|
+
else if (char === LAYOUT_DIGIT_PAD) {
|
|
615
|
+
if (digitPads) {
|
|
616
|
+
flush();
|
|
617
|
+
parts.push({ type: "digit" });
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
text += char;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
else if (char === LAYOUT_LITERAL_SPACE) {
|
|
624
|
+
text += " ";
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
text += char;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
flush();
|
|
631
|
+
return parts.some((part) => part.type !== "text") ? parts : undefined;
|
|
632
|
+
};
|
|
633
|
+
/**
|
|
634
|
+
* The plain string a layout stands for — what `ssfFormat` returns for the
|
|
635
|
+
* same pattern and value: fills drop out, skips and digit pads are one
|
|
636
|
+
* space each.
|
|
637
|
+
*/
|
|
638
|
+
export const numberFormatLayoutText = (parts) => {
|
|
639
|
+
let out = "";
|
|
640
|
+
for (const part of parts) {
|
|
641
|
+
if (part.type === "text")
|
|
642
|
+
out += part.text;
|
|
643
|
+
else if (part.type !== "fill")
|
|
644
|
+
out += " ";
|
|
645
|
+
}
|
|
646
|
+
return out;
|
|
647
|
+
};
|
|
648
|
+
function ssfFormatBase(pattern, value, locale, layout) {
|
|
501
649
|
try {
|
|
502
650
|
if (locale)
|
|
503
651
|
ensureNumfmtLocale(locale);
|
|
@@ -506,12 +654,22 @@ export const ssfFormat = (pattern, value, locale) => {
|
|
|
506
654
|
shortAmPm = withShortAmPmMarker(pattern);
|
|
507
655
|
shortAmPmPatternCache.set(pattern, shortAmPm);
|
|
508
656
|
}
|
|
509
|
-
const
|
|
657
|
+
const baseCode = withWorkbookSeparatorsCached(shortAmPm ?? pattern, locale);
|
|
658
|
+
const code = layout ? layout.transform(baseCode) : baseCode;
|
|
510
659
|
let patternLocale = localeForPattern(pattern, locale);
|
|
511
660
|
if (shortAmPm !== undefined && patternLocale) {
|
|
512
661
|
patternLocale = getShortAmPmLocale(patternLocale);
|
|
513
662
|
}
|
|
514
|
-
|
|
663
|
+
// numfmt types `fillChar` / `skipChar` as booleans; at runtime they are
|
|
664
|
+
// the marker strings it emits ahead of the fill / skip character.
|
|
665
|
+
const options = layout
|
|
666
|
+
? {
|
|
667
|
+
locale: patternLocale,
|
|
668
|
+
nbsp: layout.nbsp,
|
|
669
|
+
fillChar: layout.fillChar,
|
|
670
|
+
skipChar: layout.skipChar,
|
|
671
|
+
}
|
|
672
|
+
: { locale: patternLocale };
|
|
515
673
|
if (typeof value === "number") {
|
|
516
674
|
// Excel decides rounding, `General`, huge magnitudes and conditional
|
|
517
675
|
// sections from the 15-significant-digit decimal, not the binary
|
|
@@ -529,9 +687,9 @@ export const ssfFormat = (pattern, value, locale) => {
|
|
|
529
687
|
return isNegativeElapsedTime ? `-${formatted}` : formatted;
|
|
530
688
|
}
|
|
531
689
|
catch (err) {
|
|
532
|
-
return String(value);
|
|
690
|
+
return layout ? undefined : String(value);
|
|
533
691
|
}
|
|
534
|
-
}
|
|
692
|
+
}
|
|
535
693
|
/**
|
|
536
694
|
* Excel's legacy fixed 56-color palette used by `[ColorN]` directives
|
|
537
695
|
* inside number format patterns (1-indexed). This palette is INDEPENDENT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../../array.ts","../../cell-data-helpers.ts","../../clipboard-html-sanitize.ts","../../color.ts","../../colors.ts","../../condition-operand.ts","../../conditional-format.ts","../../content-hash.ts","../../data-validation.ts","../../date.ts","../../dom.ts","../../excel-number-format.ts","../../formatter.ts","../../formula-locale.ts","../../formula-refs.ts","../../formula.ts","../../index.ts","../../keyboard.ts","../../locale.ts","../../log.ts","../../memoize.ts","../../numbers.ts","../../rich-text-html.ts","../../rich-text-links.ts","../../selection.ts","../../shared-string-canonical.ts","../../sheet-names.ts","../../sheet-protection.ts","../../sheet-span.ts","../../sort.ts","../../sparkline-groups.ts","../../string.ts","../../table-names.ts","../../table-styles.ts","../../table-totals.ts","../../typeguards.ts","../../uuid.ts","../../vitest.config.ts","../../formula-locale/formula-locale-data.generated.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["../../array.ts","../../cell-data-helpers.ts","../../cjk-number-format.ts","../../clipboard-html-sanitize.ts","../../color.ts","../../colors.ts","../../condition-operand.ts","../../conditional-format.ts","../../content-hash.ts","../../data-validation.ts","../../date.ts","../../dom.ts","../../excel-number-format.ts","../../formatter.ts","../../formula-locale.ts","../../formula-refs.ts","../../formula.ts","../../index.ts","../../keyboard.ts","../../locale.ts","../../log.ts","../../memoize.ts","../../numbers.ts","../../rich-text-html.ts","../../rich-text-links.ts","../../selection.ts","../../shared-string-canonical.ts","../../sheet-names.ts","../../sheet-protection.ts","../../sheet-span.ts","../../sort.ts","../../sparkline-groups.ts","../../string.ts","../../table-names.ts","../../table-styles.ts","../../table-totals.ts","../../typeguards.ts","../../uuid.ts","../../vitest.config.ts","../../formula-locale/formula-locale-data.generated.ts"],"version":"5.8.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rowsncolumns/utils",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.6.1",
|
|
4
4
|
"author": "Vinay M",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"numfmt": "^3.2.2",
|
|
47
|
-
"@rowsncolumns/common-types": ">=5.3.
|
|
47
|
+
"@rowsncolumns/common-types": ">=5.3.5"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {},
|
|
50
50
|
"peerDependencies": {}
|