@4verburga/alpine-spanishplus 1.6.6
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/LICENSE +21 -0
- package/README.md +60 -0
- package/app.config.ts +45 -0
- package/app.vue +11 -0
- package/assets/main.css +20 -0
- package/components/AppFooter.vue +110 -0
- package/components/AppHeader.vue +151 -0
- package/components/AppLayout.vue +35 -0
- package/components/AppLoadingBar.vue +110 -0
- package/components/Button.vue +46 -0
- package/components/ColorModeSwitch.vue +47 -0
- package/components/DocumentDrivenNotFound.vue +49 -0
- package/components/MainNav.vue +64 -0
- package/components/SocialIcons.vue +70 -0
- package/components/content/ArticleIndexEntry.vue +122 -0
- package/components/content/ArticlesIndex.vue +70 -0
- package/components/content/ArticlesList.vue +72 -0
- package/components/content/ArticlesListItem.vue +149 -0
- package/components/content/ContactForm.vue +123 -0
- package/components/content/Gallery.vue +49 -0
- package/components/content/Hero.vue +77 -0
- package/components/data-entry/Input.vue +87 -0
- package/composables/date.ts +8 -0
- package/layouts/article.vue +131 -0
- package/layouts/default.vue +6 -0
- package/layouts/page.vue +5 -0
- package/nuxt.config.ts +90 -0
- package/nuxt.schema.ts +184 -0
- package/package.json +59 -0
- package/tokens.config.ts +51 -0
- package/types/contact.ts +7 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
import type { Field } from '../../types/contact'
|
|
4
|
+
const alpine = useAppConfig().alpine
|
|
5
|
+
|
|
6
|
+
const { FORMSPREE_URL } = useRuntimeConfig().public
|
|
7
|
+
|
|
8
|
+
if (!FORMSPREE_URL) {
|
|
9
|
+
console.warn('No FORMSPREE_URL provided')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const status = ref()
|
|
13
|
+
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
submitButtonText: {
|
|
16
|
+
type: String,
|
|
17
|
+
default: 'Send message'
|
|
18
|
+
},
|
|
19
|
+
fields: {
|
|
20
|
+
type: Array as PropType<Field[]>,
|
|
21
|
+
default: () => [
|
|
22
|
+
{
|
|
23
|
+
type: 'text',
|
|
24
|
+
model: 'name',
|
|
25
|
+
name: 'Name',
|
|
26
|
+
placeholder: 'Your name',
|
|
27
|
+
required: true,
|
|
28
|
+
layout: 'default'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'email',
|
|
32
|
+
model: 'email',
|
|
33
|
+
name: 'Email',
|
|
34
|
+
placeholder: 'Your email',
|
|
35
|
+
required: true,
|
|
36
|
+
layout: 'default'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: 'text',
|
|
40
|
+
model: 'text',
|
|
41
|
+
name: 'Subject',
|
|
42
|
+
required: false,
|
|
43
|
+
layout: 'default'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'textarea',
|
|
47
|
+
model: 'message',
|
|
48
|
+
name: 'Message',
|
|
49
|
+
placeholder: 'Your message',
|
|
50
|
+
required: true,
|
|
51
|
+
layout: 'big'
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const form = reactive(props.fields.map(v => ({ ...v, data: '' })))
|
|
58
|
+
|
|
59
|
+
const onSend = async (e: any) => {
|
|
60
|
+
e.preventDefault()
|
|
61
|
+
const data = new FormData(e.target)
|
|
62
|
+
|
|
63
|
+
status.value = 'Sending...'
|
|
64
|
+
|
|
65
|
+
fetch(e.target.action, {
|
|
66
|
+
method: e.target.method,
|
|
67
|
+
body: data,
|
|
68
|
+
headers: {
|
|
69
|
+
'Accept': 'application/json'
|
|
70
|
+
}
|
|
71
|
+
}).then(response => {
|
|
72
|
+
if (response.ok) {
|
|
73
|
+
status.value = alpine.form.successMessage
|
|
74
|
+
e.target.reset()
|
|
75
|
+
} else {
|
|
76
|
+
// Handle errors from API
|
|
77
|
+
response.json().then(data => {
|
|
78
|
+
if (Object.hasOwn(data, 'errors')) {
|
|
79
|
+
status.value = data["errors"][0].message
|
|
80
|
+
console.error(data["errors"].map((error: any) => error["message"]).join(", "))
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
status.value = 'Send message'
|
|
83
|
+
}, 2000)
|
|
84
|
+
} else {
|
|
85
|
+
console.error("There was a problem submitting your form")
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
}).catch(() => {
|
|
90
|
+
// Catch all other errors
|
|
91
|
+
console.error("There was a problem submitting your form")
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<template>
|
|
98
|
+
<form class="contact-form" method="POST" :action="FORMSPREE_URL" @submit="onSend">
|
|
99
|
+
<div class="inputs">
|
|
100
|
+
<Input v-for="(field, index) in form" :key="index" v-model="field.data" :field="field" />
|
|
101
|
+
</div>
|
|
102
|
+
<div>
|
|
103
|
+
<Button type="submit" :disabled="!FORMSPREE_URL">
|
|
104
|
+
{{ status ? status : submitButtonText }}
|
|
105
|
+
</Button>
|
|
106
|
+
</div>
|
|
107
|
+
</form>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<style scoped lang="ts">
|
|
111
|
+
css({
|
|
112
|
+
'.contact-form': {
|
|
113
|
+
'.inputs': {
|
|
114
|
+
display: 'grid',
|
|
115
|
+
gridAutoFlow: 'row',
|
|
116
|
+
gridTemplateColumns: 'repeat(1, minmax(0, 1fr))',
|
|
117
|
+
gap: '{space.8}',
|
|
118
|
+
marginBottom: '{space.8}',
|
|
119
|
+
maxWidth: '{size.md}'
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps({
|
|
5
|
+
images: {
|
|
6
|
+
type: Array as PropType<string[]>,
|
|
7
|
+
default: () => []
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<section class="gallery">
|
|
14
|
+
<div
|
|
15
|
+
class="layout"
|
|
16
|
+
>
|
|
17
|
+
<NuxtImg
|
|
18
|
+
v-for="(image, index) in images"
|
|
19
|
+
:key="index"
|
|
20
|
+
:src="image"
|
|
21
|
+
:width="16"
|
|
22
|
+
:height="9"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<style scoped lang="ts">
|
|
29
|
+
css({
|
|
30
|
+
'.gallery': {
|
|
31
|
+
'.layout': {
|
|
32
|
+
display: 'grid',
|
|
33
|
+
gap: '{space.8}',
|
|
34
|
+
my: '{space.16}',
|
|
35
|
+
'--cols': 1,
|
|
36
|
+
gridTemplateColumns: 'repeat(var(--cols), minmax(0, 1fr))',
|
|
37
|
+
'@md': {
|
|
38
|
+
'--cols': (props) => props.images.length < 2 ? props.images.length : 2
|
|
39
|
+
},
|
|
40
|
+
img: {
|
|
41
|
+
objectFit: 'cover',
|
|
42
|
+
width: '100%',
|
|
43
|
+
aspectRatio: '16 / 9',
|
|
44
|
+
borderRadius: '{radii.md}'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps({
|
|
3
|
+
image: {
|
|
4
|
+
type: String,
|
|
5
|
+
default: null
|
|
6
|
+
},
|
|
7
|
+
imageAlt: {
|
|
8
|
+
type: String,
|
|
9
|
+
default: 'Hero Image'
|
|
10
|
+
},
|
|
11
|
+
imagePosition: {
|
|
12
|
+
type: String,
|
|
13
|
+
default: 'right'
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<section class="hero">
|
|
20
|
+
<div class="layout">
|
|
21
|
+
<div class="content">
|
|
22
|
+
<div class="title">
|
|
23
|
+
<ContentSlot :use="$slots.title" unwrap="p">
|
|
24
|
+
Hero title
|
|
25
|
+
</ContentSlot>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="description">
|
|
28
|
+
<ContentSlot :use="$slots.description" unwrap="p">
|
|
29
|
+
Hero description
|
|
30
|
+
</ContentSlot>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<NuxtImg
|
|
34
|
+
v-if="image"
|
|
35
|
+
:class="imagePosition"
|
|
36
|
+
:src="image"
|
|
37
|
+
:alt="imageAlt"
|
|
38
|
+
:width="16"
|
|
39
|
+
:height="9"
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<style scoped lang="ts">
|
|
46
|
+
css({
|
|
47
|
+
'.hero': {
|
|
48
|
+
'.layout': {
|
|
49
|
+
display: 'grid',
|
|
50
|
+
gridTemplateColumns: 'repeat(1, minmax(0, 1fr))',
|
|
51
|
+
gap: '{space.8}',
|
|
52
|
+
'@lg': {
|
|
53
|
+
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
|
|
54
|
+
},
|
|
55
|
+
'.title': {
|
|
56
|
+
fontSize: '{text.4xl.fontSize}',
|
|
57
|
+
lineHeight: '{text.4xl.lineHeight}',
|
|
58
|
+
fontWeight: '{fontWeight.bold}',
|
|
59
|
+
},
|
|
60
|
+
'.description': {
|
|
61
|
+
marginTop: '{space.3}',
|
|
62
|
+
fontSize: '{text.xl.fontSize}',
|
|
63
|
+
lineHeight: '{text.xl.lineHeight}',
|
|
64
|
+
},
|
|
65
|
+
img: {
|
|
66
|
+
width: '100%',
|
|
67
|
+
aspectRatio: '16 / 9',
|
|
68
|
+
objectFit: 'cover',
|
|
69
|
+
borderRadius: '{radii.md}',
|
|
70
|
+
'&.left': {
|
|
71
|
+
order: -1
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
import type { Field } from '../types/contact'
|
|
4
|
+
|
|
5
|
+
defineEmits(['update:modelValue'])
|
|
6
|
+
|
|
7
|
+
defineProps({
|
|
8
|
+
modelValue: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true
|
|
11
|
+
},
|
|
12
|
+
field: {
|
|
13
|
+
type: Object as PropType<Field>,
|
|
14
|
+
required: true,
|
|
15
|
+
validator: (value: Field) => {
|
|
16
|
+
if (!value.name) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<div>
|
|
28
|
+
<label :for="field.name">
|
|
29
|
+
{{ field.label }}
|
|
30
|
+
</label>
|
|
31
|
+
<input
|
|
32
|
+
v-if="field.type !== 'textarea'"
|
|
33
|
+
:id="field.name"
|
|
34
|
+
:name="field.name"
|
|
35
|
+
:value="modelValue"
|
|
36
|
+
:type="field.type ? field.type : 'text'"
|
|
37
|
+
:placeholder="field.placeholder ? field.placeholder : ''"
|
|
38
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
39
|
+
>
|
|
40
|
+
<textarea
|
|
41
|
+
v-else
|
|
42
|
+
:id="field.name"
|
|
43
|
+
:name="field.name"
|
|
44
|
+
:value="modelValue"
|
|
45
|
+
:type="field.type ? field.type : 'text'"
|
|
46
|
+
:placeholder="field.placeholder ? field.placeholder : ''"
|
|
47
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<style scoped lang="ts">
|
|
53
|
+
css({
|
|
54
|
+
div: {
|
|
55
|
+
label: {
|
|
56
|
+
display: 'block',
|
|
57
|
+
fontSize: '{text.base.fontSize}',
|
|
58
|
+
lineHeight: '{text.base.lineHeight}',
|
|
59
|
+
fontWeight: '{fontWeight.semibold}',
|
|
60
|
+
marginBottom: '{space.2}',
|
|
61
|
+
cursor: 'pointer',
|
|
62
|
+
},
|
|
63
|
+
'input, textarea': {
|
|
64
|
+
backgroundColor: 'transparent',
|
|
65
|
+
outline: 'none',
|
|
66
|
+
border: '1px solid {color.gray.300}',
|
|
67
|
+
borderRadius: '{radii.sm}',
|
|
68
|
+
padding: '{space.2} {space.4}',
|
|
69
|
+
width: '100%',
|
|
70
|
+
caretColor: '{color.gray.500}',
|
|
71
|
+
'&:focus': {
|
|
72
|
+
borderColor: '{color.gray.700}'
|
|
73
|
+
},
|
|
74
|
+
'@dark': {
|
|
75
|
+
borderColor: '{color.gray.700}',
|
|
76
|
+
'&:focus': {
|
|
77
|
+
borderColor: '{color.gray.400}'
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
textarea: {
|
|
82
|
+
resize: 'none',
|
|
83
|
+
height: '{space.48}'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
</style>
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<article ref="article">
|
|
3
|
+
<!-- TODO: could be refactored as a transparent ButtonLink -->
|
|
4
|
+
<NuxtLink
|
|
5
|
+
:to="parentPath"
|
|
6
|
+
class="back"
|
|
7
|
+
>
|
|
8
|
+
<Icon name="ph:arrow-left" />
|
|
9
|
+
<span>
|
|
10
|
+
Back
|
|
11
|
+
</span>
|
|
12
|
+
</NuxtLink>
|
|
13
|
+
<header>
|
|
14
|
+
<h1
|
|
15
|
+
v-if="page?.title"
|
|
16
|
+
class="title"
|
|
17
|
+
>
|
|
18
|
+
{{ page.title }}
|
|
19
|
+
</h1>
|
|
20
|
+
<time
|
|
21
|
+
v-if="page?.date"
|
|
22
|
+
:datetime="page.date"
|
|
23
|
+
>
|
|
24
|
+
{{ formatDate(page.date) }}
|
|
25
|
+
</time>
|
|
26
|
+
</header>
|
|
27
|
+
|
|
28
|
+
<div class="prose">
|
|
29
|
+
<slot />
|
|
30
|
+
<div
|
|
31
|
+
v-if="alpine?.backToTop"
|
|
32
|
+
class="back-to-top"
|
|
33
|
+
>
|
|
34
|
+
<ProseA @click.prevent.stop="onBackToTop">
|
|
35
|
+
{{ alpine?.backToTop?.text || 'Back to top' }}
|
|
36
|
+
<Icon :name="alpine?.backToTop?.icon || 'material-symbols:arrow-upward'" />
|
|
37
|
+
</ProseA>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</article>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
const { page } = useContent()
|
|
45
|
+
const route = useRoute()
|
|
46
|
+
const alpine = useAppConfig().alpine
|
|
47
|
+
|
|
48
|
+
const article = ref<HTMLElement | null>(null)
|
|
49
|
+
|
|
50
|
+
if (page.value) {
|
|
51
|
+
const linkArray = []
|
|
52
|
+
const metaArray = []
|
|
53
|
+
|
|
54
|
+
if (page.value.cover) {
|
|
55
|
+
metaArray.push({ property: 'og:image', content: page.value.cover })
|
|
56
|
+
}
|
|
57
|
+
if (page.value.canonical) {
|
|
58
|
+
linkArray.push({ rel: 'canonical', href: page.value.canonical })
|
|
59
|
+
}
|
|
60
|
+
useHead({
|
|
61
|
+
meta: metaArray,
|
|
62
|
+
link: linkArray
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const parentPath = computed(
|
|
67
|
+
() => {
|
|
68
|
+
const pathTabl = route.path.split('/')
|
|
69
|
+
pathTabl.pop()
|
|
70
|
+
return pathTabl.join('/')
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
const onBackToTop = () => {
|
|
75
|
+
article.value?.scrollIntoView({
|
|
76
|
+
behavior: 'smooth'
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<style scoped lang="ts">
|
|
82
|
+
css({
|
|
83
|
+
article: {
|
|
84
|
+
maxWidth: '{alpine.readableLine}',
|
|
85
|
+
mx: 'auto',
|
|
86
|
+
py: '{space.4}',
|
|
87
|
+
'@sm': {
|
|
88
|
+
py: '{space.12}',
|
|
89
|
+
},
|
|
90
|
+
'.back': {
|
|
91
|
+
display: 'inline-flex',
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
fontSize: '{text.lg.fontSize}',
|
|
94
|
+
borderBottom: '1px solid {elements.border.secondary.static}',
|
|
95
|
+
'& :deep(svg)': {
|
|
96
|
+
width: '{size.16}',
|
|
97
|
+
height: '{size.16}',
|
|
98
|
+
marginRight: '{space.2}'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
header: {
|
|
102
|
+
marginTop: '{space.16}',
|
|
103
|
+
marginBottom: '{space.12}',
|
|
104
|
+
},
|
|
105
|
+
'.title': {
|
|
106
|
+
fontSize: '{text.5xl.fontSize}',
|
|
107
|
+
lineHeight: '{text.5xl.lineHeight}',
|
|
108
|
+
fontWeight: '{fontWeight.semibold}',
|
|
109
|
+
marginBottom: '{space.4}'
|
|
110
|
+
},
|
|
111
|
+
time: {
|
|
112
|
+
color: '{elements.text.secondary.color.static}'
|
|
113
|
+
},
|
|
114
|
+
'.prose': {
|
|
115
|
+
'.back-to-top': {
|
|
116
|
+
display: 'flex',
|
|
117
|
+
justifyContent: 'flex-end',
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
width: '100%',
|
|
120
|
+
a: {
|
|
121
|
+
cursor: 'pointer',
|
|
122
|
+
fontSize: '{text.lg.fontSize}'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
'& :deep(h1)': {
|
|
126
|
+
display: 'none'
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
</style>
|
package/layouts/page.vue
ADDED
package/nuxt.config.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createResolver, logger, defineNuxtModule } from '@nuxt/kit'
|
|
2
|
+
import { $fetch } from 'ofetch'
|
|
3
|
+
import { version } from './package.json'
|
|
4
|
+
|
|
5
|
+
const { resolve } = createResolver(import.meta.url)
|
|
6
|
+
|
|
7
|
+
// That allows to overwrite these dependencies paths via `.env` for local development
|
|
8
|
+
const envModules = {
|
|
9
|
+
tokens: process?.env?.THEME_DEV_TOKENS_PATH || '@nuxt-themes/tokens',
|
|
10
|
+
elements: process?.env?.THEME_DEV_ELEMENTS_PATH || '@nuxt-themes/elements',
|
|
11
|
+
studio: process?.env?.THEME_DEV_STUDIO_PATH || '@nuxthq/studio',
|
|
12
|
+
typography: process?.env?.THEME_DEV_TYPOGRAPHY_PATH || '@nuxt-themes/typography'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const updateModule = defineNuxtModule({
|
|
16
|
+
meta: {
|
|
17
|
+
name: '@nuxt-themes/alpine'
|
|
18
|
+
},
|
|
19
|
+
setup (_, nuxt) {
|
|
20
|
+
if (nuxt.options.dev) {
|
|
21
|
+
$fetch('https://registry.npmjs.org/@nuxt-themes/alpine/latest').then((release) => {
|
|
22
|
+
if (release.version > version) {
|
|
23
|
+
logger.info(`A new version of Alpine (v${release.version}) is available: https://github.com/nuxt-themes/alpine/releases/latest`)
|
|
24
|
+
}
|
|
25
|
+
}).catch(() => {})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
|
31
|
+
export default defineNuxtConfig({
|
|
32
|
+
app: {
|
|
33
|
+
head: {
|
|
34
|
+
htmlAttrs: {
|
|
35
|
+
lang: 'en'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
extends: [envModules.typography, envModules.elements],
|
|
40
|
+
runtimeConfig: {
|
|
41
|
+
public: {
|
|
42
|
+
FORMSPREE_URL: process.env.FORMSPREE_URL
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
pages: true,
|
|
46
|
+
modules: [
|
|
47
|
+
envModules.tokens,
|
|
48
|
+
envModules.studio,
|
|
49
|
+
'@nuxt/content',
|
|
50
|
+
updateModule as any
|
|
51
|
+
],
|
|
52
|
+
components: [
|
|
53
|
+
{ path: resolve('./components'), global: true },
|
|
54
|
+
{ path: resolve('./components/content'), global: true },
|
|
55
|
+
{ path: resolve('./components/data-entry'), global: true }
|
|
56
|
+
],
|
|
57
|
+
css: [
|
|
58
|
+
resolve('./assets/main.css'),
|
|
59
|
+
],
|
|
60
|
+
colorMode: {
|
|
61
|
+
classSuffix: ''
|
|
62
|
+
},
|
|
63
|
+
pinceau: {
|
|
64
|
+
studio: true
|
|
65
|
+
},
|
|
66
|
+
content: {
|
|
67
|
+
documentDriven: true,
|
|
68
|
+
navigation: {
|
|
69
|
+
fields: ['navTitle']
|
|
70
|
+
},
|
|
71
|
+
highlight: {
|
|
72
|
+
theme: {
|
|
73
|
+
default: 'github-light',
|
|
74
|
+
dark: 'github-dark'
|
|
75
|
+
},
|
|
76
|
+
preload: ['json', 'js', 'ts', 'html', 'css', 'vue', 'diff', 'shell', 'markdown', 'yaml', 'bash', 'ini', 'c', 'cpp']
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
experimental: {
|
|
80
|
+
inlineSSRStyles: false
|
|
81
|
+
},
|
|
82
|
+
typescript: {
|
|
83
|
+
includeWorkspace: true
|
|
84
|
+
},
|
|
85
|
+
nitro: {
|
|
86
|
+
prerender: {
|
|
87
|
+
ignore: ['/__pinceau_tokens_config.json', '/__pinceau_tokens_schema.json']
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
})
|