@innertia-solutions/innertia-nuxt 0.1.50 → 0.1.51
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/components/Files/Preview.vue +67 -9
- package/package.json +1 -1
|
@@ -274,30 +274,88 @@ function buildSheet(ws, workbook) {
|
|
|
274
274
|
return { name: ws.name, cols, rows, firstRow: 1, imageMap }
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
/** Detecta el delimitador más probable de un texto tabular (tab / ; / ,). */
|
|
278
|
+
function detectDelimiter(text) {
|
|
279
|
+
const line = text.split(/\r?\n/).find(l => l.trim()) ?? ''
|
|
280
|
+
const counts = { '\t': (line.match(/\t/g) || []).length, ';': (line.match(/;/g) || []).length, ',': (line.match(/,/g) || []).length }
|
|
281
|
+
const max = Math.max(counts['\t'], counts[';'], counts[','])
|
|
282
|
+
if (max === 0) return null
|
|
283
|
+
return counts['\t'] === max ? '\t' : (counts[';'] === max ? ';' : ',')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** Parser genérico de texto delimitado con soporte de comillas. */
|
|
287
|
+
function parseDelimited(text, delim) {
|
|
288
|
+
const rows = []
|
|
289
|
+
let row = [], cell = '', inQ = false
|
|
290
|
+
for (let i = 0; i < text.length; i++) {
|
|
291
|
+
const c = text[i]
|
|
292
|
+
if (inQ) {
|
|
293
|
+
if (c === '"') { if (text[i + 1] === '"') { cell += '"'; i++ } else inQ = false }
|
|
294
|
+
else cell += c
|
|
295
|
+
} else {
|
|
296
|
+
if (c === '"') inQ = true
|
|
297
|
+
else if (c === delim) { row.push(cell); cell = '' }
|
|
298
|
+
else if (c === '\n') { row.push(cell); rows.push(row); row = []; cell = '' }
|
|
299
|
+
else if (c === '\r') continue
|
|
300
|
+
else cell += c
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (cell.length || row.length) { row.push(cell); rows.push(row) }
|
|
304
|
+
return rows
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** Construye una sheet (misma forma que buildSheet) desde texto delimitado. */
|
|
308
|
+
function buildSheetFromDelimited(text, name = 'Hoja 1') {
|
|
309
|
+
const delim = detectDelimiter(text) ?? '\t'
|
|
310
|
+
const raw = parseDelimited(text, delim).filter(r => r.length && !(r.length === 1 && r[0] === ''))
|
|
311
|
+
const colCount = raw.reduce((m, r) => Math.max(m, r.length), 0)
|
|
312
|
+
const cols = []
|
|
313
|
+
for (let c = 0; c < colCount; c++) cols.push(colLetter(c))
|
|
314
|
+
const rows = raw.map((r, ri) => {
|
|
315
|
+
const rowData = []
|
|
316
|
+
for (let c = 0; c < colCount; c++) {
|
|
317
|
+
rowData.push({ v: r[c] ?? '', align: 'left', t: 'string', address: colLetter(c) + (ri + 1) })
|
|
318
|
+
}
|
|
319
|
+
return rowData
|
|
320
|
+
})
|
|
321
|
+
return { name, cols, rows, firstRow: 1, imageMap: {} }
|
|
322
|
+
}
|
|
323
|
+
|
|
277
324
|
const loadXlsx = async () => {
|
|
278
325
|
if (viewerType.value !== 'xlsx') return
|
|
279
326
|
isLoadingXlsx.value = true
|
|
280
327
|
xlsxError.value = null
|
|
281
328
|
xlsxActiveIdx.value = 0
|
|
329
|
+
let buf = null
|
|
282
330
|
try {
|
|
331
|
+
const res = await fetch(src.value)
|
|
332
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
|
333
|
+
buf = await res.arrayBuffer()
|
|
334
|
+
|
|
283
335
|
const mod = await import('exceljs').catch(() => null)
|
|
284
336
|
const ExcelJS = pickModule(mod, 'Workbook')
|
|
285
337
|
?? (mod?.default?.Workbook ? mod.default : null)
|
|
286
338
|
?? mod
|
|
287
|
-
if (!ExcelJS?.Workbook)
|
|
288
|
-
|
|
289
|
-
throw new Error('Para previsualizar .xlsx instalá la dep: pnpm add exceljs')
|
|
290
|
-
}
|
|
291
|
-
const res = await fetch(src.value)
|
|
292
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
|
293
|
-
const buf = await res.arrayBuffer()
|
|
339
|
+
if (!ExcelJS?.Workbook) throw new Error('exceljs no disponible')
|
|
340
|
+
|
|
294
341
|
const wb = new ExcelJS.Workbook()
|
|
295
342
|
await wb.xlsx.load(buf)
|
|
296
343
|
const sheets = wb.worksheets.map(ws => buildSheet(ws, wb))
|
|
297
344
|
xlsxWorkbook.value = { sheets }
|
|
298
345
|
} catch (e) {
|
|
299
|
-
|
|
300
|
-
|
|
346
|
+
// Fallback: el archivo no es un .xlsx OOXML válido (típico: un CSV/TSV exportado
|
|
347
|
+
// con extensión .xls, o mime mal detectado). Lo renderizamos como tabla delimitada.
|
|
348
|
+
try {
|
|
349
|
+
const text = new TextDecoder('utf-8').decode(buf ?? new ArrayBuffer(0))
|
|
350
|
+
if (text && text.trim()) {
|
|
351
|
+
xlsxWorkbook.value = { sheets: [buildSheetFromDelimited(text)] }
|
|
352
|
+
} else {
|
|
353
|
+
throw e
|
|
354
|
+
}
|
|
355
|
+
} catch (_) {
|
|
356
|
+
console.error('[FilesPreview] xlsx error', e)
|
|
357
|
+
xlsxError.value = 'No se pudo previsualizar la hoja de cálculo.'
|
|
358
|
+
}
|
|
301
359
|
} finally {
|
|
302
360
|
isLoadingXlsx.value = false
|
|
303
361
|
}
|