@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.
@@ -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
- console.warn('[FilesPreview] exceljs module shape:', mod)
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
- console.error('[FilesPreview] xlsx error', e)
300
- xlsxError.value = e.message
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@innertia-solutions/innertia-nuxt",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
4
4
  "description": "Innertia Solutions — Nuxt layer unificada: core, auth, multitenancy, theme y app contexts",
5
5
  "keywords": [
6
6
  "nuxt",