@wordup-md/nuxt-layer-shadcn-unocss 0.2.26 → 0.2.27

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.
@@ -25,7 +25,7 @@ export default defineAppConfig({
25
25
  border: true,
26
26
  },
27
27
  header: {
28
- title: 'WordUp Demo Site',
28
+ title: 'Demo Site',
29
29
  showTitle: true,
30
30
  logo: {
31
31
  light: '/logo.svg',
@@ -0,0 +1,174 @@
1
+ <script lang="ts" setup>
2
+
3
+ </script>
4
+
5
+ <template>
6
+ <div>
7
+ <!-- Begin Brevo Form -->
8
+ <!-- START - We recommend to place the below code in head tag of your website html -->
9
+ <link
10
+ rel="stylesheet"
11
+ href="https://sibforms.com/forms/end-form/build/sib-styles.css"
12
+ >
13
+ <!-- END - We recommend to place the above code in head tag of your website html -->
14
+
15
+ <!-- START - We recommend to place the below code where you want the form in your website html -->
16
+ <div
17
+ class="sib-form"
18
+ style="text-align: center;background-color: #EFF2F7;"
19
+ >
20
+ <div
21
+ id="sib-form-container"
22
+ class="sib-form-container"
23
+ >
24
+ <div
25
+ id="sib-container"
26
+ class="sib-container--large sib-container--vertical"
27
+ style="text-align:center; background-color:rgba(255,255,255,1); max-width:540px; border-radius:3px; border-width:1px; border-color:#C0CCD9; border-style:solid;"
28
+ >
29
+ <form
30
+ id="sib-form"
31
+ method="POST"
32
+ action="https://a2981c76.sibforms.com/serve/MUIFAOcj2LR9UgcDm_uy9p-buw_3lNWLzElF7u1lxKLaOynii2NN5lwwfUBDqtjKiSWLqbYAqvmXXqfz0Z_MbR7cFw58a5KI_qq04ZkvkKo5ecMIh4JTjYDrJKuPS1zvmQ9xSF92-9z-cLsbmH8l0oJq8m3xQ6Wvuus4bk4JrAmOYUdzMBg7RoJmlKY9X8bkWSk1w07sowxfwR6cEw=="
33
+ >
34
+ <div style="padding: 8px 0;">
35
+ <div
36
+ class="sib-form-block"
37
+ style="font-size:32px; text-align:left; font-weight:700; font-family:Helvetica, sans-serif; color:#3C4858; background-color:transparent; text-align:left"
38
+ >
39
+ <p>Newsletter</p>
40
+ </div>
41
+ </div>
42
+ <div style="padding: 8px 0;">
43
+ <div
44
+ class="sib-form-block"
45
+ style="font-size:16px; text-align:left; font-family:Helvetica, sans-serif; color:#3C4858; background-color:transparent; text-align:left"
46
+ >
47
+ <div class="sib-text-form-block">
48
+ <p>Inscrivez-vous à notre newsletter pour suivre nos actualités.</p>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ <div style="padding: 8px 0;">
53
+ <div class="sib-input sib-form-block">
54
+ <div class="form__entry entry_block">
55
+ <div class="form__label-row ">
56
+ <label
57
+ class="entry__label"
58
+ style="font-weight: 700; text-align:left; font-size:16px; text-align:left; font-weight:700; font-family:Helvetica, sans-serif; color:#3c4858;"
59
+ for="EMAIL"
60
+ data-required="*"
61
+ >Veuillez renseigner votre adresse email pour vous inscrire</label>
62
+
63
+ <div class="entry__field">
64
+ <input
65
+ id="EMAIL"
66
+ class="input "
67
+ type="text"
68
+ name="EMAIL"
69
+ autocomplete="off"
70
+ placeholder="EMAIL"
71
+ data-required="true"
72
+ required
73
+ >
74
+ </div>
75
+ </div>
76
+
77
+ <label
78
+ class="entry__error entry__error--primary"
79
+ style="font-size:16px; text-align:left; font-family:Helvetica, sans-serif; color:#661d1d; background-color:#ffeded; border-radius:3px; border-color:#ff4949;"
80
+ />
81
+ <label
82
+ class="entry__specification"
83
+ style="font-size:12px; text-align:left; font-family:Helvetica, sans-serif; color:#8390A4; text-align:left"
84
+ >
85
+ Veuillez renseigner votre adresse email pour vous inscrire. Ex. : abc@xyz.com
86
+ </label>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ <div style="padding: 8px 0;">
91
+ <div
92
+ class="sib-form-block"
93
+ style="text-align: left"
94
+ >
95
+ <button
96
+ class="sib-form-block__button sib-form-block__button-with-loader"
97
+ style="font-size:16px; text-align:left; font-weight:700; font-family:Helvetica, sans-serif; color:#FFFFFF; background-color:#3E4857; border-radius:3px; border-width:0px;"
98
+ form="sib-form"
99
+ type="submit"
100
+ >
101
+ <svg
102
+ class="icon clickable__icon progress-indicator__icon sib-hide-loader-icon"
103
+ viewBox="0 0 512 512"
104
+ style=""
105
+ >
106
+ <path d="M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z" />
107
+ </svg>
108
+ S&#039;INSCRIRE
109
+ </button>
110
+ </div>
111
+ </div>
112
+ <input
113
+ type="text"
114
+ name="email_address_check"
115
+ value=""
116
+ class="input--hidden"
117
+ >
118
+ <input
119
+ type="hidden"
120
+ name="locale"
121
+ value="fr"
122
+ >
123
+ <input
124
+ type="hidden"
125
+ name="html_type"
126
+ value="simple"
127
+ >
128
+ </form>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ <!-- END - We recommend to place the above code where you want the form in your website html -->
133
+ <!-- End Brevo Form -->
134
+ </div>
135
+ </template>
136
+
137
+ <style scoped>
138
+ @font-face {
139
+ font-display: block;
140
+ font-family: Roboto;
141
+ src: url(https://assets.brevo.com/font/Roboto/Latin/normal/normal/7529907e9eaf8ebb5220c5f9850e3811.woff2) format("woff2"), url(https://assets.brevo.com/font/Roboto/Latin/normal/normal/25c678feafdc175a70922a116c9be3e7.woff) format("woff")
142
+ }
143
+
144
+ @font-face {
145
+ font-display: fallback;
146
+ font-family: Roboto;
147
+ font-weight: 600;
148
+ src: url(https://assets.brevo.com/font/Roboto/Latin/medium/normal/6e9caeeafb1f3491be3e32744bc30440.woff2) format("woff2"), url(https://assets.brevo.com/font/Roboto/Latin/medium/normal/71501f0d8d5aa95960f6475d5487d4c2.woff) format("woff")
149
+ }
150
+
151
+ @font-face {
152
+ font-display: fallback;
153
+ font-family: Roboto;
154
+ font-weight: 700;
155
+ src: url(https://assets.brevo.com/font/Roboto/Latin/bold/normal/3ef7cf158f310cf752d5ad08cd0e7e60.woff2) format("woff2"), url(https://assets.brevo.com/font/Roboto/Latin/bold/normal/ece3a1d82f18b60bcce0211725c476aa.woff) format("woff")
156
+ }
157
+
158
+ #sib-container input:-ms-input-placeholder {
159
+ text-align: left;
160
+ font-family: Helvetica, sans-serif;
161
+ color: #c0ccda;
162
+ }
163
+
164
+ #sib-container input::placeholder {
165
+ text-align: left;
166
+ font-family: Helvetica, sans-serif;
167
+ color: #c0ccda;
168
+ }
169
+
170
+ #sib-container a {
171
+ text-decoration: underline;
172
+ color: #2BB2FC;
173
+ }
174
+ </style>
@@ -25,41 +25,41 @@ Add `:` before the key to bind the frontmatter value to the component.\
25
25
  Or use the `{{ $doc.key }}` syntax to bind the value of the frontmatter.
26
26
 
27
27
  ::stack
28
- ::div{class="p-4"}
29
- This is the title from the frontmatter: **Title of the page**.
30
-
31
- ::alert
28
+ :::div{.p-4}
29
+ This is the title from the frontmatter: **Title of the page**.
30
+
31
+ ::::alert
32
32
  ---
33
33
  :type: key
34
34
  ---
35
35
  With the property `:type: key`, it displays a **{{ $doc.key }} alert**.
36
- ::
37
-
38
- Or inline:
39
-
40
- :alert[Title of the page]{:type="key" :icon="icon"}
41
- ::
36
+ ::::
37
+
38
+ Or inline:
39
+
40
+ :alert[Title of the page]{:icon="icon" :type="key"}
41
+ :::
42
42
 
43
- ```mdc
44
- ---
45
- title: Title of the page
46
- icon: lucide:file
47
- key: example
48
- ---
43
+ ```mdc
44
+ ---
45
+ title: Title of the page
46
+ icon: lucide:file
47
+ key: example
48
+ ---
49
49
 
50
- This is the title from the frontmatter: **{{ $doc.title }}**.
50
+ This is the title from the frontmatter: **{{ $doc.title }}**.
51
51
 
52
- ::alert
53
- ---
54
- :type: key
55
- ---
56
- With the property `:type: key`, it displays a **{{ $doc.key }} alert**.
57
- ::
52
+ ::alert
53
+ ---
54
+ :type: key
55
+ ---
56
+ With the property `:type: key`, it displays a **{{ $doc.key }} alert**.
57
+ ::
58
58
 
59
- Or inline:
59
+ Or inline:
60
60
 
61
- :alert[{{ $doc.title }}]{:type="key" :icon="icon"}
62
- ```
61
+ :alert[{{ $doc.title }}]{:type="key" :icon="icon"}
62
+ ```
63
63
  ::
64
64
 
65
65
  ## Available Frontmatter Attributes
@@ -98,80 +98,95 @@ authors:
98
98
  ## Showcases
99
99
 
100
100
  ::tabs{variant="line"}
101
- ::stack{label="badges"}
102
- ![badges-showcase](/front-matter-showcase/badges.png){class="w-full"}
103
- ```yml
104
- badges:
105
- - value: 0.8.10
106
- - value: Source
107
- icon: lucide:code
108
- to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/FileTree.vue
109
- target: _blank
110
- ```
111
- ::
112
-
113
- ::stack{label="authors"}
114
- ![authors-showcase](/front-matter-showcase/authors.png){class="w-full"}
115
- ```yml
116
- authors:
117
- - name: Tony Zhang
118
- username: ZTL-UwU
119
- avatar: https://www.github.com/ZTL-UwU.png
120
- to: https://github.com/ZTL-UwU
121
- target: _blank
122
- ```
123
- ::
124
-
125
- ::stack{label="navBadges"}
126
- ![nav-badges-showcase](/front-matter-showcase/nav-badges.png){class="w-full"}
127
- ```yml
128
- navBadges:
129
- - value: New
130
- type: lime
131
- ```
132
- ::
101
+ :::stack{label="badges"}
102
+ ![badges-showcase](/front-matter-showcase/badges.png){.w-full}
103
+
104
+ ```yml
105
+ badges:
106
+ - value: 0.8.10
107
+ - value: Source
108
+ icon: lucide:code
109
+ to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/FileTree.vue
110
+ target: _blank
111
+ ```
112
+ :::
113
+
114
+ :::stack{label="authors"}
115
+ ![authors-showcase](/front-matter-showcase/authors.png){.w-full}
116
+
117
+ ```yml
118
+ authors:
119
+ - name: Tony Zhang
120
+ username: ZTL-UwU
121
+ avatar: https://www.github.com/ZTL-UwU.png
122
+ to: https://github.com/ZTL-UwU
123
+ target: _blank
124
+ ```
125
+ :::
126
+
127
+ :::stack{label="navBadges"}
128
+ ![nav-badges-showcase](/front-matter-showcase/nav-badges.png){.w-full}
129
+
130
+ ```yml
131
+ navBadges:
132
+ - value: New
133
+ type: lime
134
+ ```
135
+ :::
133
136
  ::
134
137
 
135
138
  ## Parameters
136
139
 
137
140
  ::field-group
138
- ::field{name="title" type="string"}
141
+ :::field{name="title" type="string"}
139
142
  Title of the page. Defaults to the filename.
140
- ::
141
- ::field{name="description" type="string"}
142
- Description of the page. Defaults to the first `<p>`{lang="html"} of the page.
143
- ::
144
- ::field{name="navigation" type="boolean" default-value="true"}
143
+ :::
144
+
145
+ :::field{name="description" type="string"}
146
+ Description of the page. Defaults to the first `<p>` of the page.
147
+ :::
148
+
149
+ :::field{default-value="true" name="navigation" type="boolean"}
145
150
  Define if the page is included in the sidebar. Set it to `false` in `index.md`.
146
- ::
147
- ::field{name="icon" type="string"}
151
+ :::
152
+
153
+ :::field{name="icon" type="string"}
148
154
  The icon shown in the sidebar for the page.
149
- ::
150
- ::field{name="navBadges" type="[]"}
155
+ :::
156
+
157
+ :::field{name="navBadges" type="[]"}
151
158
  A list of badges appended to the end of the sidebar link.
152
- ::
153
- ::field{name="navTruncate" type="boolean" default-value="true"}
159
+ :::
160
+
161
+ :::field{default-value="true" name="navTruncate" type="boolean"}
154
162
  Whether to truncate the sidebar title.
155
- ::
156
- ::field{name="badges" type="[]"}
163
+ :::
164
+
165
+ :::field{name="badges" type="[]"}
157
166
  A list of badges shown at the bottom of page title.
158
- ::
159
- ::field{name="authors" type="[]"}
167
+ :::
168
+
169
+ :::field{name="authors" type="[]"}
160
170
  A list of authors shown at the bottom of page title.
161
- ::
162
- ::field{name="toc" type="boolean" default-value="true"}
171
+ :::
172
+
173
+ :::field{default-value="true" name="toc" type="boolean"}
163
174
  Whether to show the toc section for this page.
164
- ::
165
- ::field{name="aside" type="boolean" default-value="true"}
175
+ :::
176
+
177
+ :::field{default-value="true" name="aside" type="boolean"}
166
178
  Whether to show the aside section for this page.
167
- ::
168
- ::field{name="editLink" type="boolean" default-value="true"}
179
+ :::
180
+
181
+ :::field{default-value="true" name="editLink" type="boolean"}
169
182
  Whether to show the edit link for this page.
170
- ::
171
- ::field{name="prevNext" type="boolean" default-value="true"}
183
+ :::
184
+
185
+ :::field{default-value="true" name="prevNext" type="boolean"}
172
186
  Whether to show the previous & next page buttons.
173
- ::
174
- ::field{name="breadcrumb" type="boolean" default-value="true"}
187
+ :::
188
+
189
+ :::field{default-value="true" name="breadcrumb" type="boolean"}
175
190
  Whether to show the breadcrumb.
176
- ::
191
+ :::
177
192
  ::
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Démo
3
+ description: Démo
4
+ icon: lucide:camera
5
+ key: example
6
+ ---
7
+
8
+ ## Un titre
9
+
@@ -113,3 +113,5 @@ class: wide-content grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 [&>div]
113
113
  :badge[Edge compatible]{size="lg" type="new"}
114
114
  :::
115
115
  ::
116
+
117
+ :brevo
@@ -14,9 +14,9 @@ export default defineNuxtConfig({
14
14
 
15
15
  compatibilityDate: '2025-01-10',
16
16
 
17
- nitro: {
18
- preset: 'vercel',
19
- },
17
+ // nitro: {
18
+ // preset: 'vercel',
19
+ // },
20
20
 
21
21
  // vite: {
22
22
  // server: {
@@ -51,8 +51,25 @@ export default defineNuxtConfig({
51
51
  },
52
52
 
53
53
  unpress: {
54
- repo: 'https://github.com/wordup-md/nuxt-layer-shadcn-unocss',
55
- autoMountIfDevMode: true,
56
- allowMountWithoutLogin: true,
54
+ repo: 'https://gitlab.com/ManUtopiK/nuxt-layer/-/tree/gitlab',
55
+ sources: {
56
+ 'ManUtopiK:nuxt-layer': {
57
+ name: 'ManUtopiK:nuxt-layer',
58
+ driver: 'gitlab',
59
+ bases: {
60
+ gitlab: {
61
+ name: 'gitlab',
62
+ srcDirs: [
63
+ '.playground/content',
64
+ ],
65
+ assetsDirs: [
66
+ '.playground/public',
67
+ ],
68
+ },
69
+ },
70
+ },
71
+ },
72
+ // autoMountIfDevMode: true,
73
+ // allowMountWithoutLogin: true,
57
74
  },
58
75
  })
@@ -38,7 +38,7 @@
38
38
  }
39
39
 
40
40
  & pre {
41
- --at-apply: "p-3 rounded-lg border bg-muted/30! text-card-foreground shadow-sm overflow-x-auto";
41
+ --at-apply: "my-5! p-3 rounded-lg border bg-muted/30! text-card-foreground shadow-sm overflow-x-auto";
42
42
 
43
43
  & code {
44
44
  --at-apply: "bg-transparent p-0 border-none";
@@ -49,7 +49,7 @@
49
49
  --at-apply: "rounded-none border-b-none border-l-none border-r-none shadow-none";
50
50
  }
51
51
  .FRONTMATTER pre {
52
- --at-apply: "rounded-none border-none shadow-none bg-transparent";
52
+ --at-apply: "my-0! rounded-none border-none shadow-none bg-transparent";
53
53
  }
54
54
 
55
55
  & > div {
@@ -1,14 +1,38 @@
1
1
  <template>
2
2
  <div class="group relative">
3
3
  <UiEditorDropdown
4
- v-model="mdcAttrs.type"
5
4
  chevron
6
5
  tooltip="Type"
7
6
  placement="bottom-start"
8
- :items="types"
9
7
  class="absolute left-3 top--2 z-10 opacity-0 border rounded pl-2 pr-1 transition-opacity group-hover:opacity-100 bg-background"
10
8
  >
11
9
  <span class="text-xs font-mono capitalize">{{ model.type }}</span>
10
+ <template #menu>
11
+ <UiEditorMenuItem
12
+ v-for="item of types"
13
+ :key="item"
14
+ :label="item"
15
+ :pressed="mdcAttrs.type === item"
16
+ class="mb-0.5 last:mb-0"
17
+ @click="mdcAttrs.type = item"
18
+ />
19
+ <hr
20
+ v-if="filteredFrontmatter.length > 0"
21
+ class="my-1"
22
+ >
23
+ <UiEditorMenuItem
24
+ v-for="[key, value] of filteredFrontmatter"
25
+ :key="key"
26
+ :label="`${key}: ${value}`"
27
+ :pressed="mdcAttrs.type === `:${key}`"
28
+ class="mb-0.5 last:mb-0 fmkeys"
29
+ @click="mdcAttrs.type = `:${key}`"
30
+ >
31
+ <template #label>
32
+ {{ key }}: <strong>{{ value }}</strong>
33
+ </template>
34
+ </UiEditorMenuItem>
35
+ </template>
12
36
  </UiEditorDropdown>
13
37
 
14
38
  <Alert
@@ -27,10 +51,12 @@
27
51
  import type { VueNodeViewProps } from 'prosekit/vue'
28
52
 
29
53
  const props = defineProps<VueNodeViewProps>()
30
- const { getComponentProps } = useMdcEditor()
54
+ const { getComponentProps, frontmatter } = useMdcEditor()
31
55
 
32
56
  const types = ['default', 'info', 'success', 'warning', 'danger', 'example', 'secondary']
33
57
 
58
+ const filteredFrontmatter = computed(() => Object.entries(frontmatter.value).filter(([key, value]) => types.includes(value as string)))
59
+
34
60
  const { model, mdcAttrs } = getComponentProps(props, {
35
61
  id: {
36
62
  type: String,
@@ -62,3 +88,13 @@ const { model, mdcAttrs } = getComponentProps(props, {
62
88
  },
63
89
  })
64
90
  </script>
91
+
92
+ <style scoped>
93
+ .fmkeys :deep(div) {
94
+ @apply first-letter:lowercase! font-mono;
95
+ }
96
+ :deep(p) {
97
+ margin-top: 0;
98
+ margin-bottom: 0;
99
+ }
100
+ </style>
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <section
3
3
  :ref="props.contentRef"
4
- v-bind="model"
5
4
  />
6
5
  </template>
7
6
 
@@ -9,14 +8,14 @@
9
8
  import type { VueNodeViewProps } from 'prosekit/vue'
10
9
 
11
10
  const props = defineProps<VueNodeViewProps>()
12
- const { getComponentProps } = useMdcEditor()
13
- const { model } = getComponentProps(props, {
14
- id: {
15
- type: String,
16
- },
17
- class: {
18
- type: String,
19
- default: '',
20
- },
21
- })
11
+ // const { getComponentProps } = useMdcEditor()
12
+ // const { model } = getComponentProps(props, {
13
+ // id: {
14
+ // type: String,
15
+ // },
16
+ // class: {
17
+ // type: String,
18
+ // default: '',
19
+ // },
20
+ // })
22
21
  </script>
package/nuxt.config.ts CHANGED
@@ -21,36 +21,36 @@ export default defineNuxtConfig({
21
21
  $env: {
22
22
  development: {
23
23
  modules: [
24
- '@unpress/nuxt-module',
24
+ !process.env.UNPRESS ? '@unpress/nuxt-module' : '../../../unpress/packages/nuxt-module/src/module',
25
25
  ],
26
+
27
+ alias: !process.env.UNPRESS
28
+ ? undefined
29
+ : {
30
+ '@unpress/mdc-editor': r('../../unpress/packages/mdc-editor/src/module'),
31
+ '@unpress/nuxt-module': r('../../unpress/packages/nuxt-module/src/module'),
32
+ },
33
+
34
+ vite: !process.env.UNPRESS
35
+ ? undefined
36
+ : {
37
+ server: {
38
+ fs: {
39
+ allow: [
40
+ // Allow serving files from the project root
41
+ currentDir,
42
+ // Allow serving files from the monorepo root (parent directories)
43
+ resolve(currentDir, '../../..'),
44
+ ],
45
+ },
46
+ },
47
+ },
26
48
  },
27
49
  production: {
28
50
  modules: [
29
51
  '@unpress/nuxt-module',
30
52
  ],
31
53
  },
32
-
33
- unpress: {
34
- modules: [
35
- '../../../unpress/packages/nuxt-module/src/module',
36
- ],
37
- alias: {
38
- '@unpress/mdc-editor': r('../../unpress/packages/mdc-editor/src/module'),
39
- '@unpress/nuxt-module': r('../../unpress/packages/nuxt-module/src/module'),
40
- },
41
- vite: {
42
- server: {
43
- fs: {
44
- allow: [
45
- // Allow serving files from the project root
46
- currentDir,
47
- // Allow serving files from the monorepo root (parent directories)
48
- resolve(currentDir, '../../..'),
49
- ],
50
- },
51
- },
52
- },
53
- },
54
54
  },
55
55
 
56
56
  components: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordup-md/nuxt-layer-shadcn-unocss",
3
3
  "type": "module",
4
- "version": "0.2.26",
4
+ "version": "0.2.27",
5
5
  "author": "Emmanuel Salomon <emmanuel.salomon@gmail.com>",
6
6
  "main": "./nuxt.config.ts",
7
7
  "repository": {
@@ -16,6 +16,20 @@
16
16
  "wordup-md"
17
17
  ],
18
18
  "license": "MIT",
19
+ "scripts": {
20
+ "dev": "nuxt dev .playground",
21
+ "dev:unpress": "UNPRESS=true nuxt dev .playground",
22
+ "dev:root": "nuxt dev",
23
+ "prepare": "npx nuxt prepare .playground",
24
+ "build": "npx nuxt build .playground",
25
+ "generate": "npx nuxt generate .playground",
26
+ "preview": "npx nuxt preview .playground",
27
+ "lint": "eslint .",
28
+ "build:json-doc": "tsx scripts/buildContentDoc-cli.ts",
29
+ "bump": "pnpm build:json-doc && git add public/content-doc.json && bumpp --skip-install --commit --push --tag",
30
+ "release": "pnpm bump && npm publish",
31
+ "clean": "find . -name 'node_modules' -type d -prune -exec rm -rf '{}' + && find . -name '.nuxt' -type d -prune -exec rm -rf '{}' + && find . -name '.output' -type d -prune -exec rm -rf '{}' + && find . -name 'dist' -prune -exec rm -rf '{}' +"
32
+ },
19
33
  "devDependencies": {
20
34
  "@nuxt/eslint": "latest",
21
35
  "@nuxt/kit": "^3.17.2",
@@ -46,7 +60,7 @@
46
60
  "@nuxtjs/i18n": "^9.5.4",
47
61
  "@nuxtjs/robots": "^5.6.0",
48
62
  "@tanstack/vue-table": "^8.21.3",
49
- "@unpress/nuxt-module": "0.1.13-beta.8",
63
+ "@unpress/nuxt-module": "0.1.14-beta.2",
50
64
  "class-variance-authority": "^0.7.1",
51
65
  "clsx": "^2.1.1",
52
66
  "nuxt": "3.17.2",
@@ -55,16 +69,9 @@
55
69
  "tailwind-merge": "^3.2.0"
56
70
  },
57
71
  "packageManager": "pnpm@10.4.1",
58
- "scripts": {
59
- "dev": "nuxi dev .playground",
60
- "dev:root": "nuxi dev",
61
- "build": "npx nuxt build .playground",
62
- "generate": "npx nuxt generate .playground",
63
- "preview": "npx nuxt preview .playground",
64
- "lint": "eslint .",
65
- "build:json-doc": "tsx scripts/buildContentDoc-cli.ts",
66
- "bump": "pnpm build:json-doc && git add public/content-doc.json && bumpp --skip-install --commit --push --tag",
67
- "release": "pnpm bump && npm publish",
68
- "clean": "find . -name 'node_modules' -type d -prune -exec rm -rf '{}' + && find . -name '.nuxt' -type d -prune -exec rm -rf '{}' + && find . -name '.output' -type d -prune -exec rm -rf '{}' + && find . -name 'dist' -prune -exec rm -rf '{}' +"
72
+ "pnpm": {
73
+ "onlyBuiltDependencies": [
74
+ "sharp"
75
+ ]
69
76
  }
70
- }
77
+ }
package/plugins/wordup.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { TextSelection } from 'prosemirror-state'
2
+ import type { Node } from 'prosemirror-model'
3
+
1
4
  export default defineNuxtPlugin((nuxtApp) => {
2
5
  nuxtApp.hook('mdc-editor:config', ({ config, editor }: { config: any, editor: any }) => {
3
6
  config.components.push({
@@ -16,9 +19,127 @@ export default defineNuxtPlugin((nuxtApp) => {
16
19
  transform() {
17
20
  return { type: 'containerComponent', attrs: { componentName: 'alert' } }
18
21
  },
19
- onSelect: () => editor.commands.insertContainerComponent({
20
- name: 'alert',
21
- }),
22
+ onSelect: async () => {
23
+ const nodes = await config.convertMarkdownToNode(`::alert{type="info"}
24
+ {|}
25
+ ::`)
26
+ // console.log('nodes', nodes, editor, editor.commands, editor.schema.nodeFromJSON(nodes))
27
+
28
+ const { schema, view, state } = editor
29
+ const insertPos = state.selection.anchor - 1
30
+
31
+ // Find and replace {|} cursor placeholder with a paragraph node containing empty text
32
+ const findAndReplaceCursor = (obj: Record<string, unknown>, path: number[] = []): number[] | null => {
33
+ if (typeof obj !== 'object' || obj === null) return null
34
+
35
+ // Check for cursor placeholder in content array
36
+ if (Array.isArray(obj.content)) {
37
+ for (let i = 0; i < obj.content.length; i++) {
38
+ const item = obj.content[i] as Record<string, unknown>
39
+ if (item.type === 'text' && item.text === '{|}') {
40
+ return [...path, i]
41
+ }
42
+ const found = findAndReplaceCursor(item, [...path, i])
43
+ if (found) return found
44
+ }
45
+ }
46
+
47
+ // Check text property directly
48
+ if (obj.text === '{|}') {
49
+ return path
50
+ }
51
+
52
+ return null
53
+ }
54
+
55
+ const cursorPath = findAndReplaceCursor(nodes as Record<string, unknown>)
56
+ console.log(cursorPath)
57
+ if (cursorPath) {
58
+ // Replace cursor placeholder with a paragraph node containing empty text
59
+ let current: Record<string, unknown> = nodes as Record<string, unknown>
60
+ for (let i = 0; i < cursorPath.length - 1; i++) {
61
+ const content = current.content as Record<string, unknown>[]
62
+ if (content) {
63
+ current = content[cursorPath[i]] as Record<string, unknown>
64
+ }
65
+ }
66
+
67
+ if (Array.isArray(current.content)) {
68
+ const cursorIndex = cursorPath[cursorPath.length - 1]
69
+ // Replace {|} with a paragraph node containing a text node with a space
70
+ current.content[cursorIndex] = {
71
+ // type: 'paragraph',
72
+ // content: [
73
+ // {
74
+ type: 'text',
75
+ text: '\u200b',
76
+ // },
77
+ // ],
78
+ }
79
+ }
80
+ }
81
+
82
+ const parsedNodes = schema.nodeFromJSON(nodes)
83
+ console.log('parsedNodes', parsedNodes, cursorPath)
84
+
85
+ // Calculate cursor position offset within the parsed nodes structure
86
+ // The path is an array of indices: [0, 1, 2] means content[0].content[1].content[2]
87
+ const calculateCursorOffset = (node: Node, path: number[]): number | null => {
88
+ if (path.length === 0) {
89
+ return 1 // Base case: position 1 is inside the root node
90
+ }
91
+
92
+ let offset = 1 // Start inside the root node (after opening tag)
93
+ let currentNode = node
94
+
95
+ // Traverse the path, summing up node sizes as we go
96
+ for (let i = 0; i < path.length; i++) {
97
+ const pathIndex = path[i]
98
+ const isLastStep = i === path.length - 1
99
+
100
+ if (!currentNode.content || currentNode.content.childCount <= pathIndex) {
101
+ return null // Invalid path
102
+ }
103
+
104
+ // Sum sizes of all nodes before the target index
105
+ for (let j = 0; j < pathIndex; j++) {
106
+ offset += currentNode.content.child(j).nodeSize
107
+ }
108
+
109
+ if (isLastStep) {
110
+ // For the last step, we want the position at the start of the text node
111
+ // The position is after the opening tag of the parent, plus the sum of previous siblings
112
+ return offset + 1
113
+ }
114
+
115
+ // Move into the target child node (+1 to get inside it)
116
+ offset += 1
117
+ currentNode = currentNode.content.child(pathIndex)
118
+ }
119
+
120
+ return offset
121
+ }
122
+
123
+ let cursorOffset: number | null = null
124
+ if (cursorPath) {
125
+ // Calculate the offset from the root of parsedNodes
126
+ cursorOffset = calculateCursorOffset(parsedNodes, cursorPath)
127
+ // console.log('cursorOffset', cursorOffset, 'cursorPath', cursorPath)
128
+ }
129
+
130
+ const tr = state.tr
131
+ tr.insert(insertPos, parsedNodes)
132
+
133
+ // Set cursor position if we calculated the offset
134
+ if (cursorOffset !== null) {
135
+ const cursorPos = insertPos + cursorOffset
136
+ // console.log('Setting cursor at', cursorPos, 'insertPos', insertPos, 'offset', cursorOffset)
137
+ tr.setSelection(TextSelection.create(tr.doc, cursorPos))
138
+ }
139
+
140
+ view.focus()
141
+ return view.dispatch(tr)
142
+ },
22
143
  })
23
144
 
24
145
  config.components.push({
@@ -89,7 +210,7 @@ export default defineNuxtPlugin((nuxtApp) => {
89
210
  // get next html element with js
90
211
  setTimeout(() => {
91
212
  prevNode.node.nextElementSibling?.querySelector('input.INLINE_MENU_LINK_INPUT')?.focus()
92
- }, 100)
213
+ }, 300)
93
214
  // const node = editor.state.doc.nodeAt(nodePos)
94
215
  // if (node && node.type.name === 'read-more') {
95
216
  // const input = node.firstChild?.firstChild?.firstChild as HTMLInputElement
@@ -133,9 +254,24 @@ export default defineNuxtPlugin((nuxtApp) => {
133
254
  transform() {
134
255
  return { type: 'containerComponent', attrs: { componentName: 'steps' } }
135
256
  },
136
- onSelect: () => editor.commands.insertContainerComponent({
137
- name: 'steps',
138
- }),
257
+ // onSelect: () => editor.commands.insertContainerComponent({
258
+ // name: 'steps',
259
+ // }),
260
+ onSelect: async () => {
261
+ const nodes = await config.convertMarkdownToNode(`::steps
262
+ ###
263
+ ::`)
264
+
265
+ const { schema, view, state } = editor
266
+ const parsedNodes = schema.nodeFromJSON(nodes)
267
+ // console.log('parsedNodes', parsedNodes)
268
+
269
+ const tr = state.tr
270
+ const insertPos = state.selection.anchor - 2
271
+ tr.insert(insertPos, parsedNodes)
272
+
273
+ return view.dispatch(tr)
274
+ },
139
275
  })
140
276
 
141
277
  config.components.push({
@@ -26,7 +26,7 @@
26
26
  "title": "Pages",
27
27
  "_id": "content:1.getting-started:2.writing:2.pages.md",
28
28
  "_path": "getting-started/writing/pages",
29
- "content": "\n\n## `^-` Frontmatter\n\nFront-matter is a convention of Markdown-based CMS to provide metadata to documents, like description or title. Remark MDC uses the YAML syntax with `key: value` pairs.\n\nTo define frontmatter, start your document with `---\\n---` section and put your desired data in YAML format within this section.\n\n```md\n---\ntitle: Title of the page\ndescription: meta description of the page\n---\n\n<!-- Content of the page -->\n```\n\nYou can reuse the same frontmatter attributes in the content or in the components props.\\\nAdd `:` before the key to bind the frontmatter value to the component.\\\nOr use the `{{ $doc.key }}` syntax to bind the value of the frontmatter.\n\n::stack\n ::div{class=\"p-4\"}\n This is the title from the frontmatter: **Title of the page**.\n\n ::alert\n ---\n :type: key\n ---\n With the property `:type: key`, it displays a **{{ $doc.key }} alert**.\n ::\n\n Or inline:\n\n :alert[Title of the page]{:type=\"key\" :icon=\"icon\"}\n ::\n\n ```mdc\n ---\n title: Title of the page\n icon: lucide:file\n key: example\n ---\n\n This is the title from the frontmatter: **{{ $doc.title }}**.\n\n ::alert\n ---\n :type: key\n ---\n With the property `:type: key`, it displays a **{{ $doc.key }} alert**.\n ::\n\n Or inline:\n\n :alert[{{ $doc.title }}]{:type=\"key\" :icon=\"icon\"}\n ```\n::\n\n## Available Frontmatter Attributes\n\n```md\n---\ntitle: Front Matter\ndescription: Front matter attributes used in shadcn-docs-nuxt.\nicon: lucide:book-type\n\nnavTruncate: false\nnavBadges:\n - value: New\n type: lime\n\nbadges:\n - value: Docus\n to: https://docus.dev/api/components#alert\n target: _blank\n - value: Source\n icon: lucide:code\n to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/Alert.vue\n target: _blank\n\nauthors:\n - name: Tony Zhang\n username: ZTL-UwU\n avatar: https://www.github.com/ZTL-UwU.png\n to: https://github.com/ZTL-UwU\n target: _blank\n---\n\n<!-- Content of the page -->\n```\n\n## Showcases\n\n::tabs{variant=\"line\"}\n::stack{label=\"badges\"}\n![badges-showcase](/front-matter-showcase/badges.png){class=\"w-full\"}\n```yml\nbadges:\n - value: 0.8.10\n - value: Source\n icon: lucide:code\n to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/FileTree.vue\n target: _blank\n```\n::\n\n::stack{label=\"authors\"}\n![authors-showcase](/front-matter-showcase/authors.png){class=\"w-full\"}\n```yml\nauthors:\n - name: Tony Zhang\n username: ZTL-UwU\n avatar: https://www.github.com/ZTL-UwU.png\n to: https://github.com/ZTL-UwU\n target: _blank\n```\n::\n\n::stack{label=\"navBadges\"}\n![nav-badges-showcase](/front-matter-showcase/nav-badges.png){class=\"w-full\"}\n```yml\nnavBadges:\n - value: New\n type: lime\n```\n::\n::\n\n## Parameters\n\n::field-group\n ::field{name=\"title\" type=\"string\"}\n Title of the page. Defaults to the filename.\n ::\n ::field{name=\"description\" type=\"string\"}\n Description of the page. Defaults to the first `<p>`{lang=\"html\"} of the page.\n ::\n ::field{name=\"navigation\" type=\"boolean\" default-value=\"true\"}\n Define if the page is included in the sidebar. Set it to `false` in `index.md`.\n ::\n ::field{name=\"icon\" type=\"string\"}\n The icon shown in the sidebar for the page.\n ::\n ::field{name=\"navBadges\" type=\"[]\"}\n A list of badges appended to the end of the sidebar link.\n ::\n ::field{name=\"navTruncate\" type=\"boolean\" default-value=\"true\"}\n Whether to truncate the sidebar title.\n ::\n ::field{name=\"badges\" type=\"[]\"}\n A list of badges shown at the bottom of page title.\n ::\n ::field{name=\"authors\" type=\"[]\"}\n A list of authors shown at the bottom of page title.\n ::\n ::field{name=\"toc\" type=\"boolean\" default-value=\"true\"}\n Whether to show the toc section for this page.\n ::\n ::field{name=\"aside\" type=\"boolean\" default-value=\"true\"}\n Whether to show the aside section for this page.\n ::\n ::field{name=\"editLink\" type=\"boolean\" default-value=\"true\"}\n Whether to show the edit link for this page.\n ::\n ::field{name=\"prevNext\" type=\"boolean\" default-value=\"true\"}\n Whether to show the previous & next page buttons.\n ::\n ::field{name=\"breadcrumb\" type=\"boolean\" default-value=\"true\"}\n Whether to show the breadcrumb.\n ::\n::\n",
29
+ "content": "\n\n## `^-` Frontmatter\n\nFront-matter is a convention of Markdown-based CMS to provide metadata to documents, like description or title. Remark MDC uses the YAML syntax with `key: value` pairs.\n\nTo define frontmatter, start your document with `---\\n---` section and put your desired data in YAML format within this section.\n\n```md\n---\ntitle: Title of the page\ndescription: meta description of the page\n---\n\n<!-- Content of the page -->\n```\n\nYou can reuse the same frontmatter attributes in the content or in the components props.\\\nAdd `:` before the key to bind the frontmatter value to the component.\\\nOr use the `{{ $doc.key }}` syntax to bind the value of the frontmatter.\n\n::stack\n :::div{.p-4}\n This is the title from the frontmatter: **Title of the page**.\n \n ::::alert\n ---\n :type: key\n ---\n With the property `:type: key`, it displays a **{{ $doc.key }} alert**.\n ::::\n \n Or inline:\n \n :alert[Title of the page]{:icon=\"icon\" :type=\"key\"}\n :::\n\n```mdc\n---\ntitle: Title of the page\nicon: lucide:file\nkey: example\n---\n\nThis is the title from the frontmatter: **{{ $doc.title }}**.\n\n::alert\n---\n:type: key\n---\nWith the property `:type: key`, it displays a **{{ $doc.key }} alert**.\n::\n\nOr inline:\n\n:alert[{{ $doc.title }}]{:type=\"key\" :icon=\"icon\"}\n```\n::\n\n## Available Frontmatter Attributes\n\n```md\n---\ntitle: Front Matter\ndescription: Front matter attributes used in shadcn-docs-nuxt.\nicon: lucide:book-type\n\nnavTruncate: false\nnavBadges:\n - value: New\n type: lime\n\nbadges:\n - value: Docus\n to: https://docus.dev/api/components#alert\n target: _blank\n - value: Source\n icon: lucide:code\n to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/Alert.vue\n target: _blank\n\nauthors:\n - name: Tony Zhang\n username: ZTL-UwU\n avatar: https://www.github.com/ZTL-UwU.png\n to: https://github.com/ZTL-UwU\n target: _blank\n---\n\n<!-- Content of the page -->\n```\n\n## Showcases\n\n::tabs{variant=\"line\"}\n :::stack{label=\"badges\"}\n ![badges-showcase](/front-matter-showcase/badges.png){.w-full}\n \n ```yml\n badges:\n - value: 0.8.10\n - value: Source\n icon: lucide:code\n to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/FileTree.vue\n target: _blank\n ```\n :::\n\n :::stack{label=\"authors\"}\n ![authors-showcase](/front-matter-showcase/authors.png){.w-full}\n \n ```yml\n authors:\n - name: Tony Zhang\n username: ZTL-UwU\n avatar: https://www.github.com/ZTL-UwU.png\n to: https://github.com/ZTL-UwU\n target: _blank\n ```\n :::\n\n :::stack{label=\"navBadges\"}\n ![nav-badges-showcase](/front-matter-showcase/nav-badges.png){.w-full}\n \n ```yml\n navBadges:\n - value: New\n type: lime\n ```\n :::\n::\n\n## Parameters\n\n::field-group\n :::field{name=\"title\" type=\"string\"}\n Title of the page. Defaults to the filename.\n :::\n\n :::field{name=\"description\" type=\"string\"}\n Description of the page. Defaults to the first `<p>` of the page.\n :::\n\n :::field{default-value=\"true\" name=\"navigation\" type=\"boolean\"}\n Define if the page is included in the sidebar. Set it to `false` in `index.md`.\n :::\n\n :::field{name=\"icon\" type=\"string\"}\n The icon shown in the sidebar for the page.\n :::\n\n :::field{name=\"navBadges\" type=\"[]\"}\n A list of badges appended to the end of the sidebar link.\n :::\n\n :::field{default-value=\"true\" name=\"navTruncate\" type=\"boolean\"}\n Whether to truncate the sidebar title.\n :::\n\n :::field{name=\"badges\" type=\"[]\"}\n A list of badges shown at the bottom of page title.\n :::\n\n :::field{name=\"authors\" type=\"[]\"}\n A list of authors shown at the bottom of page title.\n :::\n\n :::field{default-value=\"true\" name=\"toc\" type=\"boolean\"}\n Whether to show the toc section for this page.\n :::\n\n :::field{default-value=\"true\" name=\"aside\" type=\"boolean\"}\n Whether to show the aside section for this page.\n :::\n\n :::field{default-value=\"true\" name=\"editLink\" type=\"boolean\"}\n Whether to show the edit link for this page.\n :::\n\n :::field{default-value=\"true\" name=\"prevNext\" type=\"boolean\"}\n Whether to show the previous & next page buttons.\n :::\n\n :::field{default-value=\"true\" name=\"breadcrumb\" type=\"boolean\"}\n Whether to show the breadcrumb.\n :::\n::\n",
30
30
  "description": "Front matter attributes.",
31
31
  "icon": "lucide:file",
32
32
  "key": "example"
@@ -800,6 +800,15 @@
800
800
  "navigation.redirect": "/development/configuration",
801
801
  "_path": "development"
802
802
  },
803
+ {
804
+ "title": "Démo",
805
+ "_id": "content:demo.md",
806
+ "_path": "demo",
807
+ "content": "\n\n## Un titre\n\n",
808
+ "description": "Démo",
809
+ "icon": "lucide:camera",
810
+ "key": "example"
811
+ },
803
812
  {
804
813
  "title": "Layout",
805
814
  "_id": "content:layout.md",