@maizzle/framework 6.0.0-rc.13 → 6.0.0-rc.15
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/components/Button.vue +2 -2
- package/dist/components/CodeBlock.vue +2 -1
- package/dist/components/Column.vue +28 -22
- package/dist/components/Container.vue +47 -9
- package/dist/components/Font.vue +96 -0
- package/dist/components/Head.vue +1 -1
- package/dist/components/Layout.vue +24 -4
- package/dist/components/Outlook.vue +38 -11
- package/dist/components/Overlap.vue +75 -18
- package/dist/components/Row.vue +90 -19
- package/dist/components/Section.vue +35 -8
- package/dist/components/utils.d.mts +14 -1
- package/dist/components/utils.d.mts.map +1 -1
- package/dist/components/utils.mjs +32 -1
- package/dist/components/utils.mjs.map +1 -1
- package/dist/components/utils.ts +39 -0
- package/dist/composables/renderContext.d.mts +8 -1
- package/dist/composables/renderContext.d.mts.map +1 -1
- package/dist/composables/renderContext.mjs.map +1 -1
- package/dist/composables/useFont.d.mts +50 -0
- package/dist/composables/useFont.d.mts.map +1 -0
- package/dist/composables/useFont.mjs +93 -0
- package/dist/composables/useFont.mjs.map +1 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -1
- package/dist/plugins/postcss/quoteFontFamilies.d.mts +13 -0
- package/dist/plugins/postcss/quoteFontFamilies.d.mts.map +1 -0
- package/dist/plugins/postcss/quoteFontFamilies.mjs +84 -0
- package/dist/plugins/postcss/quoteFontFamilies.mjs.map +1 -0
- package/dist/prepare.d.mts +17 -0
- package/dist/prepare.d.mts.map +1 -0
- package/dist/prepare.mjs +44 -0
- package/dist/prepare.mjs.map +1 -0
- package/dist/render/createRenderer.d.mts.map +1 -1
- package/dist/render/createRenderer.mjs +10 -2
- package/dist/render/createRenderer.mjs.map +1 -1
- package/dist/render/injectFonts.d.mts +15 -0
- package/dist/render/injectFonts.d.mts.map +1 -0
- package/dist/render/injectFonts.mjs +46 -0
- package/dist/render/injectFonts.mjs.map +1 -0
- package/dist/render/plugins/rowSourceLocation.d.mts +18 -0
- package/dist/render/plugins/rowSourceLocation.d.mts.map +1 -0
- package/dist/render/plugins/rowSourceLocation.mjs +45 -0
- package/dist/render/plugins/rowSourceLocation.mjs.map +1 -0
- package/dist/serve.d.mts.map +1 -1
- package/dist/serve.mjs +6 -2
- package/dist/serve.mjs.map +1 -1
- package/dist/server/ui/App.vue +25 -11
- package/dist/server/ui/lib/emulated-dark-mode.ts +131 -0
- package/dist/server/ui/pages/Preview.vue +24 -5
- package/dist/transformers/columnWidth.d.mts +31 -0
- package/dist/transformers/columnWidth.d.mts.map +1 -0
- package/dist/transformers/columnWidth.mjs +166 -0
- package/dist/transformers/columnWidth.mjs.map +1 -0
- package/dist/transformers/filters/index.mjs +1 -1
- package/dist/transformers/filters/index.mjs.map +1 -1
- package/dist/transformers/index.d.mts.map +1 -1
- package/dist/transformers/index.mjs +5 -1
- package/dist/transformers/index.mjs.map +1 -1
- package/dist/transformers/msoWidthFromClass.d.mts +19 -0
- package/dist/transformers/msoWidthFromClass.d.mts.map +1 -0
- package/dist/transformers/msoWidthFromClass.mjs +61 -0
- package/dist/transformers/msoWidthFromClass.mjs.map +1 -0
- package/dist/transformers/tailwindcss.d.mts.map +1 -1
- package/dist/transformers/tailwindcss.mjs +4 -12
- package/dist/transformers/tailwindcss.mjs.map +1 -1
- package/dist/utils/decodeStyleEntities.d.mts +15 -0
- package/dist/utils/decodeStyleEntities.d.mts.map +1 -0
- package/dist/utils/decodeStyleEntities.mjs +18 -0
- package/dist/utils/decodeStyleEntities.mjs.map +1 -0
- package/node_modules/maizzle/dist/commands/new.mjs +3 -3
- package/node_modules/maizzle/dist/index.d.mts +1 -0
- package/node_modules/maizzle/dist/index.mjs +3 -0
- package/node_modules/maizzle/package.json +3 -2
- package/node_modules/nypm/dist/cli.mjs +28 -5
- package/node_modules/nypm/dist/index.d.mts +0 -8
- package/node_modules/nypm/dist/index.mjs +27 -4
- package/node_modules/nypm/package.json +12 -12
- package/package.json +2 -1
package/dist/components/Row.vue
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
const warnedLocations = new Set<string>()
|
|
3
|
+
</script>
|
|
4
|
+
|
|
1
5
|
<script setup lang="ts">
|
|
2
|
-
import { Comment, computed, createStaticVNode,
|
|
3
|
-
import type {
|
|
6
|
+
import { Comment, Text, computed, createStaticVNode, provide, useAttrs, useSlots, Fragment } from 'vue'
|
|
7
|
+
import type { VNode } from 'vue'
|
|
8
|
+
import Column from './Column.vue'
|
|
9
|
+
import { hasWidthInStyle, hasWidthUtility, normalizeToPixels } from './utils.ts'
|
|
4
10
|
|
|
5
11
|
defineOptions({ inheritAttrs: false })
|
|
6
12
|
|
|
@@ -8,10 +14,12 @@ const attrs = useAttrs()
|
|
|
8
14
|
|
|
9
15
|
const props = defineProps({
|
|
10
16
|
/**
|
|
11
|
-
*
|
|
17
|
+
* Explicit row width.
|
|
12
18
|
*
|
|
13
|
-
* Used
|
|
14
|
-
*
|
|
19
|
+
* Used as the width source for column min-width calculation.
|
|
20
|
+
* When not set, the nearest sized ancestor (`Container`, `Section`,
|
|
21
|
+
* outer `Column`, or this row's own width class/inline style) is
|
|
22
|
+
* used instead.
|
|
15
23
|
*/
|
|
16
24
|
width: {
|
|
17
25
|
type: [String, Number],
|
|
@@ -46,6 +54,41 @@ function countChildren(vnodes: VNode[]): number {
|
|
|
46
54
|
return count
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
function hasColumnChild(vnodes: VNode[]): boolean {
|
|
58
|
+
for (const vnode of vnodes) {
|
|
59
|
+
if (vnode.type === Fragment && Array.isArray(vnode.children)) {
|
|
60
|
+
if (hasColumnChild(vnode.children as VNode[])) return true
|
|
61
|
+
} else if (vnode.type === Column) {
|
|
62
|
+
return true
|
|
63
|
+
} else if (
|
|
64
|
+
typeof vnode.type === 'object'
|
|
65
|
+
&& vnode.type !== null
|
|
66
|
+
&& '__name' in vnode.type
|
|
67
|
+
&& (vnode.type as { __name?: string }).__name === 'Column'
|
|
68
|
+
) {
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function hasMeaningfulContent(vnodes: VNode[]): boolean {
|
|
76
|
+
for (const vnode of vnodes) {
|
|
77
|
+
if (vnode.type === Comment) continue
|
|
78
|
+
if (vnode.type === Fragment && Array.isArray(vnode.children)) {
|
|
79
|
+
if (hasMeaningfulContent(vnode.children as VNode[])) return true
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
if (vnode.type === Text) {
|
|
83
|
+
if (typeof vnode.children === 'string' && vnode.children.trim()) return true
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
if (typeof vnode.type === 'symbol') continue
|
|
87
|
+
return true
|
|
88
|
+
}
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
|
|
49
92
|
const columnCount = computed(() => {
|
|
50
93
|
if (props.cols) return props.cols
|
|
51
94
|
|
|
@@ -53,26 +96,40 @@ const columnCount = computed(() => {
|
|
|
53
96
|
return countChildren(children) || 1
|
|
54
97
|
})
|
|
55
98
|
|
|
56
|
-
|
|
99
|
+
provide('columnCount', columnCount)
|
|
57
100
|
|
|
58
|
-
const
|
|
101
|
+
const userStyle = computed(() => {
|
|
102
|
+
const s = attrs.style
|
|
103
|
+
if (!s) return ''
|
|
104
|
+
return typeof s === 'object'
|
|
105
|
+
? Object.entries(s).map(([k, v]) => `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${v}`).join('; ')
|
|
106
|
+
: String(s)
|
|
107
|
+
})
|
|
59
108
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
109
|
+
const userHasWidth = computed(() => {
|
|
110
|
+
const cls = (attrs.class as string) ?? ''
|
|
111
|
+
return hasWidthUtility(cls) || hasWidthInStyle(userStyle.value)
|
|
112
|
+
})
|
|
64
113
|
|
|
65
|
-
|
|
66
|
-
|
|
114
|
+
const colWidthSource = computed(() => {
|
|
115
|
+
if (props.width != null) return normalizeToPixels(props.width)
|
|
116
|
+
if (userHasWidth.value) return ''
|
|
117
|
+
return null
|
|
118
|
+
})
|
|
67
119
|
|
|
68
|
-
|
|
69
|
-
}
|
|
120
|
+
const restAttrs = computed(() => {
|
|
121
|
+
const { style: _, 'data-maizzle-loc': __, ...rest } = attrs
|
|
122
|
+
return rest
|
|
123
|
+
})
|
|
70
124
|
|
|
71
|
-
|
|
72
|
-
|
|
125
|
+
const divStyle = computed(() => {
|
|
126
|
+
const parts: string[] = ['font-size: 0;']
|
|
127
|
+
if (userStyle.value) parts.push(userStyle.value)
|
|
128
|
+
return parts.join(' ')
|
|
129
|
+
})
|
|
73
130
|
|
|
74
131
|
const MsoBefore = () => createStaticVNode(
|
|
75
|
-
'<!--[if mso]><table role="none" cellpadding="0" cellspacing="0"
|
|
132
|
+
'<!--[if mso]><table role="none" cellpadding="0" cellspacing="0" style="width: 100%"><tr><![endif]-->',
|
|
76
133
|
1
|
|
77
134
|
)
|
|
78
135
|
|
|
@@ -80,11 +137,25 @@ const MsoAfter = () => createStaticVNode(
|
|
|
80
137
|
'<!--[if mso]></tr></table><![endif]-->',
|
|
81
138
|
1
|
|
82
139
|
)
|
|
140
|
+
|
|
141
|
+
const initialChildren = slots.default?.() ?? []
|
|
142
|
+
if (hasMeaningfulContent(initialChildren) && !hasColumnChild(initialChildren)) {
|
|
143
|
+
const loc = (attrs['data-maizzle-loc'] as string | undefined) ?? '<unknown location>'
|
|
144
|
+
if (!warnedLocations.has(loc)) {
|
|
145
|
+
warnedLocations.add(loc)
|
|
146
|
+
const display = loc.split('/').pop() ?? loc
|
|
147
|
+
console.warn(`[maizzle] <Row> in ${display} has no <Column> inside it. Layout will break in Outlook.`)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
83
150
|
</script>
|
|
84
151
|
|
|
85
152
|
<template>
|
|
86
153
|
<MsoBefore />
|
|
87
|
-
<div
|
|
154
|
+
<div
|
|
155
|
+
v-bind="restAttrs"
|
|
156
|
+
:style="divStyle"
|
|
157
|
+
:data-maizzle-cw="colWidthSource"
|
|
158
|
+
>
|
|
88
159
|
<slot />
|
|
89
160
|
</div>
|
|
90
161
|
<MsoAfter />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, createStaticVNode, useAttrs } from 'vue'
|
|
3
|
-
import { normalizeToPixels } from './utils.ts'
|
|
3
|
+
import { hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels } from './utils.ts'
|
|
4
4
|
|
|
5
5
|
defineOptions({ inheritAttrs: false })
|
|
6
6
|
|
|
@@ -12,11 +12,14 @@ const props = defineProps({
|
|
|
12
12
|
*
|
|
13
13
|
* Applied as `max-width` on the div and as `width` on the MSO table.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* When not set, the MSO table width is auto-derived from a width
|
|
16
|
+
* utility class (e.g. `max-w-md`) or inline style (`max-width`/
|
|
17
|
+
* `width`) on the component, after CSS inlining. Falls back to
|
|
18
|
+
* `100%` when no width source is provided.
|
|
16
19
|
*/
|
|
17
20
|
width: {
|
|
18
21
|
type: [String, Number],
|
|
19
|
-
default:
|
|
22
|
+
default: null
|
|
20
23
|
},
|
|
21
24
|
/**
|
|
22
25
|
* Inline CSS applied only to the MSO `<td>` element.
|
|
@@ -31,8 +34,6 @@ const props = defineProps({
|
|
|
31
34
|
}
|
|
32
35
|
})
|
|
33
36
|
|
|
34
|
-
const hasCustomWidth = computed(() => props.width !== '100%')
|
|
35
|
-
|
|
36
37
|
const userStyle = computed(() => {
|
|
37
38
|
const s = attrs.style
|
|
38
39
|
if (!s) return ''
|
|
@@ -41,9 +42,17 @@ const userStyle = computed(() => {
|
|
|
41
42
|
: String(s)
|
|
42
43
|
})
|
|
43
44
|
|
|
45
|
+
const userHasWidth = computed(() => {
|
|
46
|
+
const cls = (attrs.class as string) ?? ''
|
|
47
|
+
return hasWidthUtility(cls) || hasWidthInStyle(userStyle.value)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const useMarker = props.width == null && userHasWidth.value
|
|
51
|
+
const msoId = useMarker ? nextId('s') : null
|
|
52
|
+
|
|
44
53
|
const divStyle = computed(() => {
|
|
45
54
|
const parts: string[] = []
|
|
46
|
-
if (
|
|
55
|
+
if (props.width != null) parts.push(`max-width: ${normalizeToPixels(props.width)}`)
|
|
47
56
|
if (userStyle.value) parts.push(userStyle.value)
|
|
48
57
|
return parts.length ? parts.join('; ') : undefined
|
|
49
58
|
})
|
|
@@ -60,10 +69,22 @@ const tdStyles = computed(() => {
|
|
|
60
69
|
return parts.length ? parts.join('; ') : ''
|
|
61
70
|
})
|
|
62
71
|
|
|
72
|
+
const msoWidth = computed(() => {
|
|
73
|
+
if (props.width != null) return normalizeToPixels(props.width)
|
|
74
|
+
if (useMarker) return `__MAIZZLE_MSOW_${msoId}__`
|
|
75
|
+
return '100%'
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const colWidthSource = computed(() => {
|
|
79
|
+
if (props.width != null) return normalizeToPixels(props.width)
|
|
80
|
+
if (userHasWidth.value) return ''
|
|
81
|
+
return null
|
|
82
|
+
})
|
|
83
|
+
|
|
63
84
|
const MsoBefore = () => {
|
|
64
85
|
const tdStyle = tdStyles.value ? ` style="${tdStyles.value}"` : ''
|
|
65
86
|
return createStaticVNode(
|
|
66
|
-
`<!--[if mso]><table role="none" cellpadding="0" cellspacing="0" style="width: ${
|
|
87
|
+
`<!--[if mso]><table role="none" cellpadding="0" cellspacing="0" style="width: ${msoWidth.value}"><tr><td${tdStyle}><![endif]-->`,
|
|
67
88
|
1
|
|
68
89
|
)
|
|
69
90
|
}
|
|
@@ -76,7 +97,13 @@ const MsoAfter = () => createStaticVNode(
|
|
|
76
97
|
|
|
77
98
|
<template>
|
|
78
99
|
<MsoBefore />
|
|
79
|
-
<div
|
|
100
|
+
<div
|
|
101
|
+
v-bind="restAttrs"
|
|
102
|
+
:style="divStyle"
|
|
103
|
+
:data-maizzle-msow-id="msoId"
|
|
104
|
+
:data-maizzle-msow-fallback="useMarker ? '100%' : null"
|
|
105
|
+
:data-maizzle-cw="colWidthSource"
|
|
106
|
+
>
|
|
80
107
|
<slot />
|
|
81
108
|
</div>
|
|
82
109
|
<MsoAfter />
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
//#region src/components/utils.d.ts
|
|
2
2
|
declare function normalizeToPixels(value: string | number): string;
|
|
3
|
+
/**
|
|
4
|
+
* Module-scoped sequential ID generator. Used by components to mint
|
|
5
|
+
* unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.
|
|
6
|
+
*
|
|
7
|
+
* Must live here (not inside `<script setup>`) because Vue compiles
|
|
8
|
+
* `<script setup>` into the component's `setup()` function — any
|
|
9
|
+
* `let counter = 0` there resets per instance, causing id collisions.
|
|
10
|
+
*/
|
|
11
|
+
declare function nextId(prefix: string): string;
|
|
12
|
+
declare function hasWidthUtility(classStr: string): boolean;
|
|
13
|
+
declare function hasWidthInStyle(styleStr: string): boolean;
|
|
14
|
+
declare function hasHeightUtility(classStr: string): boolean;
|
|
15
|
+
declare function hasHeightInStyle(styleStr: string): boolean;
|
|
3
16
|
//#endregion
|
|
4
|
-
export { normalizeToPixels };
|
|
17
|
+
export { hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels };
|
|
5
18
|
//# sourceMappingURL=utils.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAA"}
|
|
1
|
+
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAA;AAAlC;;;;;AAiBA;;;AAjBA,iBAiBgB,MAAA,CAAO,MAAA;AAAA,iBAKP,eAAA,CAAgB,QAAA;AAAA,iBAQhB,eAAA,CAAgB,QAAA;AAAA,iBAIhB,gBAAA,CAAiB,QAAA;AAAA,iBAQjB,gBAAA,CAAiB,QAAA"}
|
|
@@ -3,7 +3,38 @@ function normalizeToPixels(value) {
|
|
|
3
3
|
if (typeof value === "number" || Number.isFinite(Number(value))) return `${value}px`;
|
|
4
4
|
return value;
|
|
5
5
|
}
|
|
6
|
+
const counters = {};
|
|
7
|
+
/**
|
|
8
|
+
* Module-scoped sequential ID generator. Used by components to mint
|
|
9
|
+
* unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.
|
|
10
|
+
*
|
|
11
|
+
* Must live here (not inside `<script setup>`) because Vue compiles
|
|
12
|
+
* `<script setup>` into the component's `setup()` function — any
|
|
13
|
+
* `let counter = 0` there resets per instance, causing id collisions.
|
|
14
|
+
*/
|
|
15
|
+
function nextId(prefix) {
|
|
16
|
+
counters[prefix] = (counters[prefix] ?? 0) + 1;
|
|
17
|
+
return `${prefix}${counters[prefix]}`;
|
|
18
|
+
}
|
|
19
|
+
function hasWidthUtility(classStr) {
|
|
20
|
+
return classStr.split(/\s+/).some((c) => {
|
|
21
|
+
const clean = (c.split(":").pop() ?? "").replace(/^!/, "");
|
|
22
|
+
return /^(w-|max-w-|min-w-)/.test(clean);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function hasWidthInStyle(styleStr) {
|
|
26
|
+
return /(?:^|;\s*)(?:max-width|width)\s*:/i.test(styleStr);
|
|
27
|
+
}
|
|
28
|
+
function hasHeightUtility(classStr) {
|
|
29
|
+
return classStr.split(/\s+/).some((c) => {
|
|
30
|
+
const clean = (c.split(":").pop() ?? "").replace(/^!/, "");
|
|
31
|
+
return /^(h-|max-h-|min-h-)/.test(clean);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function hasHeightInStyle(styleStr) {
|
|
35
|
+
return /(?:^|;\s*)(?:max-height|height)\s*:/i.test(styleStr);
|
|
36
|
+
}
|
|
6
37
|
|
|
7
38
|
//#endregion
|
|
8
|
-
export { normalizeToPixels };
|
|
39
|
+
export { hasHeightInStyle, hasHeightUtility, hasWidthInStyle, hasWidthUtility, nextId, normalizeToPixels };
|
|
9
40
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","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"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;AAChE,KAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,MAAM,CAAC,CAC7D,QAAO,GAAG,MAAM;AAElB,QAAO"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","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"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;AAChE,KAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,MAAM,CAAC,CAC7D,QAAO,GAAG,MAAM;AAElB,QAAO;;AAGT,MAAM,WAAmC,EAAE;;;;;;;;;AAU3C,SAAgB,OAAO,QAAwB;AAC7C,UAAS,WAAW,SAAS,WAAW,KAAK;AAC7C,QAAO,GAAG,SAAS,SAAS;;AAG9B,SAAgB,gBAAgB,UAA2B;AACzD,QAAO,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,IAAI,CAAC,KAAK,IAAI,IAChB,QAAQ,MAAM,GAAG;AACvC,SAAO,sBAAsB,KAAK,MAAM;GACxC;;AAGJ,SAAgB,gBAAgB,UAA2B;AACzD,QAAO,qCAAqC,KAAK,SAAS;;AAG5D,SAAgB,iBAAiB,UAA2B;AAC1D,QAAO,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,IAAI,CAAC,KAAK,IAAI,IAChB,QAAQ,MAAM,GAAG;AACvC,SAAO,sBAAsB,KAAK,MAAM;GACxC;;AAGJ,SAAgB,iBAAiB,UAA2B;AAC1D,QAAO,uCAAuC,KAAK,SAAS"}
|
package/dist/components/utils.ts
CHANGED
|
@@ -4,3 +4,42 @@ export function normalizeToPixels(value: string | number): string {
|
|
|
4
4
|
}
|
|
5
5
|
return value
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
const counters: Record<string, number> = {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Module-scoped sequential ID generator. Used by components to mint
|
|
12
|
+
* unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.
|
|
13
|
+
*
|
|
14
|
+
* Must live here (not inside `<script setup>`) because Vue compiles
|
|
15
|
+
* `<script setup>` into the component's `setup()` function — any
|
|
16
|
+
* `let counter = 0` there resets per instance, causing id collisions.
|
|
17
|
+
*/
|
|
18
|
+
export function nextId(prefix: string): string {
|
|
19
|
+
counters[prefix] = (counters[prefix] ?? 0) + 1
|
|
20
|
+
return `${prefix}${counters[prefix]}`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function hasWidthUtility(classStr: string): boolean {
|
|
24
|
+
return classStr.split(/\s+/).some((c) => {
|
|
25
|
+
const utility = c.split(':').pop() ?? ''
|
|
26
|
+
const clean = utility.replace(/^!/, '')
|
|
27
|
+
return /^(w-|max-w-|min-w-)/.test(clean)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function hasWidthInStyle(styleStr: string): boolean {
|
|
32
|
+
return /(?:^|;\s*)(?:max-width|width)\s*:/i.test(styleStr)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function hasHeightUtility(classStr: string): boolean {
|
|
36
|
+
return classStr.split(/\s+/).some((c) => {
|
|
37
|
+
const utility = c.split(':').pop() ?? ''
|
|
38
|
+
const clean = utility.replace(/^!/, '')
|
|
39
|
+
return /^(h-|max-h-|min-h-)/.test(clean)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function hasHeightInStyle(styleStr: string): boolean {
|
|
44
|
+
return /(?:^|;\s*)(?:max-height|height)\s*:/i.test(styleStr)
|
|
45
|
+
}
|
|
@@ -4,6 +4,12 @@ import { UsePlaintextOptions } from "./usePlaintext.mjs";
|
|
|
4
4
|
import { InjectionKey } from "vue";
|
|
5
5
|
|
|
6
6
|
//#region src/composables/renderContext.d.ts
|
|
7
|
+
interface FontRegistration {
|
|
8
|
+
family: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
declaration: string;
|
|
11
|
+
url: string;
|
|
12
|
+
}
|
|
7
13
|
interface RenderContext {
|
|
8
14
|
doctype?: string;
|
|
9
15
|
preheader?: {
|
|
@@ -17,8 +23,9 @@ interface RenderContext {
|
|
|
17
23
|
handler: EventMap[EventName];
|
|
18
24
|
}>;
|
|
19
25
|
plaintext?: UsePlaintextOptions;
|
|
26
|
+
fonts?: FontRegistration[];
|
|
20
27
|
}
|
|
21
28
|
declare const RenderContextKey: InjectionKey<RenderContext>;
|
|
22
29
|
//#endregion
|
|
23
|
-
export { RenderContext, RenderContextKey };
|
|
30
|
+
export { FontRegistration, RenderContext, RenderContextKey };
|
|
24
31
|
//# sourceMappingURL=renderContext.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderContext.d.mts","names":[],"sources":["../../src/composables/renderContext.ts"],"mappings":";;;;;;UAKiB,aAAA;EACf,OAAA;EACA,SAAA;IAAc,IAAA;IAAc,WAAA;IAAqB,QAAA;EAAA;EACjD,SAAA,GAAY,aAAA;EACZ,gBAAA,EAAkB,KAAA;IAAQ,IAAA,EAAM,SAAA;IAAW,OAAA,EAAS,QAAA,CAAS,SAAA;EAAA;EAC7D,SAAA,GAAY,mBAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"renderContext.d.mts","names":[],"sources":["../../src/composables/renderContext.ts"],"mappings":";;;;;;UAKiB,gBAAA;EACf,MAAA;EACA,IAAA;EACA,WAAA;EACA,GAAA;AAAA;AAAA,UAGe,aAAA;EACf,OAAA;EACA,SAAA;IAAc,IAAA;IAAc,WAAA;IAAqB,QAAA;EAAA;EACjD,SAAA,GAAY,aAAA;EACZ,gBAAA,EAAkB,KAAA;IAAQ,IAAA,EAAM,SAAA;IAAW,OAAA,EAAS,QAAA,CAAS,SAAA;EAAA;EAC7D,SAAA,GAAY,mBAAA;EACZ,KAAA,GAAQ,gBAAA;AAAA;AAAA,cAGG,gBAAA,EAAkB,YAAA,CAAa,aAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderContext.mjs","names":[],"sources":["../../src/composables/renderContext.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\nimport type { UsePlaintextOptions } from './usePlaintext.ts'\n\nexport interface RenderContext {\n doctype?: string\n preheader?: { text: string; fillerCount: number; shyCount: number }\n sfcConfig?: MaizzleConfig\n sfcEventHandlers: Array<{ name: EventName; handler: EventMap[EventName] }>\n plaintext?: UsePlaintextOptions\n}\n\nexport const RenderContextKey: InjectionKey<RenderContext> = Symbol('RenderContext')\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"renderContext.mjs","names":[],"sources":["../../src/composables/renderContext.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\nimport type { UsePlaintextOptions } from './usePlaintext.ts'\n\nexport interface FontRegistration {\n family: string\n slug: string\n declaration: string\n url: string\n}\n\nexport interface RenderContext {\n doctype?: string\n preheader?: { text: string; fillerCount: number; shyCount: number }\n sfcConfig?: MaizzleConfig\n sfcEventHandlers: Array<{ name: EventName; handler: EventMap[EventName] }>\n plaintext?: UsePlaintextOptions\n fonts?: FontRegistration[]\n}\n\nexport const RenderContextKey: InjectionKey<RenderContext> = Symbol('RenderContext')\n"],"mappings":";AAqBA,MAAa,mBAAgD,OAAO,gBAAgB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/composables/useFont.d.ts
|
|
2
|
+
type FontProvider = 'google' | 'bunny';
|
|
3
|
+
interface UseFontOptions {
|
|
4
|
+
/**
|
|
5
|
+
* A single font family name, e.g. `"Roboto"` or `"Open Sans"`.
|
|
6
|
+
*
|
|
7
|
+
* For fallback fonts, use the `fallback` option instead of a
|
|
8
|
+
* comma-separated list here.
|
|
9
|
+
*/
|
|
10
|
+
family: string;
|
|
11
|
+
/** CSS fallback list appended to the `font-family` declaration. */
|
|
12
|
+
fallback?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Font provider used to build the stylesheet URL when `url` is omitted.
|
|
15
|
+
* Bunny Fonts is a drop-in, privacy-friendly Google Fonts mirror.
|
|
16
|
+
* @default 'google'
|
|
17
|
+
*/
|
|
18
|
+
provider?: FontProvider;
|
|
19
|
+
/**
|
|
20
|
+
* Stylesheet URL. When provided, used as-is for the `<link href>`.
|
|
21
|
+
* When omitted, a URL is built from `provider`, `family`, `weights`,
|
|
22
|
+
* `display` and `styles`.
|
|
23
|
+
*/
|
|
24
|
+
url?: string;
|
|
25
|
+
/** Font weights to load. Ignored when `url` is provided. */
|
|
26
|
+
weights?: number[];
|
|
27
|
+
/** `font-display` value. Ignored when `url` is provided. */
|
|
28
|
+
display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
|
|
29
|
+
/** Font styles to load. Ignored when `url` is provided. */
|
|
30
|
+
styles?: Array<'normal' | 'italic'>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Register a font for the current email template.
|
|
34
|
+
*
|
|
35
|
+
* Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`
|
|
36
|
+
* (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`
|
|
37
|
+
* and merges `--font-{slug}` declarations into the template's existing
|
|
38
|
+
* `@import "tailwindcss"` style block so a `font-{slug}` utility class
|
|
39
|
+
* is generated. If no Tailwind import is found, falls back to a `:root`
|
|
40
|
+
* declaration so the CSS variable is still available.
|
|
41
|
+
*
|
|
42
|
+
* Usage in SFC <script setup>:
|
|
43
|
+
* ```ts
|
|
44
|
+
* useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function useFont(options: UseFontOptions): void;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { FontProvider, UseFontOptions, useFont };
|
|
50
|
+
//# sourceMappingURL=useFont.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFont.d.mts","names":[],"sources":["../../src/composables/useFont.ts"],"mappings":";KA8CY,YAAA;AAAA,UAEK,cAAA;EAFO;;;;AAExB;;EAOE,MAAA;EAoBc;EAlBd,QAAA;EAAA;;;;;EAMA,QAAA,GAAW,YAAA;EAYX;;;;AA+CF;EArDE,GAAA;;EAEA,OAAA;EAmD6C;EAjD7C,OAAA;;EAEA,MAAA,GAAS,KAAA;AAAA;;;;;;;;;;;;;;;;iBA+CK,OAAA,CAAQ,OAAA,EAAS,cAAA"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { RenderContextKey } from "./renderContext.mjs";
|
|
2
|
+
import { inject } from "vue";
|
|
3
|
+
|
|
4
|
+
//#region src/composables/useFont.ts
|
|
5
|
+
const FAMILY_CATEGORIES = {
|
|
6
|
+
"Roboto": "sans",
|
|
7
|
+
"Open Sans": "sans",
|
|
8
|
+
"Inter": "sans",
|
|
9
|
+
"Lato": "sans",
|
|
10
|
+
"Montserrat": "sans",
|
|
11
|
+
"Merriweather": "serif",
|
|
12
|
+
"Playfair Display": "serif",
|
|
13
|
+
"Lora": "serif",
|
|
14
|
+
"PT Serif": "serif",
|
|
15
|
+
"Noto Serif": "serif",
|
|
16
|
+
"Oswald": "display",
|
|
17
|
+
"Bebas Neue": "display",
|
|
18
|
+
"Anton": "display",
|
|
19
|
+
"Lobster": "display",
|
|
20
|
+
"Pacifico": "display",
|
|
21
|
+
"Dancing Script": "handwriting",
|
|
22
|
+
"Caveat": "handwriting",
|
|
23
|
+
"Shadows Into Light": "handwriting",
|
|
24
|
+
"Satisfy": "handwriting",
|
|
25
|
+
"Great Vibes": "handwriting",
|
|
26
|
+
"Roboto Mono": "mono",
|
|
27
|
+
"Source Code Pro": "mono",
|
|
28
|
+
"JetBrains Mono": "mono",
|
|
29
|
+
"Fira Code": "mono",
|
|
30
|
+
"Inconsolata": "mono"
|
|
31
|
+
};
|
|
32
|
+
const DEFAULT_FALLBACKS = {
|
|
33
|
+
sans: "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif",
|
|
34
|
+
serif: "ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif",
|
|
35
|
+
mono: "ui-monospace, Menlo, Consolas, monospace",
|
|
36
|
+
display: "Impact, \"Arial Black\", system-ui, sans-serif",
|
|
37
|
+
handwriting: "\"Segoe Script\", \"Brush Script MT\", cursive"
|
|
38
|
+
};
|
|
39
|
+
const PROVIDER_BASE_URL = {
|
|
40
|
+
google: "https://fonts.googleapis.com/css2",
|
|
41
|
+
bunny: "https://fonts.bunny.net/css2"
|
|
42
|
+
};
|
|
43
|
+
function slugify(family) {
|
|
44
|
+
return family.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
45
|
+
}
|
|
46
|
+
function buildProviderUrl(opts) {
|
|
47
|
+
const familyParam = opts.family.trim().replace(/\s+/g, "+");
|
|
48
|
+
const weights = [...opts.weights].sort((a, b) => a - b);
|
|
49
|
+
const hasItalic = opts.styles.includes("italic");
|
|
50
|
+
const hasNormal = opts.styles.includes("normal");
|
|
51
|
+
const axis = hasItalic ? `:ital,wght@${weights.flatMap((w) => [...hasNormal ? [`0,${w}`] : [], `1,${w}`]).join(";")}` : `:wght@${weights.join(";")}`;
|
|
52
|
+
return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Register a font for the current email template.
|
|
56
|
+
*
|
|
57
|
+
* Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`
|
|
58
|
+
* (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`
|
|
59
|
+
* and merges `--font-{slug}` declarations into the template's existing
|
|
60
|
+
* `@import "tailwindcss"` style block so a `font-{slug}` utility class
|
|
61
|
+
* is generated. If no Tailwind import is found, falls back to a `:root`
|
|
62
|
+
* declaration so the CSS variable is still available.
|
|
63
|
+
*
|
|
64
|
+
* Usage in SFC <script setup>:
|
|
65
|
+
* ```ts
|
|
66
|
+
* useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
function useFont(options) {
|
|
70
|
+
const ctx = inject(RenderContextKey);
|
|
71
|
+
if (!ctx) return;
|
|
72
|
+
ctx.fonts = ctx.fonts ?? [];
|
|
73
|
+
if (ctx.fonts.some((f) => f.family === options.family)) return;
|
|
74
|
+
const url = options.url ?? buildProviderUrl({
|
|
75
|
+
family: options.family,
|
|
76
|
+
provider: options.provider ?? "google",
|
|
77
|
+
weights: options.weights ?? [400],
|
|
78
|
+
display: options.display ?? "swap",
|
|
79
|
+
styles: options.styles ?? ["normal"]
|
|
80
|
+
});
|
|
81
|
+
const fallback = options.fallback ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? "sans"];
|
|
82
|
+
const declaration = `${/\s/.test(options.family) ? `"${options.family}"` : options.family}, ${fallback}`;
|
|
83
|
+
ctx.fonts.push({
|
|
84
|
+
family: options.family,
|
|
85
|
+
slug: slugify(options.family),
|
|
86
|
+
declaration,
|
|
87
|
+
url
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
export { useFont };
|
|
93
|
+
//# sourceMappingURL=useFont.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFont.mjs","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;CAChB;AAED,MAAM,oBAAkD;CACtD,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,aAAa;CACd;AAkCD,MAAM,oBAAkD;CACtD,QAAQ;CACR,OAAO;CACR;AAED,SAAS,QAAQ,QAAwB;AACvC,QAAO,OACJ,MAAM,CACN,aAAa,CACb,QAAQ,QAAQ,IAAI,CACpB,QAAQ,eAAe,GAAG;;AAG/B,SAAS,iBAAiB,MAAkE;CAC1F,MAAM,cAAc,KAAK,OAAO,MAAM,CAAC,QAAQ,QAAQ,IAAI;CAC3D,MAAM,UAAU,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CACvD,MAAM,YAAY,KAAK,OAAO,SAAS,SAAS;CAChD,MAAM,YAAY,KAAK,OAAO,SAAS,SAAS;CAEhD,MAAM,OAAO,YACT,cAAc,QAAQ,SAAQ,MAAK,CACjC,GAAI,YAAY,CAAC,KAAK,IAAI,GAAG,EAAE,EAC/B,KAAK,IACN,CAAC,CAAC,KAAK,IAAI,KACZ,SAAS,QAAQ,KAAK,IAAI;AAE9B,QAAO,GAAG,kBAAkB,KAAK,UAAU,UAAU,cAAc,KAAK,WAAW,KAAK;;;;;;;;;;;;;;;;;AAkB1F,SAAgB,QAAQ,SAA+B;CACrD,MAAM,MAAM,OAAO,iBAAiB;AACpC,KAAI,CAAC,IAAK;AAEV,KAAI,QAAQ,IAAI,SAAS,EAAE;AAC3B,KAAI,IAAI,MAAM,MAAK,MAAK,EAAE,WAAW,QAAQ,OAAO,CAAE;CAEtD,MAAM,MAAM,QAAQ,OAAO,iBAAiB;EAC1C,QAAQ,QAAQ;EAChB,UAAU,QAAQ,YAAY;EAC9B,SAAS,QAAQ,WAAW,CAAC,IAAI;EACjC,SAAS,QAAQ,WAAW;EAC5B,QAAQ,QAAQ,UAAU,CAAC,SAAS;EACrC,CAAC;CAEF,MAAM,WAAW,QAAQ,YACpB,kBAAkB,kBAAkB,QAAQ,WAAW;CAE5D,MAAM,cAAc,GADL,KAAK,KAAK,QAAQ,OAAO,GAAG,IAAI,QAAQ,OAAO,KAAK,QAAQ,OAC7C,IAAI;AAElC,KAAI,MAAM,KAAK;EACb,QAAQ,QAAQ;EAChB,MAAM,QAAQ,QAAQ,OAAO;EAC7B;EACA;EACD,CAAC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -5,11 +5,13 @@ import { usePlaintext } from "./composables/usePlaintext.mjs";
|
|
|
5
5
|
import { useConfig } from "./composables/useConfig.mjs";
|
|
6
6
|
import { useDoctype } from "./composables/useDoctype.mjs";
|
|
7
7
|
import { useEvent } from "./composables/useEvent.mjs";
|
|
8
|
+
import { useFont } from "./composables/useFont.mjs";
|
|
8
9
|
import { resolveConfig } from "./config/index.mjs";
|
|
9
10
|
import { maizzle } from "./plugin.mjs";
|
|
10
11
|
import { CreateRendererOptions, RenderedTemplate, Renderer, createRenderer } from "./render/createRenderer.mjs";
|
|
11
12
|
import { RenderOptions, RenderResult, render } from "./render/index.mjs";
|
|
12
13
|
import { serve } from "./serve.mjs";
|
|
14
|
+
import { PrepareOptions, prepare } from "./prepare.mjs";
|
|
13
15
|
import { createPlaintext } from "./plaintext.mjs";
|
|
14
16
|
import { inlineLink } from "./transformers/inlineLink.mjs";
|
|
15
17
|
import { urlQuery } from "./transformers/urlQuery.mjs";
|
|
@@ -28,4 +30,4 @@ import { replaceStrings } from "./transformers/replaceStrings.mjs";
|
|
|
28
30
|
import { format } from "./transformers/format.mjs";
|
|
29
31
|
import { minify } from "./transformers/minify.mjs";
|
|
30
32
|
import { useHead } from "@unhead/vue";
|
|
31
|
-
export { type AttributesConfig, type CreateRendererOptions, type CssConfig, type EntitiesConfig, type FilterFunction, type FiltersConfig, type HtmlConfig, type MaizzleConfig, type RenderOptions, type RenderResult, type RenderedTemplate, type Renderer, type UrlConfig, type UrlQuery, type UrlQueryOptions, addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCSS, inlineLink, maizzle, minify, removeAttributes, purgeCSS as removeUnusedCSS, render, replaceStrings, resolveConfig, safeClassNames, serve, shorthandCSS, sixHex, urlQuery, useConfig, useDoctype, useEvent, useHead, usePlaintext };
|
|
33
|
+
export { type AttributesConfig, type CreateRendererOptions, type CssConfig, type EntitiesConfig, type FilterFunction, type FiltersConfig, type HtmlConfig, type MaizzleConfig, type PrepareOptions, type RenderOptions, type RenderResult, type RenderedTemplate, type Renderer, type UrlConfig, type UrlQuery, type UrlQueryOptions, addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCSS, inlineLink, maizzle, minify, prepare, removeAttributes, purgeCSS as removeUnusedCSS, render, replaceStrings, resolveConfig, safeClassNames, serve, shorthandCSS, sixHex, urlQuery, useConfig, useDoctype, useEvent, useFont, useHead, usePlaintext };
|
package/dist/index.mjs
CHANGED
|
@@ -23,9 +23,11 @@ import { build } from "./build.mjs";
|
|
|
23
23
|
import { maizzle } from "./plugin.mjs";
|
|
24
24
|
import { render } from "./render/index.mjs";
|
|
25
25
|
import { serve } from "./serve.mjs";
|
|
26
|
+
import { prepare } from "./prepare.mjs";
|
|
26
27
|
import { useDoctype } from "./composables/useDoctype.mjs";
|
|
27
28
|
import { useEvent } from "./composables/useEvent.mjs";
|
|
29
|
+
import { useFont } from "./composables/useFont.mjs";
|
|
28
30
|
import { usePlaintext } from "./composables/usePlaintext.mjs";
|
|
29
31
|
import { useHead } from "@unhead/vue";
|
|
30
32
|
|
|
31
|
-
export { addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCSS, inlineLink, maizzle, minify, removeAttributes, purgeCSS as removeUnusedCSS, render, replaceStrings, resolveConfig, safeClassNames, serve, shorthandCSS, sixHex, urlQuery, useConfig, useDoctype, useEvent, useHead, usePlaintext };
|
|
33
|
+
export { addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCSS, inlineLink, maizzle, minify, prepare, removeAttributes, purgeCSS as removeUnusedCSS, render, replaceStrings, resolveConfig, safeClassNames, serve, shorthandCSS, sixHex, urlQuery, useConfig, useDoctype, useEvent, useFont, useHead, usePlaintext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Plugin } from "postcss";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/postcss/quoteFontFamilies.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Re-quote multi-word font-family identifiers that lightningcss "optimised"
|
|
6
|
+
* by removing quotes. CSS allows space-separated identifiers as a family
|
|
7
|
+
* name, but Google Fonts (and most style guides) prescribe quoted form.
|
|
8
|
+
*/
|
|
9
|
+
declare function quoteFontFamilies(): Plugin;
|
|
10
|
+
declare const postcss = true;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { postcss, quoteFontFamilies };
|
|
13
|
+
//# sourceMappingURL=quoteFontFamilies.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quoteFontFamilies.d.mts","names":[],"sources":["../../../src/plugins/postcss/quoteFontFamilies.ts"],"mappings":";;;;;AA+CA;;;iBAAgB,iBAAA,CAAA,GAAqB,MAAA;AAAA,cA6BxB,OAAA"}
|