@ztimson/utils 0.23.15 → 0.23.17
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/csv.d.ts +9 -2
- package/dist/index.cjs +39 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +39 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -684,26 +684,40 @@ function validateEmail(email) {
|
|
|
684
684
|
return /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(email);
|
|
685
685
|
}
|
|
686
686
|
function fromCsv(csv, hasHeaders = true) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
return columns;
|
|
687
|
+
function parseLine(line) {
|
|
688
|
+
const columns = [];
|
|
689
|
+
let current = "", inQuotes2 = false;
|
|
690
|
+
for (let i = 0; i < line.length; i++) {
|
|
691
|
+
const char = line[i];
|
|
692
|
+
const nextChar = line[i + 1];
|
|
693
|
+
if (char === '"') {
|
|
694
|
+
if (inQuotes2 && nextChar === '"') {
|
|
695
|
+
current += '"';
|
|
696
|
+
i++;
|
|
697
|
+
} else inQuotes2 = !inQuotes2;
|
|
698
|
+
} else if (char === "," && !inQuotes2) {
|
|
699
|
+
columns.push(current);
|
|
700
|
+
current = "";
|
|
701
|
+
} else current += char;
|
|
704
702
|
}
|
|
703
|
+
columns.push(current);
|
|
704
|
+
return columns.map((col) => col.replace(/^"|"$/g, "").replace(/""/g, '"'));
|
|
705
|
+
}
|
|
706
|
+
const rows2 = [];
|
|
707
|
+
let currentRow = "", inQuotes = false;
|
|
708
|
+
for (const char of csv) {
|
|
709
|
+
if (char === '"') inQuotes = !inQuotes;
|
|
710
|
+
if (char === "\n" && !inQuotes) {
|
|
711
|
+
rows2.push(currentRow);
|
|
712
|
+
currentRow = "";
|
|
713
|
+
} else currentRow += char;
|
|
714
|
+
}
|
|
715
|
+
if (currentRow) rows2.push(currentRow);
|
|
716
|
+
let headers = hasHeaders ? rows2.splice(0, 1)[0] : null;
|
|
717
|
+
if (headers) headers = headers.match(/(?:[^,"']+|"(?:[^"]|"")*"|'(?:[^']|'')*')+/g);
|
|
718
|
+
return rows2.map((r2) => {
|
|
705
719
|
const props = parseLine(r2);
|
|
706
|
-
const h = headers || Array(props.length).fill(null).map((
|
|
720
|
+
const h = headers || Array(props.length).fill(null).map((_, i) => {
|
|
707
721
|
let letter = "";
|
|
708
722
|
const first = i / 26;
|
|
709
723
|
if (first > 1) letter += LETTER_LIST[Math.floor(first - 1)];
|
|
@@ -717,12 +731,16 @@ function fromCsv(csv, hasHeaders = true) {
|
|
|
717
731
|
});
|
|
718
732
|
}
|
|
719
733
|
function toCsv(target, flatten = true) {
|
|
720
|
-
const
|
|
734
|
+
const t = makeArray(target);
|
|
735
|
+
const headers = new ASet(t.reduce((acc, row) => [...acc, ...Object.keys(flatten ? flattenObj(row) : row)], []));
|
|
721
736
|
return [
|
|
722
737
|
headers.join(","),
|
|
723
|
-
...
|
|
738
|
+
...t.map((row) => headers.map((h) => {
|
|
724
739
|
const value2 = dotNotation(row, h);
|
|
725
|
-
|
|
740
|
+
if (value2 == null) return "";
|
|
741
|
+
if (typeof value2 == "object") return `"${JSONSanitize(value2).replaceAll('"', '""')}"`;
|
|
742
|
+
if (typeof value2 == "string" && /[\n"]/g.test(value2)) return `"${value2.replaceAll('"', '""')}"`;
|
|
743
|
+
return value2;
|
|
726
744
|
}).join(","))
|
|
727
745
|
].join("\n");
|
|
728
746
|
}
|