@jxsuite/parser 1.6.0 → 1.7.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/csv.js +100 -1
- package/dist/markdown.js +2447 -5993
- package/dist/serialize.js +8233 -10597
- package/package.json +5 -5
- package/src/Csv.class.json +31 -0
- package/src/csv.ts +176 -1
package/dist/csv.js
CHANGED
|
@@ -116,6 +116,101 @@ function parseCSV(csv) {
|
|
|
116
116
|
}
|
|
117
117
|
return rows;
|
|
118
118
|
}
|
|
119
|
+
function scanRows(csv) {
|
|
120
|
+
const rows = [];
|
|
121
|
+
let start = 0;
|
|
122
|
+
let inQuotes = false;
|
|
123
|
+
for (let i = 0;i < csv.length; i++) {
|
|
124
|
+
const ch = csv[i];
|
|
125
|
+
if (ch === '"') {
|
|
126
|
+
if (inQuotes && csv[i + 1] === '"') {
|
|
127
|
+
i += 1;
|
|
128
|
+
} else {
|
|
129
|
+
inQuotes = !inQuotes;
|
|
130
|
+
}
|
|
131
|
+
} else if ((ch === `
|
|
132
|
+
` || ch === "\r" && csv[i + 1] === `
|
|
133
|
+
`) && !inQuotes) {
|
|
134
|
+
rows.push({ end: i, start });
|
|
135
|
+
if (ch === "\r") {
|
|
136
|
+
i += 1;
|
|
137
|
+
}
|
|
138
|
+
start = i + 1;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (csv.slice(start).trim()) {
|
|
142
|
+
rows.push({ end: csv.length, start });
|
|
143
|
+
}
|
|
144
|
+
return rows;
|
|
145
|
+
}
|
|
146
|
+
function scanRowFields(csv, row, span) {
|
|
147
|
+
const line = csv.slice(span.start, span.end);
|
|
148
|
+
const fields = [];
|
|
149
|
+
let fieldStart = 0;
|
|
150
|
+
let value = "";
|
|
151
|
+
let inQuotes = false;
|
|
152
|
+
for (let i = 0;i < line.length; i++) {
|
|
153
|
+
const ch = line[i];
|
|
154
|
+
if (ch === '"') {
|
|
155
|
+
if (inQuotes && line[i + 1] === '"') {
|
|
156
|
+
value += '"';
|
|
157
|
+
i += 1;
|
|
158
|
+
} else {
|
|
159
|
+
inQuotes = !inQuotes;
|
|
160
|
+
}
|
|
161
|
+
} else if (ch === "," && !inQuotes) {
|
|
162
|
+
fields.push({
|
|
163
|
+
end: span.start + i,
|
|
164
|
+
row,
|
|
165
|
+
start: span.start + fieldStart,
|
|
166
|
+
value: value.trim()
|
|
167
|
+
});
|
|
168
|
+
value = "";
|
|
169
|
+
fieldStart = i + 1;
|
|
170
|
+
} else {
|
|
171
|
+
value += ch;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
fields.push({ end: span.end, row, start: span.start + fieldStart, value: value.trim() });
|
|
175
|
+
return fields;
|
|
176
|
+
}
|
|
177
|
+
function scanFields(csv) {
|
|
178
|
+
return scanRows(csv).flatMap((span, row) => scanRowFields(csv, row, span));
|
|
179
|
+
}
|
|
180
|
+
function encodeField(raw, value) {
|
|
181
|
+
const lead = raw.slice(0, raw.length - raw.trimStart().length);
|
|
182
|
+
const trail = raw.slice(raw.trimEnd().length);
|
|
183
|
+
const core = raw.trim();
|
|
184
|
+
const wasQuoted = core.length >= 2 && core.startsWith('"') && core.endsWith('"');
|
|
185
|
+
const mustQuote = /["\r\n,]/.test(value) || value.trim() !== value;
|
|
186
|
+
return lead + (wasQuoted || mustQuote ? `"${value.replaceAll('"', '""')}"` : value) + trail;
|
|
187
|
+
}
|
|
188
|
+
function rewriteCSV(source, edits) {
|
|
189
|
+
const replacements = new Map;
|
|
190
|
+
for (const edit of edits) {
|
|
191
|
+
if (edit.from !== edit.to) {
|
|
192
|
+
replacements.set(edit.from, edit.to);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (replacements.size === 0) {
|
|
196
|
+
return source;
|
|
197
|
+
}
|
|
198
|
+
let out = "";
|
|
199
|
+
let cursor = 0;
|
|
200
|
+
for (const field of scanFields(source)) {
|
|
201
|
+
if (field.row === 0) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const to = replacements.get(field.value);
|
|
205
|
+
if (to === undefined) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
out += source.slice(cursor, field.start);
|
|
209
|
+
out += encodeField(source.slice(field.start, field.end), to);
|
|
210
|
+
cursor = field.end;
|
|
211
|
+
}
|
|
212
|
+
return out + source.slice(cursor);
|
|
213
|
+
}
|
|
119
214
|
function coerceCSVRows(rows, schema, idField) {
|
|
120
215
|
return rows.map((row, i) => {
|
|
121
216
|
const data = { ...row };
|
|
@@ -154,6 +249,9 @@ class Csv {
|
|
|
154
249
|
static parse(source, options = {}) {
|
|
155
250
|
return coerceCSVRows(parseCSV(source), options.schema, options.idField);
|
|
156
251
|
}
|
|
252
|
+
static rewrite(source, edits = []) {
|
|
253
|
+
return rewriteCSV(source, edits);
|
|
254
|
+
}
|
|
157
255
|
static async discover(source, options = {}) {
|
|
158
256
|
const { existsSync, readdirSync } = await import("node:fs");
|
|
159
257
|
const { resolve, extname } = await import("node:path");
|
|
@@ -191,5 +289,6 @@ class Csv {
|
|
|
191
289
|
export {
|
|
192
290
|
Csv,
|
|
193
291
|
coerceCSVRows,
|
|
194
|
-
parseCSV
|
|
292
|
+
parseCSV,
|
|
293
|
+
rewriteCSV
|
|
195
294
|
};
|