feat(export): add .toml source download and shared slugify helper
This commit is contained in:
@@ -2,14 +2,18 @@ import { ref } from 'vue'
|
|||||||
|
|
||||||
type Toast = { kind: 'ok' | 'err'; text: string } | null
|
type Toast = { kind: 'ok' | 'err'; text: string } | null
|
||||||
|
|
||||||
/** Slugified, stable download name derived from the plan title. */
|
/** Lowercase, dash-collapsed slug of a plan title — no extension, no fallback. */
|
||||||
export function exportFilename(title: string): string {
|
export function slugify(title: string): string {
|
||||||
const slug = title
|
return title
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/[^a-z0-9]+/g, '-')
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
.replace(/^-+|-+$/g, '')
|
.replace(/^-+|-+$/g, '')
|
||||||
return `macroplan-${slug || 'plan'}.png`
|
}
|
||||||
|
|
||||||
|
/** Slugified, stable download name derived from the plan title. */
|
||||||
|
export function exportFilename(title: string): string {
|
||||||
|
return `macroplan-${slugify(title) || 'plan'}.png`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
13
src/composables/useSourceExport.test.ts
Normal file
13
src/composables/useSourceExport.test.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { sourceFilename } from './useSourceExport'
|
||||||
|
|
||||||
|
describe('sourceFilename', () => {
|
||||||
|
it('slugifies the plan title into a .toml name', () => {
|
||||||
|
expect(sourceFilename('Q3 — Checkout revamp')).toBe('macroplan-q3-checkout-revamp.toml')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('falls back to a generic name when the title has no usable characters', () => {
|
||||||
|
expect(sourceFilename('')).toBe('macroplan-plan.toml')
|
||||||
|
expect(sourceFilename('—— ··')).toBe('macroplan-plan.toml')
|
||||||
|
})
|
||||||
|
})
|
||||||
17
src/composables/useSourceExport.ts
Normal file
17
src/composables/useSourceExport.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { slugify } from './usePngExport'
|
||||||
|
|
||||||
|
/** Slugified, stable download name for a plan's TOML source. */
|
||||||
|
export function sourceFilename(title: string): string {
|
||||||
|
return `macroplan-${slugify(title) || 'plan'}.toml`
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Download a plan's TOML source as a .toml file (client-side, no backend). */
|
||||||
|
export function downloadSource(source: string, filename: string): void {
|
||||||
|
const blob = new Blob([source], { type: 'text/plain;charset=utf-8' })
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = filename
|
||||||
|
a.click()
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user