@maizzle/framework 6.0.0-rc.24 → 6.0.0-rc.26
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/build.d.ts +19 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +139 -102
- package/dist/build.js.map +1 -1
- package/dist/components/Body.vue +12 -0
- package/dist/components/Button.vue +16 -29
- package/dist/components/CodeBlock.vue +5 -4
- package/dist/components/CodeInline.vue +9 -8
- package/dist/components/Column.vue +17 -4
- package/dist/components/Container.vue +7 -11
- package/dist/components/Hr.vue +1 -1
- package/dist/components/Img.vue +39 -22
- package/dist/components/Layout.vue +1 -1
- package/dist/components/Markdown.vue +9 -14
- package/dist/components/QrCode.vue +2 -2
- package/dist/components/Section.vue +9 -6
- package/dist/components/Text.vue +2 -2
- package/dist/components/utils.d.ts +25 -1
- package/dist/components/utils.d.ts.map +1 -1
- package/dist/components/utils.js +29 -1
- package/dist/components/utils.js.map +1 -1
- package/dist/components/utils.ts +46 -0
- package/dist/composables/useConfig.d.ts.map +1 -1
- package/dist/composables/useCurrentTemplate.d.ts.map +1 -1
- package/dist/composables/useEvent.d.ts.map +1 -1
- package/dist/composables/useFont.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/plaintext.js.map +1 -1
- package/dist/plugins/postcss/mergeMediaQueries.js.map +1 -1
- package/dist/plugins/postcss/pruneVars.js.map +1 -1
- package/dist/plugins/postcss/quoteFontFamilies.d.ts.map +1 -1
- package/dist/plugins/postcss/quoteFontFamilies.js.map +1 -1
- package/dist/plugins/postcss/removeDeclarations.js.map +1 -1
- package/dist/plugins/postcss/resolveProps.d.ts.map +1 -1
- package/dist/plugins/postcss/resolveProps.js +0 -3
- package/dist/plugins/postcss/resolveProps.js.map +1 -1
- package/dist/plugins/postcss/tailwindCleanup.js.map +1 -1
- package/dist/prepare.js +1 -1
- package/dist/prepare.js.map +1 -1
- package/dist/render/active.d.ts.map +1 -1
- package/dist/render/buildTemplate.d.ts +49 -0
- package/dist/render/buildTemplate.d.ts.map +1 -0
- package/dist/render/buildTemplate.js +139 -0
- package/dist/render/buildTemplate.js.map +1 -0
- package/dist/render/createRenderer.d.ts +3 -1
- package/dist/render/createRenderer.d.ts.map +1 -1
- package/dist/render/createRenderer.js +43 -10
- package/dist/render/createRenderer.js.map +1 -1
- package/dist/render/index.js +1 -1
- package/dist/render/index.js.map +1 -1
- package/dist/render/injectFonts.js.map +1 -1
- package/dist/render/parallel/buildWorker.d.ts +31 -0
- package/dist/render/parallel/buildWorker.d.ts.map +1 -0
- package/dist/render/parallel/buildWorker.js +66 -0
- package/dist/render/parallel/buildWorker.js.map +1 -0
- package/dist/render/parallel/worker.mjs +28 -0
- package/dist/render/plugins/codeBlockExtract.d.ts.map +1 -1
- package/dist/render/plugins/codeBlockExtract.js.map +1 -1
- package/dist/render/plugins/markdownExtract.d.ts.map +1 -1
- package/dist/render/plugins/markdownExtract.js.map +1 -1
- package/dist/render/plugins/rawExtract.d.ts.map +1 -1
- package/dist/render/plugins/rawExtract.js.map +1 -1
- package/dist/render/plugins/rowSourceLocation.d.ts.map +1 -1
- package/dist/render/plugins/rowSourceLocation.js.map +1 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +73 -53
- package/dist/serve.js.map +1 -1
- package/dist/server/compatibility.d.ts.map +1 -1
- package/dist/server/compatibility.js.map +1 -1
- package/dist/server/linter.js.map +1 -1
- package/dist/server/sfc-utils.js +1 -1
- package/dist/server/sfc-utils.js.map +1 -1
- package/dist/server/ui/pages/Preview.vue +34 -11
- package/dist/server/ui/vite-env.d.ts +1 -0
- package/dist/tests/render/_helpers.d.ts.map +1 -1
- package/dist/tests/render/_helpers.js.map +1 -1
- package/dist/transformers/addAttributes.js +2 -3
- package/dist/transformers/addAttributes.js.map +1 -1
- package/dist/transformers/base.d.ts +1 -1
- package/dist/transformers/base.d.ts.map +1 -1
- package/dist/transformers/base.js +5 -10
- package/dist/transformers/base.js.map +1 -1
- package/dist/transformers/columnWidth.d.ts.map +1 -1
- package/dist/transformers/columnWidth.js +2 -7
- package/dist/transformers/columnWidth.js.map +1 -1
- package/dist/transformers/entities.js.map +1 -1
- package/dist/transformers/filters/defaults.js.map +1 -1
- package/dist/transformers/filters/index.js.map +1 -1
- package/dist/transformers/format.js.map +1 -1
- package/dist/transformers/imgWidth.d.ts +20 -0
- package/dist/transformers/imgWidth.d.ts.map +1 -0
- package/dist/transformers/imgWidth.js +76 -0
- package/dist/transformers/imgWidth.js.map +1 -0
- package/dist/transformers/index.d.ts.map +1 -1
- package/dist/transformers/index.js +2 -0
- package/dist/transformers/index.js.map +1 -1
- package/dist/transformers/inlineCss.d.ts +3 -2
- package/dist/transformers/inlineCss.d.ts.map +1 -1
- package/dist/transformers/inlineCss.js.map +1 -1
- package/dist/transformers/inlineLink.js +1 -1
- package/dist/transformers/inlineLink.js.map +1 -1
- package/dist/transformers/minify.js.map +1 -1
- package/dist/transformers/minifyCodeInline.js.map +1 -1
- package/dist/transformers/msoPlaceholders.d.ts.map +1 -1
- package/dist/transformers/msoPlaceholders.js +2 -7
- package/dist/transformers/msoPlaceholders.js.map +1 -1
- package/dist/transformers/purgeCss.js.map +1 -1
- package/dist/transformers/replaceStrings.js.map +1 -1
- package/dist/transformers/safeSelectors.js.map +1 -1
- package/dist/transformers/shorthandCss.js.map +1 -1
- package/dist/transformers/tailwindComponent.js.map +1 -1
- package/dist/transformers/tailwindcss.js +1 -1
- package/dist/transformers/tailwindcss.js.map +1 -1
- package/dist/transformers/urlQuery.js.map +1 -1
- package/dist/types/config.d.ts +26 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/ast/serializer.js.map +1 -1
- package/dist/utils/compileTailwindCss.js.map +1 -1
- package/dist/utils/componentSources.js.map +1 -1
- package/dist/utils/cssBox.d.ts.map +1 -1
- package/dist/utils/cssBox.js +2 -7
- package/dist/utils/cssBox.js.map +1 -1
- package/dist/utils/decodeStyleEntities.js.map +1 -1
- package/dist/utils/url.js.map +1 -1
- package/dist/utils/watchPaths.js.map +1 -1
- package/node_modules/@clack/core/CHANGELOG.md +30 -0
- package/node_modules/@clack/core/dist/index.d.mts +109 -3
- package/node_modules/@clack/core/dist/index.mjs +972 -17
- package/node_modules/@clack/core/package.json +2 -1
- package/node_modules/@clack/prompts/CHANGELOG.md +42 -0
- package/node_modules/@clack/prompts/README.md +30 -9
- package/node_modules/@clack/prompts/dist/index.d.mts +458 -27
- package/node_modules/@clack/prompts/dist/index.mjs +1378 -141
- package/node_modules/@clack/prompts/package.json +2 -2
- package/node_modules/tinyexec/package.json +4 -4
- package/package.json +13 -11
- package/dist/components/Overlap.vue +0 -156
- package/node_modules/@clack/core/dist/index.mjs.map +0 -1
- package/node_modules/@clack/prompts/dist/index.mjs.map +0 -1
package/dist/components/Img.vue
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, createStaticVNode, useAttrs, type PropType } from 'vue'
|
|
3
|
+
import { twMerge } from 'tailwind-merge'
|
|
3
4
|
import { outlookFallbackProp } from './utils.ts'
|
|
4
5
|
import { useOutlookFallback } from '../composables/useOutlookFallback'
|
|
5
6
|
|
|
@@ -32,15 +33,22 @@ const props = defineProps({
|
|
|
32
33
|
type: String,
|
|
33
34
|
default: null
|
|
34
35
|
},
|
|
35
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* The width of the image, rendered without units.
|
|
38
|
+
*
|
|
39
|
+
* Optional: when omitted, the width is auto-derived post-render from
|
|
40
|
+
* the nearest sized ancestor (Container/Section/Column or any element
|
|
41
|
+
* with a pixel width). Falls back to fluid when no pixel width is
|
|
42
|
+
* resolvable. The `aspect` crop mode still requires an explicit width.
|
|
43
|
+
*/
|
|
36
44
|
width: {
|
|
37
45
|
type: [String, Number],
|
|
38
|
-
|
|
46
|
+
default: undefined
|
|
39
47
|
},
|
|
40
48
|
/** Animated image source, shown when user has no reduced motion preference. */
|
|
41
49
|
motionSrc: {
|
|
42
50
|
type: String,
|
|
43
|
-
default:
|
|
51
|
+
default: ''
|
|
44
52
|
},
|
|
45
53
|
/**
|
|
46
54
|
* Aspect ratio for cropped images.
|
|
@@ -111,7 +119,7 @@ const props = defineProps({
|
|
|
111
119
|
const outlookFallback = useOutlookFallback(props.outlookFallback)
|
|
112
120
|
|
|
113
121
|
function mimeFromExtension(src: string): string {
|
|
114
|
-
const ext = src.
|
|
122
|
+
const ext = src.slice(src.lastIndexOf('.') + 1).toLowerCase()
|
|
115
123
|
|
|
116
124
|
const types: Record<string, string> = {
|
|
117
125
|
apng: 'image/apng',
|
|
@@ -133,17 +141,12 @@ const ASPECT_KEYWORDS: Record<string, string> = {
|
|
|
133
141
|
'aspect-video': '16/9',
|
|
134
142
|
}
|
|
135
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Vue normalizes a component's `class` attr to a string before it
|
|
146
|
+
* reaches `attrs`, so only the string/empty cases can occur here.
|
|
147
|
+
*/
|
|
136
148
|
function normalizeClass(value: unknown): string {
|
|
137
|
-
|
|
138
|
-
if (typeof value === 'string') return value
|
|
139
|
-
if (Array.isArray(value)) return value.map(normalizeClass).filter(Boolean).join(' ')
|
|
140
|
-
if (typeof value === 'object') {
|
|
141
|
-
return Object.entries(value as Record<string, unknown>)
|
|
142
|
-
.filter(([, v]) => v)
|
|
143
|
-
.map(([k]) => k)
|
|
144
|
-
.join(' ')
|
|
145
|
-
}
|
|
146
|
-
return ''
|
|
149
|
+
return typeof value === 'string' ? value : ''
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
/**
|
|
@@ -182,10 +185,18 @@ const ratio = computed(() => {
|
|
|
182
185
|
|
|
183
186
|
const isCropped = computed(() => ratio.value !== null)
|
|
184
187
|
|
|
185
|
-
const motionType = computed(() => mimeFromExtension(props.motionSrc
|
|
188
|
+
const motionType = computed(() => mimeFromExtension(props.motionSrc))
|
|
186
189
|
|
|
187
190
|
const imgWidth = computed(() => Number.parseInt(String(props.width), 10))
|
|
188
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Whether an explicit, usable pixel width was supplied. When false, the
|
|
194
|
+
* non-cropped `<img>` is emitted without a width attribute plus a
|
|
195
|
+
* `data-maizzle-img-width` marker the `imgWidth` transformer reads to
|
|
196
|
+
* backfill the width from the nearest sized ancestor.
|
|
197
|
+
*/
|
|
198
|
+
const hasWidth = computed(() => props.width != null && props.width !== '' && Number.isFinite(imgWidth.value))
|
|
199
|
+
|
|
189
200
|
const heightPx = computed(() =>
|
|
190
201
|
ratio.value && Number.isFinite(imgWidth.value)
|
|
191
202
|
? Math.round((imgWidth.value * ratio.value.h) / ratio.value.w)
|
|
@@ -243,6 +254,13 @@ const NotMsoBefore = () => createStaticVNode('<!--[if !mso]><!-->', 1)
|
|
|
243
254
|
const NotMsoAfter = () => createStaticVNode('<!--<![endif]-->', 1)
|
|
244
255
|
|
|
245
256
|
const imgClass = 'max-w-full align-middle'
|
|
257
|
+
|
|
258
|
+
const cropClass = computed(() =>
|
|
259
|
+
twMerge(
|
|
260
|
+
`overflow-hidden table max-w-full${hasWidth.value ? ` w-[${imgWidth.value}px]` : ''}`,
|
|
261
|
+
parsedClass.value.className,
|
|
262
|
+
)
|
|
263
|
+
)
|
|
246
264
|
</script>
|
|
247
265
|
|
|
248
266
|
<template>
|
|
@@ -254,8 +272,7 @@ const imgClass = 'max-w-full align-middle'
|
|
|
254
272
|
v-bind="{ ...attrs, class: undefined }"
|
|
255
273
|
role="img"
|
|
256
274
|
:aria-label="alt || undefined"
|
|
257
|
-
:class="
|
|
258
|
-
:style="`width: ${imgWidth}px;`"
|
|
275
|
+
:class="cropClass"
|
|
259
276
|
>
|
|
260
277
|
<div
|
|
261
278
|
:class="[
|
|
@@ -278,7 +295,7 @@ const imgClass = 'max-w-full align-middle'
|
|
|
278
295
|
role="img"
|
|
279
296
|
:aria-label="alt || undefined"
|
|
280
297
|
:class="['overflow-hidden table max-w-full', parsedClass.className]"
|
|
281
|
-
:style="`width: ${imgWidth}px;`"
|
|
298
|
+
:style="hasWidth ? `width: ${imgWidth}px;` : undefined"
|
|
282
299
|
>
|
|
283
300
|
<div
|
|
284
301
|
:class="[
|
|
@@ -300,16 +317,16 @@ const imgClass = 'max-w-full align-middle'
|
|
|
300
317
|
<picture>
|
|
301
318
|
<source v-if="darkSrc" :srcset="darkSrc" media="(prefers-color-scheme: dark)">
|
|
302
319
|
<source v-if="motionSrc" :srcset="motionSrc" :type="motionType || undefined" media="(prefers-reduced-motion: no-preference)">
|
|
303
|
-
<img v-bind="attrs" :src="src" :alt="alt" :width="imgWidth" :class="imgClass">
|
|
320
|
+
<img v-bind="attrs" :src="src" :alt="alt" :width="hasWidth ? imgWidth : undefined" :data-maizzle-img-width="hasWidth ? undefined : ''" :class="imgClass" data-juice-duplicates="false">
|
|
304
321
|
</picture>
|
|
305
322
|
</a>
|
|
306
323
|
<picture v-else-if="usePicture">
|
|
307
324
|
<source v-if="darkSrc" :srcset="darkSrc" media="(prefers-color-scheme: dark)">
|
|
308
325
|
<source v-if="motionSrc" :srcset="motionSrc" :type="motionType || undefined" media="(prefers-reduced-motion: no-preference)">
|
|
309
|
-
<img v-bind="attrs" :src="src" :alt="alt" :width="imgWidth" :class="imgClass">
|
|
326
|
+
<img v-bind="attrs" :src="src" :alt="alt" :width="hasWidth ? imgWidth : undefined" :data-maizzle-img-width="hasWidth ? undefined : ''" :class="imgClass" data-juice-duplicates="false">
|
|
310
327
|
</picture>
|
|
311
328
|
<a v-else-if="href" :href="href">
|
|
312
|
-
<img v-bind="attrs" :src="src" :alt="alt" :width="imgWidth" :class="imgClass">
|
|
329
|
+
<img v-bind="attrs" :src="src" :alt="alt" :width="hasWidth ? imgWidth : undefined" :data-maizzle-img-width="hasWidth ? undefined : ''" :class="imgClass" data-juice-duplicates="false">
|
|
313
330
|
</a>
|
|
314
|
-
<img v-else v-bind="attrs" :src="src" :alt="alt" :width="imgWidth" :class="imgClass">
|
|
331
|
+
<img v-else v-bind="attrs" :src="src" :alt="alt" :width="hasWidth ? imgWidth : undefined" :data-maizzle-img-width="hasWidth ? undefined : ''" :class="imgClass" data-juice-duplicates="false">
|
|
315
332
|
</template>
|
|
@@ -116,7 +116,7 @@ const htmlXmlns = computed(() => outlookFallback ? {
|
|
|
116
116
|
<MsoHead v-if="outlookFallback" />
|
|
117
117
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
118
118
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous">
|
|
119
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet" media="screen">
|
|
119
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" media="screen">
|
|
120
120
|
<style>
|
|
121
121
|
@import "@maizzle/tailwindcss";
|
|
122
122
|
|
|
@@ -3,7 +3,8 @@ import { createStaticVNode, inject, type PropType } from 'vue'
|
|
|
3
3
|
import { createMarkdownExit, type MarkdownExitOptions } from 'markdown-exit'
|
|
4
4
|
import { codeToHtml, type BundledTheme } from 'shiki'
|
|
5
5
|
import { defu } from 'defu'
|
|
6
|
-
import { MaizzleConfigKey } from '../composables/useConfig
|
|
6
|
+
import { MaizzleConfigKey } from '../composables/useConfig'
|
|
7
|
+
import { shikiToCodeBlock } from './utils'
|
|
7
8
|
|
|
8
9
|
export default {
|
|
9
10
|
props: {
|
|
@@ -62,9 +63,9 @@ export default {
|
|
|
62
63
|
* still works standalone, when no config is provided.
|
|
63
64
|
*/
|
|
64
65
|
const mdConfig = inject(MaizzleConfigKey, undefined)?.markdown ?? {}
|
|
65
|
-
const markdownOptions = mdConfig.markdownOptions
|
|
66
|
-
const markdownUses = mdConfig.markdownUses
|
|
67
|
-
const markdownSetup = mdConfig.markdownSetup
|
|
66
|
+
const markdownOptions = mdConfig.markdownOptions
|
|
67
|
+
const markdownUses = mdConfig.markdownUses
|
|
68
|
+
const markdownSetup = mdConfig.markdownSetup
|
|
68
69
|
const theme = props.shikiTheme ?? mdConfig.shikiTheme ?? 'github-dark-high-contrast'
|
|
69
70
|
|
|
70
71
|
const md = createMarkdownExit(defu(
|
|
@@ -89,23 +90,17 @@ export default {
|
|
|
89
90
|
* code-block wrapping below composes over whatever they emit.
|
|
90
91
|
*/
|
|
91
92
|
for (const use of markdownUses ?? []) {
|
|
92
|
-
if (Array.isArray(use)) md.use(...use)
|
|
93
|
+
if (Array.isArray(use)) md.use(use[0], ...use.slice(1))
|
|
93
94
|
else md.use(use)
|
|
94
95
|
}
|
|
95
96
|
await markdownSetup?.(md)
|
|
96
97
|
|
|
97
|
-
const wrapPre = (html: string) =>
|
|
98
|
-
`<table class="w-full"><tr><td class="max-w-0 mso-padding-alt-4">${html}</td></tr></table>\n`
|
|
99
|
-
|
|
100
98
|
const defaultFence = md.renderer.rules.fence!
|
|
101
|
-
md.renderer.rules.fence = (...args) =>
|
|
102
|
-
|
|
103
|
-
if (typeof result === 'string') return wrapPre(result)
|
|
104
|
-
return result.then(wrapPre)
|
|
105
|
-
}
|
|
99
|
+
md.renderer.rules.fence = (...args) =>
|
|
100
|
+
Promise.resolve(defaultFence(...args)).then(shikiToCodeBlock)
|
|
106
101
|
|
|
107
102
|
const defaultCodeBlock = md.renderer.rules.code_block!
|
|
108
|
-
md.renderer.rules.code_block = (...args) =>
|
|
103
|
+
md.renderer.rules.code_block = (...args) => shikiToCodeBlock(defaultCodeBlock(...args) as string)
|
|
109
104
|
|
|
110
105
|
let html = await md.renderAsync(source)
|
|
111
106
|
|
|
@@ -21,7 +21,7 @@ const escapeAttr = (v: string) =>
|
|
|
21
21
|
* fall through to the caller's default.
|
|
22
22
|
*/
|
|
23
23
|
function tokenToPx(token: string): number {
|
|
24
|
-
const seg = token.
|
|
24
|
+
const seg = token.slice(token.lastIndexOf(':') + 1)
|
|
25
25
|
const m = seg.match(/^(?:size|w|h)-(.+)$/)
|
|
26
26
|
if (!m) return 0
|
|
27
27
|
const v = m[1]
|
|
@@ -45,7 +45,7 @@ function partition(cls: string): { neutral: string[]; sizing: string[] } {
|
|
|
45
45
|
const neutral: string[] = []
|
|
46
46
|
const sizing: string[] = []
|
|
47
47
|
for (const t of cls.split(/\s+/).filter(Boolean)) {
|
|
48
|
-
const last = t.
|
|
48
|
+
const last = t.slice(t.lastIndexOf(':') + 1)
|
|
49
49
|
if (/^(?:size|w|h|min-w|min-h|max-w|max-h)-/.test(last)) sizing.push(t)
|
|
50
50
|
else neutral.push(t)
|
|
51
51
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, createStaticVNode, useAttrs } from 'vue'
|
|
3
|
+
import { twMerge } from 'tailwind-merge'
|
|
3
4
|
import { hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp } from './utils.ts'
|
|
4
5
|
import { useOutlookFallback } from '../composables/useOutlookFallback'
|
|
5
6
|
|
|
@@ -65,15 +66,16 @@ const useMarker = outlookFallback && props.width == null && userHasWidth.value
|
|
|
65
66
|
const msoId = useMarker ? nextId('s') : null
|
|
66
67
|
const tdId = outlookFallback ? nextId('st') : null
|
|
67
68
|
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
if (props.width
|
|
71
|
-
|
|
72
|
-
return parts.length ? parts.join('; ') : undefined
|
|
69
|
+
const mergedClass = computed(() => {
|
|
70
|
+
const userClass = (attrs.class as string) ?? ''
|
|
71
|
+
if (props.width == null) return userClass || undefined
|
|
72
|
+
return twMerge(`max-w-[${normalizeToPixels(props.width)}]`, userClass)
|
|
73
73
|
})
|
|
74
74
|
|
|
75
|
+
const divStyle = computed(() => userStyle.value || undefined)
|
|
76
|
+
|
|
75
77
|
const restAttrs = computed(() => {
|
|
76
|
-
const { style: _, ...rest } = attrs
|
|
78
|
+
const { style: _, class: __, ...rest } = attrs
|
|
77
79
|
return rest
|
|
78
80
|
})
|
|
79
81
|
|
|
@@ -106,6 +108,7 @@ const MsoAfter = () => createStaticVNode(
|
|
|
106
108
|
<MsoBefore v-if="outlookFallback" />
|
|
107
109
|
<div
|
|
108
110
|
v-bind="restAttrs"
|
|
111
|
+
:class="mergedClass"
|
|
109
112
|
:style="divStyle"
|
|
110
113
|
:data-maizzle-msow-id="msoId"
|
|
111
114
|
:data-maizzle-msow-fallback="useMarker ? '100%' : null"
|
package/dist/components/Text.vue
CHANGED
|
@@ -18,8 +18,8 @@ const props = defineProps({
|
|
|
18
18
|
|
|
19
19
|
const attrs = useAttrs()
|
|
20
20
|
|
|
21
|
-
const defaultClass = computed(() => props.as === 'span' ? '
|
|
22
|
-
const mergedClass = computed(() => twMerge(defaultClass.value, attrs.class as string))
|
|
21
|
+
const defaultClass = computed(() => props.as === 'span' ? '' : 'mt-4 text-base')
|
|
22
|
+
const mergedClass = computed(() => twMerge(defaultClass.value, attrs.class as string) || undefined)
|
|
23
23
|
</script>
|
|
24
24
|
|
|
25
25
|
<template>
|
|
@@ -23,6 +23,30 @@ declare const outlookFallbackProp: {
|
|
|
23
23
|
readonly type: BooleanConstructor;
|
|
24
24
|
readonly default: null;
|
|
25
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Default utility classes for a code-block `<pre>`. `whitespace-pre!` is
|
|
28
|
+
* forced important so Gmail's stylesheet can't reset it to `normal`, and
|
|
29
|
+
* `mb-0` strips the browser's default `<pre>` bottom margin.
|
|
30
|
+
*/
|
|
31
|
+
declare function codeBlockPreClass(bg: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Build the email-safe table wrapper around highlighted code. Shared by the
|
|
34
|
+
* `<CodeBlock>` component and the Markdown fenced/indented code-block
|
|
35
|
+
* rules so both render identical markup: a full-width table whose
|
|
36
|
+
* cell carries the theme background, wrapping a `<pre>` styled
|
|
37
|
+
* with utility classes (not Shiki's raw inline styles).
|
|
38
|
+
*/
|
|
39
|
+
declare function buildCodeBlock(codeContent: string, bg: string, options?: {
|
|
40
|
+
preClass?: string;
|
|
41
|
+
tdClass?: string;
|
|
42
|
+
styleAttr?: string;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* Re-wrap a Shiki (or plain markdown-it) `<pre><code>` block as a CodeBlock,
|
|
46
|
+
* pulling the inner code and the theme background out of the highlighted
|
|
47
|
+
* HTML. Falls back to a white background for unhighlighted blocks.
|
|
48
|
+
*/
|
|
49
|
+
declare function shikiToCodeBlock(highlighted: string): string;
|
|
26
50
|
//#endregion
|
|
27
|
-
export { hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp };
|
|
51
|
+
export { buildCodeBlock, codeBlockPreClass, hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp, shikiToCodeBlock };
|
|
28
52
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAsB;AAAxD;;;;AAAwD;AAiBxD;;;AAjBA,iBAiBgB,MAAA,CAAO,MAAc;AAAA,iBAKrB,eAAA,CAAgB,QAAgB;AAAA,iBAQhC,eAAA,CAAgB,QAAgB;AAAA,iBAIhC,gBAAA,CAAiB,QAAgB;AAAA,iBAQjC,gBAAA,CAAiB,QAAgB;;AApBD;AAQhD;;;;cAsBa,mBAAA;EAAA,eAGH,kBAAA;EAAA"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAsB;AAAxD;;;;AAAwD;AAiBxD;;;AAjBA,iBAiBgB,MAAA,CAAO,MAAc;AAAA,iBAKrB,eAAA,CAAgB,QAAgB;AAAA,iBAQhC,eAAA,CAAgB,QAAgB;AAAA,iBAIhC,gBAAA,CAAiB,QAAgB;AAAA,iBAQjC,gBAAA,CAAiB,QAAgB;;AApBD;AAQhD;;;;cAsBa,mBAAA;EAAA,eAGH,kBAAA;EAAA;;;AArBuC;AAQjD;;;iBAoBgB,iBAAA,CAAkB,EAAU;AApBK;AAUjD;;;;;;AAViD,iBA+BjC,cAAA,CACd,WAAA,UACA,EAAA,UACA,OAAA;EAAW,QAAA;EAAmB,OAAA;EAAkB,SAAA;AAAA;;;AAdN;AAW5C;;iBAoBgB,gBAAA,CAAiB,WAAmB"}
|
package/dist/components/utils.js
CHANGED
|
@@ -44,7 +44,35 @@ const outlookFallbackProp = {
|
|
|
44
44
|
type: Boolean,
|
|
45
45
|
default: null
|
|
46
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Default utility classes for a code-block `<pre>`. `whitespace-pre!` is
|
|
49
|
+
* forced important so Gmail's stylesheet can't reset it to `normal`, and
|
|
50
|
+
* `mb-0` strips the browser's default `<pre>` bottom margin.
|
|
51
|
+
*/
|
|
52
|
+
function codeBlockPreClass(bg) {
|
|
53
|
+
return `font-mono bg-[${bg}] p-4 mb-0 overflow-auto whitespace-pre! [word-wrap:normal] [word-break:normal] [word-spacing:normal]`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the email-safe table wrapper around highlighted code. Shared by the
|
|
57
|
+
* `<CodeBlock>` component and the Markdown fenced/indented code-block
|
|
58
|
+
* rules so both render identical markup: a full-width table whose
|
|
59
|
+
* cell carries the theme background, wrapping a `<pre>` styled
|
|
60
|
+
* with utility classes (not Shiki's raw inline styles).
|
|
61
|
+
*/
|
|
62
|
+
function buildCodeBlock(codeContent, bg, options = {}) {
|
|
63
|
+
const preClass = options.preClass ?? codeBlockPreClass(bg);
|
|
64
|
+
return `<table class="w-full"><tr><td class="${options.tdClass ?? `bg-[${bg}] max-w-0 mso-padding-alt-4`}"><pre class="${preClass}"${options.styleAttr ?? ""} data-juice-important><code>${codeContent}</code></pre></td></tr></table>`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Re-wrap a Shiki (or plain markdown-it) `<pre><code>` block as a CodeBlock,
|
|
68
|
+
* pulling the inner code and the theme background out of the highlighted
|
|
69
|
+
* HTML. Falls back to a white background for unhighlighted blocks.
|
|
70
|
+
*/
|
|
71
|
+
function shikiToCodeBlock(highlighted) {
|
|
72
|
+
const bg = highlighted.match(/background-color:\s*(#[0-9a-fA-F]+)/)?.[1] ?? "#fff";
|
|
73
|
+
return buildCodeBlock(highlighted.trim().replace(/^<pre[^>]*><code[^>]*>/, "").replace(/<\/code><\/pre>$/, ""), bg);
|
|
74
|
+
}
|
|
47
75
|
//#endregion
|
|
48
|
-
export { hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp };
|
|
76
|
+
export { buildCodeBlock, codeBlockPreClass, hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels, outlookFallbackProp, shikiToCodeBlock };
|
|
49
77
|
|
|
50
78
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../src/components/utils.ts"],"sourcesContent":["export function normalizeToPixels(value: string | number): string {\n if (typeof value === 'number' || Number.isFinite(Number(value))) {\n return `${value}px`\n }\n return value\n}\n\nconst counters: Record<string, number> = {}\n\n/**\n * Module-scoped sequential ID generator. Used by components to mint\n * unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.\n *\n * Must live here (not inside `<script setup>`) because Vue compiles\n * `<script setup>` into the component's `setup()` function — any\n * `let counter = 0` there resets per instance, causing id collisions.\n */\nexport function nextId(prefix: string): string {\n counters[prefix] = (counters[prefix] ?? 0) + 1\n return `${prefix}${counters[prefix]}`\n}\n\nexport function hasWidthUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(w-|max-w-|min-w-)/.test(clean)\n })\n}\n\nexport function hasWidthInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-width|width)\\s*:/i.test(styleStr)\n}\n\nexport function hasHeightUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(h-|max-h-|min-h-)/.test(clean)\n })\n}\n\nexport function hasHeightInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-height|height)\\s*:/i.test(styleStr)\n}\n\n/**\n * Shared prop for components that emit MSO/VML fallback markup. The\n * `null` default acts as the \"unset\" sentinel — `useOutlookFallback`\n * treats `null` as inherit-from-ancestor (root default `true`),\n * letting users override per-component without losing inheritance.\n */\nexport const outlookFallbackProp = {\n type: Boolean,\n default: null,\n} as const\n\n"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;CAChE,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,KAAK,CAAC,GAC5D,OAAO,GAAG,MAAM;CAElB,OAAO;AACT;AAEA,MAAM,WAAmC,CAAC;;;;;;;;;AAU1C,SAAgB,OAAO,QAAwB;CAC7C,SAAS,WAAW,SAAS,WAAW,KAAK;CAC7C,OAAO,GAAG,SAAS,SAAS;AAC9B;AAEA,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,SAAS,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../src/components/utils.ts"],"sourcesContent":["export function normalizeToPixels(value: string | number): string {\n if (typeof value === 'number' || Number.isFinite(Number(value))) {\n return `${value}px`\n }\n return value\n}\n\nconst counters: Record<string, number> = {}\n\n/**\n * Module-scoped sequential ID generator. Used by components to mint\n * unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.\n *\n * Must live here (not inside `<script setup>`) because Vue compiles\n * `<script setup>` into the component's `setup()` function — any\n * `let counter = 0` there resets per instance, causing id collisions.\n */\nexport function nextId(prefix: string): string {\n counters[prefix] = (counters[prefix] ?? 0) + 1\n return `${prefix}${counters[prefix]}`\n}\n\nexport function hasWidthUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(w-|max-w-|min-w-)/.test(clean)\n })\n}\n\nexport function hasWidthInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-width|width)\\s*:/i.test(styleStr)\n}\n\nexport function hasHeightUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(h-|max-h-|min-h-)/.test(clean)\n })\n}\n\nexport function hasHeightInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-height|height)\\s*:/i.test(styleStr)\n}\n\n/**\n * Shared prop for components that emit MSO/VML fallback markup. The\n * `null` default acts as the \"unset\" sentinel — `useOutlookFallback`\n * treats `null` as inherit-from-ancestor (root default `true`),\n * letting users override per-component without losing inheritance.\n */\nexport const outlookFallbackProp = {\n type: Boolean,\n default: null,\n} as const\n\n/**\n * Default utility classes for a code-block `<pre>`. `whitespace-pre!` is\n * forced important so Gmail's stylesheet can't reset it to `normal`, and\n * `mb-0` strips the browser's default `<pre>` bottom margin.\n */\nexport function codeBlockPreClass(bg: string): string {\n return `font-mono bg-[${bg}] p-4 mb-0 overflow-auto whitespace-pre! [word-wrap:normal] [word-break:normal] [word-spacing:normal]`\n}\n\n/**\n * Build the email-safe table wrapper around highlighted code. Shared by the\n * `<CodeBlock>` component and the Markdown fenced/indented code-block\n * rules so both render identical markup: a full-width table whose\n * cell carries the theme background, wrapping a `<pre>` styled\n * with utility classes (not Shiki's raw inline styles).\n */\nexport function buildCodeBlock(\n codeContent: string,\n bg: string,\n options: { preClass?: string; tdClass?: string; styleAttr?: string } = {},\n): string {\n const preClass = options.preClass ?? codeBlockPreClass(bg)\n const tdClass = options.tdClass ?? `bg-[${bg}] max-w-0 mso-padding-alt-4`\n const styleAttr = options.styleAttr ?? ''\n\n // `data-juice-important` tells the CSS inliner to keep `!important` on this\n // element's inlined declarations (e.g. `white-space: pre !important`), which\n // it strips by default. Juice removes the attribute from the output.\n return `<table class=\"w-full\"><tr><td class=\"${tdClass}\"><pre class=\"${preClass}\"${styleAttr} data-juice-important><code>${codeContent}</code></pre></td></tr></table>`\n}\n\n/**\n * Re-wrap a Shiki (or plain markdown-it) `<pre><code>` block as a CodeBlock,\n * pulling the inner code and the theme background out of the highlighted\n * HTML. Falls back to a white background for unhighlighted blocks.\n */\nexport function shikiToCodeBlock(highlighted: string): string {\n const bg = highlighted.match(/background-color:\\s*(#[0-9a-fA-F]+)/)?.[1] ?? '#fff'\n const codeContent = highlighted\n .trim()\n .replace(/^<pre[^>]*><code[^>]*>/, '')\n .replace(/<\\/code><\\/pre>$/, '')\n\n return buildCodeBlock(codeContent, bg)\n}\n\n"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;CAChE,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,KAAK,CAAC,GAC5D,OAAO,GAAG,MAAM;CAElB,OAAO;AACT;AAEA,MAAM,WAAmC,CAAC;;;;;;;;;AAU1C,SAAgB,OAAO,QAAwB;CAC7C,SAAS,WAAW,SAAS,WAAW,KAAK;CAC7C,OAAO,GAAG,SAAS,SAAS;AAC9B;AAEA,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,SAAS,MAAM,KAAK,CAAC,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,GAAA,CAChB,QAAQ,MAAM,EAAE;EACtC,OAAO,sBAAsB,KAAK,KAAK;CACzC,CAAC;AACH;AAEA,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,qCAAqC,KAAK,QAAQ;AAC3D;AAEA,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,SAAS,MAAM,KAAK,CAAC,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,GAAA,CAChB,QAAQ,MAAM,EAAE;EACtC,OAAO,sBAAsB,KAAK,KAAK;CACzC,CAAC;AACH;AAEA,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,uCAAuC,KAAK,QAAQ;AAC7D;;;;;;;AAQA,MAAa,sBAAsB;CACjC,MAAM;CACN,SAAS;AACX;;;;;;AAOA,SAAgB,kBAAkB,IAAoB;CACpD,OAAO,iBAAiB,GAAG;AAC7B;;;;;;;;AASA,SAAgB,eACd,aACA,IACA,UAAuE,CAAC,GAChE;CACR,MAAM,WAAW,QAAQ,YAAY,kBAAkB,EAAE;CAOzD,OAAO,wCANS,QAAQ,WAAW,OAAO,GAAG,6BAMU,gBAAgB,SAAS,GAL9D,QAAQ,aAAa,GAKsD,8BAA8B,YAAY;AACzI;;;;;;AAOA,SAAgB,iBAAiB,aAA6B;CAC5D,MAAM,KAAK,YAAY,MAAM,qCAAqC,CAAC,GAAG,MAAM;CAM5E,OAAO,eALa,YACjB,KAAK,CAAC,CACN,QAAQ,0BAA0B,EAAE,CAAC,CACrC,QAAQ,oBAAoB,EAEC,GAAG,EAAE;AACvC"}
|
package/dist/components/utils.ts
CHANGED
|
@@ -55,3 +55,49 @@ export const outlookFallbackProp = {
|
|
|
55
55
|
default: null,
|
|
56
56
|
} as const
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Default utility classes for a code-block `<pre>`. `whitespace-pre!` is
|
|
60
|
+
* forced important so Gmail's stylesheet can't reset it to `normal`, and
|
|
61
|
+
* `mb-0` strips the browser's default `<pre>` bottom margin.
|
|
62
|
+
*/
|
|
63
|
+
export function codeBlockPreClass(bg: string): string {
|
|
64
|
+
return `font-mono bg-[${bg}] p-4 mb-0 overflow-auto whitespace-pre! [word-wrap:normal] [word-break:normal] [word-spacing:normal]`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Build the email-safe table wrapper around highlighted code. Shared by the
|
|
69
|
+
* `<CodeBlock>` component and the Markdown fenced/indented code-block
|
|
70
|
+
* rules so both render identical markup: a full-width table whose
|
|
71
|
+
* cell carries the theme background, wrapping a `<pre>` styled
|
|
72
|
+
* with utility classes (not Shiki's raw inline styles).
|
|
73
|
+
*/
|
|
74
|
+
export function buildCodeBlock(
|
|
75
|
+
codeContent: string,
|
|
76
|
+
bg: string,
|
|
77
|
+
options: { preClass?: string; tdClass?: string; styleAttr?: string } = {},
|
|
78
|
+
): string {
|
|
79
|
+
const preClass = options.preClass ?? codeBlockPreClass(bg)
|
|
80
|
+
const tdClass = options.tdClass ?? `bg-[${bg}] max-w-0 mso-padding-alt-4`
|
|
81
|
+
const styleAttr = options.styleAttr ?? ''
|
|
82
|
+
|
|
83
|
+
// `data-juice-important` tells the CSS inliner to keep `!important` on this
|
|
84
|
+
// element's inlined declarations (e.g. `white-space: pre !important`), which
|
|
85
|
+
// it strips by default. Juice removes the attribute from the output.
|
|
86
|
+
return `<table class="w-full"><tr><td class="${tdClass}"><pre class="${preClass}"${styleAttr} data-juice-important><code>${codeContent}</code></pre></td></tr></table>`
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Re-wrap a Shiki (or plain markdown-it) `<pre><code>` block as a CodeBlock,
|
|
91
|
+
* pulling the inner code and the theme background out of the highlighted
|
|
92
|
+
* HTML. Falls back to a white background for unhighlighted blocks.
|
|
93
|
+
*/
|
|
94
|
+
export function shikiToCodeBlock(highlighted: string): string {
|
|
95
|
+
const bg = highlighted.match(/background-color:\s*(#[0-9a-fA-F]+)/)?.[1] ?? '#fff'
|
|
96
|
+
const codeContent = highlighted
|
|
97
|
+
.trim()
|
|
98
|
+
.replace(/^<pre[^>]*><code[^>]*>/, '')
|
|
99
|
+
.replace(/<\/code><\/pre>$/, '')
|
|
100
|
+
|
|
101
|
+
return buildCodeBlock(codeContent, bg)
|
|
102
|
+
}
|
|
103
|
+
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConfig.d.ts","names":[],"sources":["../../src/composables/useConfig.ts"],"mappings":";;;;;;;AAWA;;;;cAAa,gBAAA,EAAkB,YAAY,CAAC,aAAA;AAAA,iBAE5B,SAAA,
|
|
1
|
+
{"version":3,"file":"useConfig.d.ts","names":[],"sources":["../../src/composables/useConfig.ts"],"mappings":";;;;;;;AAWA;;;;cAAa,gBAAA,EAAkB,YAAY,CAAC,aAAA;AAAA,iBAE5B,SAAA,IAAa,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCurrentTemplate.d.ts","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"mappings":";;;;;AAmBA;;iBAAgB,mBAAA,CAAoB,MAA8B,EAAtB,UAAU;;AAAY;AAuBlE;;;;AAAgD;;;;;;;;;;;;;iBAAhC,kBAAA,
|
|
1
|
+
{"version":3,"file":"useCurrentTemplate.d.ts","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"mappings":";;;;;AAmBA;;iBAAgB,mBAAA,CAAoB,MAA8B,EAAtB,UAAU;;AAAY;AAuBlE;;;;AAAgD;;;;;;;;;;;;;iBAAhC,kBAAA,IAAsB,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEvent.d.ts","names":[],"sources":["../../src/composables/useEvent.ts"],"mappings":";;;;;AAcA;;;;;;;;iBAAgB,QAAA,WAAmB,SAAA,
|
|
1
|
+
{"version":3,"file":"useEvent.d.ts","names":[],"sources":["../../src/composables/useEvent.ts"],"mappings":";;;;;AAcA;;;;;;;;iBAAgB,QAAA,WAAmB,SAAA,EAAW,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,QAAA,CAAS,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFont.js","names":[],"sources":["../../src/composables/useFont.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\ntype FontCategory = 'sans' | 'serif' | 'mono' | 'display' | 'handwriting'\n\nconst FAMILY_CATEGORIES: Record<string, FontCategory> = {\n // Sans-serif\n 'Roboto': 'sans',\n 'Open Sans': 'sans',\n 'Inter': 'sans',\n 'Lato': 'sans',\n 'Montserrat': 'sans',\n // Serif\n 'Merriweather': 'serif',\n 'Playfair Display': 'serif',\n 'Lora': 'serif',\n 'PT Serif': 'serif',\n 'Noto Serif': 'serif',\n // Display\n 'Oswald': 'display',\n 'Bebas Neue': 'display',\n 'Anton': 'display',\n 'Lobster': 'display',\n 'Pacifico': 'display',\n // Handwriting\n 'Dancing Script': 'handwriting',\n 'Caveat': 'handwriting',\n 'Shadows Into Light': 'handwriting',\n 'Satisfy': 'handwriting',\n 'Great Vibes': 'handwriting',\n // Monospace\n 'Roboto Mono': 'mono',\n 'Source Code Pro': 'mono',\n 'JetBrains Mono': 'mono',\n 'Fira Code': 'mono',\n 'Inconsolata': 'mono',\n}\n\nconst DEFAULT_FALLBACKS: Record<FontCategory, string> = {\n sans: 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\n mono: 'ui-monospace, Menlo, Consolas, monospace',\n display: 'Impact, \"Arial Black\", system-ui, sans-serif',\n handwriting: '\"Segoe Script\", \"Brush Script MT\", cursive',\n}\n\nexport type FontProvider = 'google' | 'bunny'\n\nexport interface UseFontOptions {\n /**\n * A single font family name, e.g. `\"Roboto\"` or `\"Open Sans\"`.\n *\n * For fallback fonts, use the `fallback` option instead of a\n * comma-separated list here.\n */\n family: string\n /** CSS fallback list appended to the `font-family` declaration. */\n fallback?: string\n /**\n * Font provider used to build the stylesheet URL when `url` is omitted.\n * Bunny Fonts is a drop-in, privacy-friendly Google Fonts mirror.\n * @default 'google'\n */\n provider?: FontProvider\n /**\n * Stylesheet URL. When provided, used as-is for the `<link href>`.\n * When omitted, a URL is built from `provider`, `family`, `weights`,\n * `display` and `styles`.\n */\n url?: string\n /** Font weights to load. Ignored when `url` is provided. */\n weights?: number[]\n /** `font-display` value. Ignored when `url` is provided. */\n display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'\n /** Font styles to load. Ignored when `url` is provided. */\n styles?: Array<'normal' | 'italic'>\n}\n\nconst PROVIDER_BASE_URL: Record<FontProvider, string> = {\n google: 'https://fonts.googleapis.com/css2',\n bunny: 'https://fonts.bunny.net/css2',\n}\n\nfunction slugify(family: string): string {\n return family\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n}\n\nfunction buildProviderUrl(opts: Required<Omit<UseFontOptions, 'url' | 'fallback'>>): string {\n const familyParam = opts.family.trim().replace(/\\s+/g, '+')\n const weights = [...opts.weights].sort((a, b) => a - b)\n const hasItalic = opts.styles.includes('italic')\n const hasNormal = opts.styles.includes('normal')\n\n const axis = hasItalic\n ? `:ital,wght@${weights.flatMap(w => [\n ...(hasNormal ? [`0,${w}`] : []),\n `1,${w}`,\n ]).join(';')}`\n : `:wght@${weights.join(';')}`\n\n return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`\n}\n\n/**\n * Register a font for the current email template.\n *\n * Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`\n * (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`\n * and merges `--font-{slug}` declarations into the template's existing\n * `@import \"tailwindcss\"` style block so a `font-{slug}` utility class\n * is generated. If no Tailwind import is found, falls back to a `:root`\n * declaration so the CSS variable is still available.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })\n * ```\n */\nexport function useFont(options: UseFontOptions): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n ctx.fonts = ctx.fonts ?? []\n if (ctx.fonts.some(f => f.family === options.family)) return\n\n const url = options.url ?? buildProviderUrl({\n family: options.family,\n provider: options.provider ?? 'google',\n weights: options.weights ?? [400],\n display: options.display ?? 'swap',\n styles: options.styles ?? ['normal'],\n })\n\n const fallback = options.fallback\n ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? 'sans']\n const quoted = /\\s/.test(options.family) ? `\"${options.family}\"` : options.family\n const declaration = `${quoted}, ${fallback}`\n\n ctx.fonts.push({\n family: options.family,\n slug: slugify(options.family),\n declaration,\n url,\n })\n}\n"],"mappings":";;;AAKA,MAAM,oBAAkD;CAEtD,UAAU;CACV,aAAa;CACb,SAAS;CACT,QAAQ;CACR,cAAc;CAEd,gBAAgB;CAChB,oBAAoB;CACpB,QAAQ;CACR,YAAY;CACZ,cAAc;CAEd,UAAU;CACV,cAAc;CACd,SAAS;CACT,WAAW;CACX,YAAY;CAEZ,kBAAkB;CAClB,UAAU;CACV,sBAAsB;CACtB,WAAW;CACX,eAAe;CAEf,eAAe;CACf,mBAAmB;CACnB,kBAAkB;CAClB,aAAa;CACb,eAAe;AACjB;AAEA,MAAM,oBAAkD;CACtD,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,aAAa;AACf;AAkCA,MAAM,oBAAkD;CACtD,QAAQ;CACR,OAAO;AACT;AAEA,SAAS,QAAQ,QAAwB;CACvC,OAAO,OACJ,KAAK,
|
|
1
|
+
{"version":3,"file":"useFont.js","names":[],"sources":["../../src/composables/useFont.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\ntype FontCategory = 'sans' | 'serif' | 'mono' | 'display' | 'handwriting'\n\nconst FAMILY_CATEGORIES: Record<string, FontCategory> = {\n // Sans-serif\n 'Roboto': 'sans',\n 'Open Sans': 'sans',\n 'Inter': 'sans',\n 'Lato': 'sans',\n 'Montserrat': 'sans',\n // Serif\n 'Merriweather': 'serif',\n 'Playfair Display': 'serif',\n 'Lora': 'serif',\n 'PT Serif': 'serif',\n 'Noto Serif': 'serif',\n // Display\n 'Oswald': 'display',\n 'Bebas Neue': 'display',\n 'Anton': 'display',\n 'Lobster': 'display',\n 'Pacifico': 'display',\n // Handwriting\n 'Dancing Script': 'handwriting',\n 'Caveat': 'handwriting',\n 'Shadows Into Light': 'handwriting',\n 'Satisfy': 'handwriting',\n 'Great Vibes': 'handwriting',\n // Monospace\n 'Roboto Mono': 'mono',\n 'Source Code Pro': 'mono',\n 'JetBrains Mono': 'mono',\n 'Fira Code': 'mono',\n 'Inconsolata': 'mono',\n}\n\nconst DEFAULT_FALLBACKS: Record<FontCategory, string> = {\n sans: 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\n mono: 'ui-monospace, Menlo, Consolas, monospace',\n display: 'Impact, \"Arial Black\", system-ui, sans-serif',\n handwriting: '\"Segoe Script\", \"Brush Script MT\", cursive',\n}\n\nexport type FontProvider = 'google' | 'bunny'\n\nexport interface UseFontOptions {\n /**\n * A single font family name, e.g. `\"Roboto\"` or `\"Open Sans\"`.\n *\n * For fallback fonts, use the `fallback` option instead of a\n * comma-separated list here.\n */\n family: string\n /** CSS fallback list appended to the `font-family` declaration. */\n fallback?: string\n /**\n * Font provider used to build the stylesheet URL when `url` is omitted.\n * Bunny Fonts is a drop-in, privacy-friendly Google Fonts mirror.\n * @default 'google'\n */\n provider?: FontProvider\n /**\n * Stylesheet URL. When provided, used as-is for the `<link href>`.\n * When omitted, a URL is built from `provider`, `family`, `weights`,\n * `display` and `styles`.\n */\n url?: string\n /** Font weights to load. Ignored when `url` is provided. */\n weights?: number[]\n /** `font-display` value. Ignored when `url` is provided. */\n display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'\n /** Font styles to load. Ignored when `url` is provided. */\n styles?: Array<'normal' | 'italic'>\n}\n\nconst PROVIDER_BASE_URL: Record<FontProvider, string> = {\n google: 'https://fonts.googleapis.com/css2',\n bunny: 'https://fonts.bunny.net/css2',\n}\n\nfunction slugify(family: string): string {\n return family\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n}\n\nfunction buildProviderUrl(opts: Required<Omit<UseFontOptions, 'url' | 'fallback'>>): string {\n const familyParam = opts.family.trim().replace(/\\s+/g, '+')\n const weights = [...opts.weights].sort((a, b) => a - b)\n const hasItalic = opts.styles.includes('italic')\n const hasNormal = opts.styles.includes('normal')\n\n const axis = hasItalic\n ? `:ital,wght@${weights.flatMap(w => [\n ...(hasNormal ? [`0,${w}`] : []),\n `1,${w}`,\n ]).join(';')}`\n : `:wght@${weights.join(';')}`\n\n return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`\n}\n\n/**\n * Register a font for the current email template.\n *\n * Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`\n * (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`\n * and merges `--font-{slug}` declarations into the template's existing\n * `@import \"tailwindcss\"` style block so a `font-{slug}` utility class\n * is generated. If no Tailwind import is found, falls back to a `:root`\n * declaration so the CSS variable is still available.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })\n * ```\n */\nexport function useFont(options: UseFontOptions): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n ctx.fonts = ctx.fonts ?? []\n if (ctx.fonts.some(f => f.family === options.family)) return\n\n const url = options.url ?? buildProviderUrl({\n family: options.family,\n provider: options.provider ?? 'google',\n weights: options.weights ?? [400],\n display: options.display ?? 'swap',\n styles: options.styles ?? ['normal'],\n })\n\n const fallback = options.fallback\n ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? 'sans']\n const quoted = /\\s/.test(options.family) ? `\"${options.family}\"` : options.family\n const declaration = `${quoted}, ${fallback}`\n\n ctx.fonts.push({\n family: options.family,\n slug: slugify(options.family),\n declaration,\n url,\n })\n}\n"],"mappings":";;;AAKA,MAAM,oBAAkD;CAEtD,UAAU;CACV,aAAa;CACb,SAAS;CACT,QAAQ;CACR,cAAc;CAEd,gBAAgB;CAChB,oBAAoB;CACpB,QAAQ;CACR,YAAY;CACZ,cAAc;CAEd,UAAU;CACV,cAAc;CACd,SAAS;CACT,WAAW;CACX,YAAY;CAEZ,kBAAkB;CAClB,UAAU;CACV,sBAAsB;CACtB,WAAW;CACX,eAAe;CAEf,eAAe;CACf,mBAAmB;CACnB,kBAAkB;CAClB,aAAa;CACb,eAAe;AACjB;AAEA,MAAM,oBAAkD;CACtD,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,aAAa;AACf;AAkCA,MAAM,oBAAkD;CACtD,QAAQ;CACR,OAAO;AACT;AAEA,SAAS,QAAQ,QAAwB;CACvC,OAAO,OACJ,KAAK,CAAC,CACN,YAAY,CAAC,CACb,QAAQ,QAAQ,GAAG,CAAC,CACpB,QAAQ,eAAe,EAAE;AAC9B;AAEA,SAAS,iBAAiB,MAAkE;CAC1F,MAAM,cAAc,KAAK,OAAO,KAAK,CAAC,CAAC,QAAQ,QAAQ,GAAG;CAC1D,MAAM,UAAU,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CACtD,MAAM,YAAY,KAAK,OAAO,SAAS,QAAQ;CAC/C,MAAM,YAAY,KAAK,OAAO,SAAS,QAAQ;CAE/C,MAAM,OAAO,YACT,cAAc,QAAQ,SAAQ,MAAK,CACjC,GAAI,YAAY,CAAC,KAAK,GAAG,IAAI,CAAC,GAC9B,KAAK,GACP,CAAC,CAAC,CAAC,KAAK,GAAG,MACX,SAAS,QAAQ,KAAK,GAAG;CAE7B,OAAO,GAAG,kBAAkB,KAAK,UAAU,UAAU,cAAc,KAAK,WAAW,KAAK;AAC1F;;;;;;;;;;;;;;;;AAiBA,SAAgB,QAAQ,SAA+B;CACrD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,CAAC,KAAK;CAEV,IAAI,QAAQ,IAAI,SAAS,CAAC;CAC1B,IAAI,IAAI,MAAM,MAAK,MAAK,EAAE,WAAW,QAAQ,MAAM,GAAG;CAEtD,MAAM,MAAM,QAAQ,OAAO,iBAAiB;EAC1C,QAAQ,QAAQ;EAChB,UAAU,QAAQ,YAAY;EAC9B,SAAS,QAAQ,WAAW,CAAC,GAAG;EAChC,SAAS,QAAQ,WAAW;EAC5B,QAAQ,QAAQ,UAAU,CAAC,QAAQ;CACrC,CAAC;CAED,MAAM,WAAW,QAAQ,YACpB,kBAAkB,kBAAkB,QAAQ,WAAW;CAE5D,MAAM,cAAc,GADL,KAAK,KAAK,QAAQ,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,QAAQ,OAC7C,IAAI;CAElC,IAAI,MAAM,KAAK;EACb,QAAQ,QAAQ;EAChB,MAAM,QAAQ,QAAQ,MAAM;EAC5B;EACA;CACF,CAAC;AACH"}
|
package/dist/config/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import { defaults } from "./defaults.js";
|
|
|
2
2
|
import { defineConfig } from "../composables/defineConfig.js";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
|
-
import { createJiti } from "jiti";
|
|
6
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createJiti } from "jiti";
|
|
7
7
|
import { createDefu } from "defu";
|
|
8
8
|
//#region src/config/index.ts
|
|
9
9
|
const merge = createDefu((obj, key, value) => {
|
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/config/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createJiti } from 'jiti'\nimport { fileURLToPath } from 'node:url'\nimport { createDefu } from 'defu'\n\n// defu that replaces arrays: if user provides content: ['x'], it replaces the default, not appends\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\nimport { defaults } from './defaults.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport { defineConfig } from '../composables/defineConfig.ts'\nexport { defaults } from './defaults.ts'\n\nconst CONFIG_FILES = [\n 'maizzle.config.ts',\n 'maizzle.config.js',\n]\n\n/**\n * Resolve the Maizzle config.\n *\n * Always loads from the config file on disk (maizzle.config.{ts,js}),\n * then merges the programmatic config on top, then fills in defaults.\n */\nexport async function resolveConfig(\n config?: Partial<MaizzleConfig> | string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n // If a string path was provided, load that specific file\n const fileConfig = await loadConfig(\n typeof config === 'string' ? config : undefined,\n cwd,\n )\n\n // Programmatic config (object) overrides file config, which overrides defaults\n const programmaticConfig = typeof config === 'object' && config !== null ? config : {}\n\n const merged = merge(programmaticConfig, fileConfig, defaults) as MaizzleConfig\n\n // Check if root was explicitly provided before resolving\n const hasExplicitRoot = !!(programmaticConfig.root ?? fileConfig.root)\n\n // Resolve root to an absolute path (defaults to cwd)\n const root = resolve(cwd, merged.root ?? '.')\n merged.root = root\n\n // Resolve content patterns relative to root\n if (merged.content) {\n merged.content = merged.content.map(p => {\n // Skip already-absolute or negated patterns\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n // Resolve static source patterns relative to root\n if (merged.static?.source) {\n merged.static.source = merged.static.source.map(p => {\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n /**\n * Resolve components.source paths relative to cwd (not root), since extra\n * component dirs often live outside the root directory. String\n * entries → resolve in-place. Object entries → resolve\n * `path`, preserve `prefix`/`pathPrefix`.\n */\n if (merged.components?.source) {\n const dirs = Array.isArray(merged.components.source)\n ? merged.components.source\n : [merged.components.source]\n\n merged.components.source = dirs.map(entry => {\n if (typeof entry === 'string') {\n return entry.startsWith('/') ? entry : resolve(cwd, entry)\n }\n return {\n ...entry,\n path: entry.path.startsWith('/') ? entry.path : resolve(cwd, entry.path),\n }\n })\n }\n\n /**\n * Default css.base to root when root is explicitly set, so Tailwind resolves\n * @source from the right directory. When root is not set, leave\n * css.base undefined so Tailwind uses its own default (the\n * template file's directory).\n */\n if (hasExplicitRoot && !merged.css?.base) {\n if (!merged.css) merged.css = {}\n merged.css.base = root\n }\n\n return merged\n}\n\nasync function loadConfig(\n configPath?: string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n const jiti = createJiti(fileURLToPath(import.meta.url), { moduleCache: false })\n\n // If an explicit path was provided, use it directly\n if (configPath) {\n const absolutePath = resolve(cwd, configPath)\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`)\n }\n\n const mod = await jiti.import(absolutePath) as any\n return mod.default ?? mod\n }\n\n // Otherwise scan cwd for known config file names\n for (const filename of CONFIG_FILES) {\n const filepath = resolve(cwd, filename)\n\n if (existsSync(filepath)) {\n const mod = await jiti.import(filepath) as any\n return mod.default ?? mod\n }\n }\n\n // No config file found, return empty (defaults will be applied by resolveConfig)\n return {}\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,IAAI,GAAG;EAC3B,IAAI,OAAO;EACX,OAAO;CACT;AACF,CAAC;AAOD,MAAM,eAAe,CACnB,qBACA,mBACF;;;;;;;AAQA,eAAsB,cACpB,QACA,MAAc,QAAQ,IAAI,GACF;CAExB,MAAM,aAAa,MAAM,WACvB,OAAO,WAAW,WAAW,SAAS,KAAA,GACtC,GACF;CAGA,MAAM,qBAAqB,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,CAAC;CAErF,MAAM,SAAS,MAAM,oBAAoB,YAAY,QAAQ;CAG7D,MAAM,kBAAkB,CAAC,EAAE,mBAAmB,QAAQ,WAAW;CAGjE,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG;CAC5C,OAAO,OAAO;CAGd,IAAI,OAAO,SACT,OAAO,UAAU,OAAO,QAAQ,KAAI,MAAK;EAEvC,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,GAAG,GAAG,OAAO;EACnD,OAAO,QAAQ,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/config/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createJiti } from 'jiti'\nimport { fileURLToPath } from 'node:url'\nimport { createDefu } from 'defu'\n\n// defu that replaces arrays: if user provides content: ['x'], it replaces the default, not appends\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\nimport { defaults } from './defaults.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport { defineConfig } from '../composables/defineConfig.ts'\nexport { defaults } from './defaults.ts'\n\nconst CONFIG_FILES = [\n 'maizzle.config.ts',\n 'maizzle.config.js',\n]\n\n/**\n * Resolve the Maizzle config.\n *\n * Always loads from the config file on disk (maizzle.config.{ts,js}),\n * then merges the programmatic config on top, then fills in defaults.\n */\nexport async function resolveConfig(\n config?: Partial<MaizzleConfig> | string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n // If a string path was provided, load that specific file\n const fileConfig = await loadConfig(\n typeof config === 'string' ? config : undefined,\n cwd,\n )\n\n // Programmatic config (object) overrides file config, which overrides defaults\n const programmaticConfig = typeof config === 'object' && config !== null ? config : {}\n\n const merged = merge(programmaticConfig, fileConfig, defaults) as MaizzleConfig\n\n // Check if root was explicitly provided before resolving\n const hasExplicitRoot = !!(programmaticConfig.root ?? fileConfig.root)\n\n // Resolve root to an absolute path (defaults to cwd)\n const root = resolve(cwd, merged.root ?? '.')\n merged.root = root\n\n // Resolve content patterns relative to root\n if (merged.content) {\n merged.content = merged.content.map(p => {\n // Skip already-absolute or negated patterns\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n // Resolve static source patterns relative to root\n if (merged.static?.source) {\n merged.static.source = merged.static.source.map(p => {\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n /**\n * Resolve components.source paths relative to cwd (not root), since extra\n * component dirs often live outside the root directory. String\n * entries → resolve in-place. Object entries → resolve\n * `path`, preserve `prefix`/`pathPrefix`.\n */\n if (merged.components?.source) {\n const dirs = Array.isArray(merged.components.source)\n ? merged.components.source\n : [merged.components.source]\n\n merged.components.source = dirs.map(entry => {\n if (typeof entry === 'string') {\n return entry.startsWith('/') ? entry : resolve(cwd, entry)\n }\n return {\n ...entry,\n path: entry.path.startsWith('/') ? entry.path : resolve(cwd, entry.path),\n }\n })\n }\n\n /**\n * Default css.base to root when root is explicitly set, so Tailwind resolves\n * @source from the right directory. When root is not set, leave\n * css.base undefined so Tailwind uses its own default (the\n * template file's directory).\n */\n if (hasExplicitRoot && !merged.css?.base) {\n if (!merged.css) merged.css = {}\n merged.css.base = root\n }\n\n return merged\n}\n\nasync function loadConfig(\n configPath?: string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n const jiti = createJiti(fileURLToPath(import.meta.url), { moduleCache: false })\n\n // If an explicit path was provided, use it directly\n if (configPath) {\n const absolutePath = resolve(cwd, configPath)\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`)\n }\n\n const mod = await jiti.import(absolutePath) as any\n return mod.default ?? mod\n }\n\n // Otherwise scan cwd for known config file names\n for (const filename of CONFIG_FILES) {\n const filepath = resolve(cwd, filename)\n\n if (existsSync(filepath)) {\n const mod = await jiti.import(filepath) as any\n return mod.default ?? mod\n }\n }\n\n // No config file found, return empty (defaults will be applied by resolveConfig)\n return {}\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,IAAI,GAAG;EAC3B,IAAI,OAAO;EACX,OAAO;CACT;AACF,CAAC;AAOD,MAAM,eAAe,CACnB,qBACA,mBACF;;;;;;;AAQA,eAAsB,cACpB,QACA,MAAc,QAAQ,IAAI,GACF;CAExB,MAAM,aAAa,MAAM,WACvB,OAAO,WAAW,WAAW,SAAS,KAAA,GACtC,GACF;CAGA,MAAM,qBAAqB,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,CAAC;CAErF,MAAM,SAAS,MAAM,oBAAoB,YAAY,QAAQ;CAG7D,MAAM,kBAAkB,CAAC,EAAE,mBAAmB,QAAQ,WAAW;CAGjE,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG;CAC5C,OAAO,OAAO;CAGd,IAAI,OAAO,SACT,OAAO,UAAU,OAAO,QAAQ,KAAI,MAAK;EAEvC,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,GAAG,GAAG,OAAO;EACnD,OAAO,QAAQ,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,GAAG;CAC5C,CAAC;CAIH,IAAI,OAAO,QAAQ,QACjB,OAAO,OAAO,SAAS,OAAO,OAAO,OAAO,KAAI,MAAK;EACnD,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,GAAG,GAAG,OAAO;EACnD,OAAO,QAAQ,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,GAAG;CAC5C,CAAC;;;;;;;CASH,IAAI,OAAO,YAAY,QAAQ;EAC7B,MAAM,OAAO,MAAM,QAAQ,OAAO,WAAW,MAAM,IAC/C,OAAO,WAAW,SAClB,CAAC,OAAO,WAAW,MAAM;EAE7B,OAAO,WAAW,SAAS,KAAK,KAAI,UAAS;GAC3C,IAAI,OAAO,UAAU,UACnB,OAAO,MAAM,WAAW,GAAG,IAAI,QAAQ,QAAQ,KAAK,KAAK;GAE3D,OAAO;IACL,GAAG;IACH,MAAM,MAAM,KAAK,WAAW,GAAG,IAAI,MAAM,OAAO,QAAQ,KAAK,MAAM,IAAI;GACzE;EACF,CAAC;CACH;;;;;;;CAQA,IAAI,mBAAmB,CAAC,OAAO,KAAK,MAAM;EACxC,IAAI,CAAC,OAAO,KAAK,OAAO,MAAM,CAAC;EAC/B,OAAO,IAAI,OAAO;CACpB;CAEA,OAAO;AACT;AAEA,eAAe,WACb,YACA,MAAc,QAAQ,IAAI,GACF;CACxB,MAAM,OAAO,WAAW,cAAc,OAAO,KAAK,GAAG,GAAG,EAAE,aAAa,MAAM,CAAC;CAG9E,IAAI,YAAY;EACd,MAAM,eAAe,QAAQ,KAAK,UAAU;EAE5C,IAAI,CAAC,WAAW,YAAY,GAC1B,MAAM,IAAI,MAAM,0BAA0B,cAAc;EAG1D,MAAM,MAAM,MAAM,KAAK,OAAO,YAAY;EAC1C,OAAO,IAAI,WAAW;CACxB;CAGA,KAAK,MAAM,YAAY,cAAc;EACnC,MAAM,WAAW,QAAQ,KAAK,QAAQ;EAEtC,IAAI,WAAW,QAAQ,GAAG;GACxB,MAAM,MAAM,MAAM,KAAK,OAAO,QAAQ;GACtC,OAAO,IAAI,WAAW;EACxB;CACF;CAGA,OAAO,CAAC;AACV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/events/index.ts"],"mappings":";;;;KAGY,SAAA;;;AAAZ;;;UAOiB,YAAA;EACf,MAAA;EACA,IAAA,EAAM,UAAU;AAAA;AAAA,UAGD,QAAA;EACf,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;EAC5D,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,sBAAmC,OAAA;EAC7F,WAAA,GAAc,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC1G,cAAA,GAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC7G,UAAA,GAAa,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;AAAA;;;;;;;;cAUhE,YAAA;EAAA,QACH,QAAA;EAdyB;;;;;EAAA,QAoBzB,kBAAA;EAnBgB;;;EAwBxB,cAAA,CAAe,MAAA,EAAQ,aAAA;EAxBgD;;;EAuCvE,EAAA,WAAa,SAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/events/index.ts"],"mappings":";;;;KAGY,SAAA;;;AAAZ;;;UAOiB,YAAA;EACf,MAAA;EACA,IAAA,EAAM,UAAU;AAAA;AAAA,UAGD,QAAA;EACf,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;EAC5D,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,sBAAmC,OAAA;EAC7F,WAAA,GAAc,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC1G,cAAA,GAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC7G,UAAA,GAAa,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;AAAA;;;;;;;;cAUhE,YAAA;EAAA,QACH,QAAA;EAdyB;;;;;EAAA,QAoBzB,kBAAA;EAnBgB;;;EAwBxB,cAAA,CAAe,MAAA,EAAQ,aAAA;EAxBgD;;;EAuCvE,EAAA,WAAa,SAAA,EAAW,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,QAAA,CAAS,CAAA;EAtCxB;;;EAiDrB,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EAjDqD;;;;EA6DvG,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,IAAiB,OAAA;EA5DD;AAUpF;;EAmEQ,eAAA,CAAgB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EAxC7C;;;EA2D7C,kBAAA,CAAmB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EAnBH;;;EAsC1F,cAAA,CAAe,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EAgBrC;;;;;;;;EAAlC,gBAAA,CAAiB,MAAA,GAAQ,SAAA;EA9FZ;;;EA4Gb,KAAA;AAAA"}
|
package/dist/events/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport type EventName = 'beforeCreate' | 'beforeRender' | 'afterRender' | 'afterTransform' | 'afterBuild'\n\n/**\n * Info about the template currently being processed, passed to per-template\n * event handlers. `source` is the SFC file contents; `path` is the result of\n * `path.parse(absolutePath)` — `{ root, dir, base, ext, name }`.\n */\nexport interface TemplateInfo {\n source: string\n path: ParsedPath\n}\n\nexport interface EventMap {\n beforeCreate: (params: { config: MaizzleConfig }) => void | Promise<void>\n beforeRender: (params: { config: MaizzleConfig; template: TemplateInfo }) => string | void | Promise<string | void>\n afterRender: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterTransform: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterBuild: (params: { files: string[]; config: MaizzleConfig }) => void | Promise<void>\n}\n\n/**\n * Central event manager that collects handlers from config and useEvent() calls.\n *\n * Handlers are run in order: config handler first, then SFC handlers in registration order.\n * For events that return a value (beforeRender, afterRender, afterTransform),\n * the returned value replaces the corresponding input for the next handler.\n */\nexport class EventManager {\n private handlers = new Map<EventName, EventMap[EventName][]>()\n /**\n * Snapshot of config-handler counts per event, captured at registerConfig().\n * clearSfcHandlers() truncates each list back to this count, dropping\n * any SFC-registered handlers that were appended after.\n */\n private configHandlerCount = new Map<EventName, number>()\n\n /**\n * Register handlers from the Maizzle config.\n */\n registerConfig(config: MaizzleConfig) {\n const eventNames: EventName[] = ['beforeCreate', 'beforeRender', 'afterRender', 'afterTransform', 'afterBuild']\n\n for (const name of eventNames) {\n const handler = config[name]\n if (typeof handler === 'function') {\n this.on(name, handler as EventMap[typeof name])\n }\n this.configHandlerCount.set(name, this.handlers.get(name)?.length ?? 0)\n }\n }\n\n /**\n * Register a handler for an event (used by useEvent composable).\n */\n on<K extends EventName>(name: K, handler: EventMap[K]) {\n if (!this.handlers.has(name)) {\n this.handlers.set(name, [])\n }\n\n this.handlers.get(name)!.push(handler)\n }\n\n /**\n * Fire beforeCreate — runs all handlers, config is mutated in place.\n */\n async fireBeforeCreate(params: { config: MaizzleConfig }) {\n const handlers = this.handlers.get('beforeCreate') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['beforeCreate'])(params)\n }\n }\n\n /**\n * Fire beforeRender — if a handler returns a string, it replaces\n * `template.source` for subsequent handlers and the renderer.\n */\n async fireBeforeRender(params: { config: MaizzleConfig; template: TemplateInfo }): Promise<string> {\n const handlers = this.handlers.get('beforeRender') ?? []\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['beforeRender'])(params)\n\n if (typeof result === 'string') {\n params.template.source = result\n }\n }\n\n return params.template.source\n }\n\n /**\n * Fire afterRender — if a handler returns a string, it replaces `html`.\n */\n async fireAfterRender(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterRender') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterRender'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterTransform — if a handler returns a string, it replaces `html`.\n */\n async fireAfterTransform(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterTransform') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterTransform'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterBuild — runs all handlers with the file list.\n */\n async fireAfterBuild(params: { files: string[]; config: MaizzleConfig }) {\n const handlers = this.handlers.get('afterBuild') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['afterBuild'])(params)\n }\n }\n\n /**\n * Drop SFC-registered handlers, keep config-registered ones.\n *\n * Per default, only clears events whose scope is per-template\n * (`beforeRender`, `afterRender`, `afterTransform`). Build-scoped events\n * (`afterBuild`) accumulate across all templates and fire once at end of\n * build. Pass an explicit list to override.\n */\n clearSfcHandlers(events: EventName[] = ['beforeRender', 'afterRender', 'afterTransform']) {\n for (const name of events) {\n const handlers = this.handlers.get(name)\n if (!handlers) continue\n const keep = this.configHandlerCount.get(name) ?? 0\n if (handlers.length > keep) {\n this.handlers.set(name, handlers.slice(0, keep))\n }\n }\n }\n\n /**\n * Clear all handlers entirely.\n */\n clear() {\n this.handlers.clear()\n }\n}\n"],"mappings":";;;;;;;;AA8BA,IAAa,eAAb,MAA0B;CACxB,2BAAmB,IAAI,IAAsC;;;;;;CAM7D,qCAA6B,IAAI,IAAuB;;;;CAKxD,eAAe,QAAuB;EAGpC,KAAK,MAAM,QAAQ;GAFc;GAAgB;GAAgB;GAAe;GAAkB;EAEtE,GAAG;GAC7B,MAAM,UAAU,OAAO;GACvB,IAAI,OAAO,YAAY,YACrB,KAAK,GAAG,MAAM,OAAgC;GAEhD,KAAK,mBAAmB,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport type EventName = 'beforeCreate' | 'beforeRender' | 'afterRender' | 'afterTransform' | 'afterBuild'\n\n/**\n * Info about the template currently being processed, passed to per-template\n * event handlers. `source` is the SFC file contents; `path` is the result of\n * `path.parse(absolutePath)` — `{ root, dir, base, ext, name }`.\n */\nexport interface TemplateInfo {\n source: string\n path: ParsedPath\n}\n\nexport interface EventMap {\n beforeCreate: (params: { config: MaizzleConfig }) => void | Promise<void>\n beforeRender: (params: { config: MaizzleConfig; template: TemplateInfo }) => string | void | Promise<string | void>\n afterRender: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterTransform: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterBuild: (params: { files: string[]; config: MaizzleConfig }) => void | Promise<void>\n}\n\n/**\n * Central event manager that collects handlers from config and useEvent() calls.\n *\n * Handlers are run in order: config handler first, then SFC handlers in registration order.\n * For events that return a value (beforeRender, afterRender, afterTransform),\n * the returned value replaces the corresponding input for the next handler.\n */\nexport class EventManager {\n private handlers = new Map<EventName, EventMap[EventName][]>()\n /**\n * Snapshot of config-handler counts per event, captured at registerConfig().\n * clearSfcHandlers() truncates each list back to this count, dropping\n * any SFC-registered handlers that were appended after.\n */\n private configHandlerCount = new Map<EventName, number>()\n\n /**\n * Register handlers from the Maizzle config.\n */\n registerConfig(config: MaizzleConfig) {\n const eventNames: EventName[] = ['beforeCreate', 'beforeRender', 'afterRender', 'afterTransform', 'afterBuild']\n\n for (const name of eventNames) {\n const handler = config[name]\n if (typeof handler === 'function') {\n this.on(name, handler as EventMap[typeof name])\n }\n this.configHandlerCount.set(name, this.handlers.get(name)?.length ?? 0)\n }\n }\n\n /**\n * Register a handler for an event (used by useEvent composable).\n */\n on<K extends EventName>(name: K, handler: EventMap[K]) {\n if (!this.handlers.has(name)) {\n this.handlers.set(name, [])\n }\n\n this.handlers.get(name)!.push(handler)\n }\n\n /**\n * Fire beforeCreate — runs all handlers, config is mutated in place.\n */\n async fireBeforeCreate(params: { config: MaizzleConfig }) {\n const handlers = this.handlers.get('beforeCreate') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['beforeCreate'])(params)\n }\n }\n\n /**\n * Fire beforeRender — if a handler returns a string, it replaces\n * `template.source` for subsequent handlers and the renderer.\n */\n async fireBeforeRender(params: { config: MaizzleConfig; template: TemplateInfo }): Promise<string> {\n const handlers = this.handlers.get('beforeRender') ?? []\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['beforeRender'])(params)\n\n if (typeof result === 'string') {\n params.template.source = result\n }\n }\n\n return params.template.source\n }\n\n /**\n * Fire afterRender — if a handler returns a string, it replaces `html`.\n */\n async fireAfterRender(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterRender') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterRender'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterTransform — if a handler returns a string, it replaces `html`.\n */\n async fireAfterTransform(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterTransform') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterTransform'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterBuild — runs all handlers with the file list.\n */\n async fireAfterBuild(params: { files: string[]; config: MaizzleConfig }) {\n const handlers = this.handlers.get('afterBuild') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['afterBuild'])(params)\n }\n }\n\n /**\n * Drop SFC-registered handlers, keep config-registered ones.\n *\n * Per default, only clears events whose scope is per-template\n * (`beforeRender`, `afterRender`, `afterTransform`). Build-scoped events\n * (`afterBuild`) accumulate across all templates and fire once at end of\n * build. Pass an explicit list to override.\n */\n clearSfcHandlers(events: EventName[] = ['beforeRender', 'afterRender', 'afterTransform']) {\n for (const name of events) {\n const handlers = this.handlers.get(name)\n if (!handlers) continue\n const keep = this.configHandlerCount.get(name) ?? 0\n if (handlers.length > keep) {\n this.handlers.set(name, handlers.slice(0, keep))\n }\n }\n }\n\n /**\n * Clear all handlers entirely.\n */\n clear() {\n this.handlers.clear()\n }\n}\n"],"mappings":";;;;;;;;AA8BA,IAAa,eAAb,MAA0B;CACxB,2BAAmB,IAAI,IAAsC;;;;;;CAM7D,qCAA6B,IAAI,IAAuB;;;;CAKxD,eAAe,QAAuB;EAGpC,KAAK,MAAM,QAAQ;GAFc;GAAgB;GAAgB;GAAe;GAAkB;EAEtE,GAAG;GAC7B,MAAM,UAAU,OAAO;GACvB,IAAI,OAAO,YAAY,YACrB,KAAK,GAAG,MAAM,OAAgC;GAEhD,KAAK,mBAAmB,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,EAAE,UAAU,CAAC;EACxE;CACF;;;;CAKA,GAAwB,MAAS,SAAsB;EACrD,IAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GACzB,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC;EAG5B,KAAK,SAAS,IAAI,IAAI,CAAC,CAAE,KAAK,OAAO;CACvC;;;;CAKA,MAAM,iBAAiB,QAAmC;EACxD,MAAM,WAAW,KAAK,SAAS,IAAI,cAAc,KAAK,CAAC;EAEvD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAqC,MAAM;CAEtD;;;;;CAMA,MAAM,iBAAiB,QAA4E;EACjG,MAAM,WAAW,KAAK,SAAS,IAAI,cAAc,KAAK,CAAC;EAEvD,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAqC,MAAM;GAEjE,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,SAAS;EAE7B;EAEA,OAAO,OAAO,SAAS;CACzB;;;;CAKA,MAAM,gBAAgB,QAA0F;EAC9G,MAAM,WAAW,KAAK,SAAS,IAAI,aAAa,KAAK,CAAC;EAEtD,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAoC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;GAAK,CAAC;GAEpH,IAAI,OAAO,WAAW,UACpB,OAAO;EAEX;EAEA,OAAO;CACT;;;;CAKA,MAAM,mBAAmB,QAA0F;EACjH,MAAM,WAAW,KAAK,SAAS,IAAI,gBAAgB,KAAK,CAAC;EAEzD,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAuC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;GAAK,CAAC;GAEvH,IAAI,OAAO,WAAW,UACpB,OAAO;EAEX;EAEA,OAAO;CACT;;;;CAKA,MAAM,eAAe,QAAoD;EACvE,MAAM,WAAW,KAAK,SAAS,IAAI,YAAY,KAAK,CAAC;EAErD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAmC,MAAM;CAEpD;;;;;;;;;CAUA,iBAAiB,SAAsB;EAAC;EAAgB;EAAe;CAAgB,GAAG;EACxF,KAAK,MAAM,QAAQ,QAAQ;GACzB,MAAM,WAAW,KAAK,SAAS,IAAI,IAAI;GACvC,IAAI,CAAC,UAAU;GACf,MAAM,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK;GAClD,IAAI,SAAS,SAAS,MACpB,KAAK,SAAS,IAAI,MAAM,SAAS,MAAM,GAAG,IAAI,CAAC;EAEnD;CACF;;;;CAKA,QAAQ;EACN,KAAK,SAAS,MAAM;CACtB;AACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { useConfig } from "./composables/useConfig.js";
|
|
2
2
|
import { defineConfig } from "./composables/defineConfig.js";
|
|
3
3
|
import { resolveConfig } from "./config/index.js";
|
|
4
|
+
import { normalizeComponentSources } from "./utils/componentSources.js";
|
|
5
|
+
import { createRenderer } from "./render/createRenderer.js";
|
|
4
6
|
import { inlineLink } from "./transformers/inlineLink.js";
|
|
5
7
|
import { safeSelectors } from "./transformers/safeSelectors.js";
|
|
6
8
|
import { attributeToStyle } from "./transformers/attributeToStyle.js";
|
|
@@ -17,8 +19,6 @@ import { purgeCss } from "./transformers/purgeCss.js";
|
|
|
17
19
|
import { replaceStrings } from "./transformers/replaceStrings.js";
|
|
18
20
|
import { format } from "./transformers/format.js";
|
|
19
21
|
import { minify } from "./transformers/minify.js";
|
|
20
|
-
import { normalizeComponentSources } from "./utils/componentSources.js";
|
|
21
|
-
import { createRenderer } from "./render/createRenderer.js";
|
|
22
22
|
import { createPlaintext } from "./plaintext.js";
|
|
23
23
|
import { useCurrentTemplate } from "./composables/useCurrentTemplate.js";
|
|
24
24
|
import { build } from "./build.js";
|
package/dist/plaintext.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plaintext.js","names":[],"sources":["../src/plaintext.ts"],"sourcesContent":["import { stripHtml } from 'string-strip-html'\nimport defu from 'defu'\n\nconst defaults = {\n dumpLinkHrefsNearby: {\n enabled: true,\n putOnNewLine: true,\n },\n}\n\nexport function createPlaintext(html: string, options?: Record<string, unknown>): string {\n return stripHtml(html, defu(options, defaults)).result\n}\n"],"mappings":";;;AAGA,MAAM,WAAW,EACf,qBAAqB;CACnB,SAAS;CACT,cAAc;AAChB,EACF;AAEA,SAAgB,gBAAgB,MAAc,SAA2C;CACvF,OAAO,UAAU,MAAM,KAAK,SAAS,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"plaintext.js","names":[],"sources":["../src/plaintext.ts"],"sourcesContent":["import { stripHtml } from 'string-strip-html'\nimport defu from 'defu'\n\nconst defaults = {\n dumpLinkHrefsNearby: {\n enabled: true,\n putOnNewLine: true,\n },\n}\n\nexport function createPlaintext(html: string, options?: Record<string, unknown>): string {\n return stripHtml(html, defu(options, defaults)).result\n}\n"],"mappings":";;;AAGA,MAAM,WAAW,EACf,qBAAqB;CACnB,SAAS;CACT,cAAc;AAChB,EACF;AAEA,SAAgB,gBAAgB,MAAc,SAA2C;CACvF,OAAO,UAAU,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,CAAC;AAClD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeMediaQueries.js","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"sourcesContent":["import sortMediaQueries from 'postcss-sort-media-queries'\nimport type postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\n/**\n * Sorts and merges CSS media queries using postcss-sort-media-queries.\n *\n * Enabled by default. Opt out with css: { media: false }.\n *\n * Config examples:\n * css: { media: true } // merge, mobile-first sort (default)\n * css: { media: { sort: 'desktop-first' } } // merge, desktop-first sort\n * css: { media: false } // disabled\n */\nexport function mergeMediaQueries(config: MaizzleConfig): postcss.Plugin | null {\n const media = config.css?.media\n\n if (media === false) return null\n\n const options = typeof media === 'object' ? media : {}\n const sort = options.sort ?? 'mobile-first'\n\n return sortMediaQueries({ sort }) as postcss.Plugin\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,kBAAkB,QAA8C;CAC9E,MAAM,QAAQ,OAAO,KAAK;CAE1B,IAAI,UAAU,OAAO,OAAO;CAK5B,OAAO,iBAAiB,EAAE,OAHV,OAAO,UAAU,WAAW,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"mergeMediaQueries.js","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"sourcesContent":["import sortMediaQueries from 'postcss-sort-media-queries'\nimport type postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\n/**\n * Sorts and merges CSS media queries using postcss-sort-media-queries.\n *\n * Enabled by default. Opt out with css: { media: false }.\n *\n * Config examples:\n * css: { media: true } // merge, mobile-first sort (default)\n * css: { media: { sort: 'desktop-first' } } // merge, desktop-first sort\n * css: { media: false } // disabled\n */\nexport function mergeMediaQueries(config: MaizzleConfig): postcss.Plugin | null {\n const media = config.css?.media\n\n if (media === false) return null\n\n const options = typeof media === 'object' ? media : {}\n const sort = options.sort ?? 'mobile-first'\n\n return sortMediaQueries({ sort }) as postcss.Plugin\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,kBAAkB,QAA8C;CAC9E,MAAM,QAAQ,OAAO,KAAK;CAE1B,IAAI,UAAU,OAAO,OAAO;CAK5B,OAAO,iBAAiB,EAAE,OAHV,OAAO,UAAU,WAAW,QAAQ,CAAC,EAAA,CAChC,QAAQ,eAEE,CAAC;AAClC"}
|