@md-plugins/quasar-app-extension-q-press 0.1.0-beta.11 → 0.1.0-beta.13

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.
Files changed (28) hide show
  1. package/README.md +2 -2
  2. package/dist/templates/init/src/_q-press/components/MarkdownCodepen.vue +67 -11
  3. package/dist/templates/init/src/_q-press/components/MarkdownExample.vue +1 -1
  4. package/dist/templates/init/src/_q-press/components/MarkdownLink.vue +1 -1
  5. package/dist/templates/init/src/_q-press/components/MarkdownTree.vue +1 -1
  6. package/dist/templates/init/src/components/LandingPage/LandingPage.vue +1 -1
  7. package/dist/templates/init/src/markdown/guides/upgrade-guide.md +3 -3
  8. package/dist/templates/init/src/markdown/quasar-app-extensions/qpress/overview.md +1 -1
  9. package/dist/templates/init/src/markdown/quasar-app-extensions/vite-md-plugin-app-ext/overview.md +1 -1
  10. package/dist/templates/init/src/siteConfig/index.ts +2 -1
  11. package/dist/templates/update/src/_q-press/components/MarkdownCodepen.vue +67 -11
  12. package/dist/templates/update/src/_q-press/components/MarkdownExample.vue +1 -1
  13. package/dist/templates/update/src/_q-press/components/MarkdownLink.vue +1 -1
  14. package/dist/templates/update/src/_q-press/components/MarkdownTree.vue +1 -1
  15. package/package.json +16 -16
  16. package/src/templates/init/src/_q-press/components/MarkdownCodepen.vue +67 -11
  17. package/src/templates/init/src/_q-press/components/MarkdownExample.vue +1 -1
  18. package/src/templates/init/src/_q-press/components/MarkdownLink.vue +1 -1
  19. package/src/templates/init/src/_q-press/components/MarkdownTree.vue +1 -1
  20. package/src/templates/init/src/components/LandingPage/LandingPage.vue +1 -1
  21. package/src/templates/init/src/markdown/guides/upgrade-guide.md +3 -3
  22. package/src/templates/init/src/markdown/quasar-app-extensions/qpress/overview.md +1 -1
  23. package/src/templates/init/src/markdown/quasar-app-extensions/vite-md-plugin-app-ext/overview.md +1 -1
  24. package/src/templates/init/src/siteConfig/index.ts +2 -1
  25. package/src/templates/update/src/_q-press/components/MarkdownCodepen.vue +67 -11
  26. package/src/templates/update/src/_q-press/components/MarkdownExample.vue +1 -1
  27. package/src/templates/update/src/_q-press/components/MarkdownLink.vue +1 -1
  28. package/src/templates/update/src/_q-press/components/MarkdownTree.vue +1 -1
package/README.md CHANGED
@@ -4,9 +4,9 @@ The Ultimate Markdown Solution for the Quasar Framework.
4
4
 
5
5
  See the [documentation](https://md-plugins.netlify.app/quasar-app-extensions/qpress/overview) for more information.
6
6
 
7
- > Current beta release: `0.1.0-beta.11`.
7
+ > Current beta release: `0.1.0-beta.13`.
8
8
  >
9
- > Q-Press currently targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29`. TypeScript processing is required.
9
+ > Q-Press currently targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30`. TypeScript processing is required.
10
10
 
11
11
  ## Features
12
12
 
@@ -41,6 +41,26 @@ const defaultJsResources = [
41
41
  `https://cdn.jsdelivr.net/npm/quasar@${Quasar.version}/dist/quasar.umd.prod.js`,
42
42
  ]
43
43
 
44
+ function getAbsolutePublicUrl(path: string) {
45
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`
46
+
47
+ return typeof location === 'undefined' ? normalizedPath : `${location.origin}${normalizedPath}`
48
+ }
49
+
50
+ function rewriteRootRelativeUrls(content: string) {
51
+ return content
52
+ .replace(
53
+ /\b(src|href|poster)=("|')\/(?!\/)([^"']*)\2/g,
54
+ (_match: string, attr: string, quote: string, path: string) =>
55
+ `${attr}=${quote}${getAbsolutePublicUrl(path)}${quote}`,
56
+ )
57
+ .replace(
58
+ /url\(\s*(["']?)\/(?!\/)([^"')]+)\1\s*\)/g,
59
+ (_match: string, quote: string, path: string) =>
60
+ `url(${quote}${getAbsolutePublicUrl(path)}${quote})`,
61
+ )
62
+ }
63
+
44
64
  function indent(code: string, spaces = 2) {
45
65
  const padding = ' '.repeat(spaces)
46
66
  return code
@@ -49,8 +69,8 @@ function indent(code: string, spaces = 2) {
49
69
  .join('\n')
50
70
  }
51
71
 
52
- function getImportNames(content: string, packageName: string) {
53
- const names = new Set<string>()
72
+ function getImportParts(content: string, packageName: string) {
73
+ const parts: { importName: string; bindingName: string }[] = []
54
74
  const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
55
75
  const importRe = new RegExp(
56
76
  `import\\s+(?!type\\b){([^}]*)}\\s+from\\s+['"]${escapedPackageName}['"];?`,
@@ -66,15 +86,32 @@ function getImportNames(content: string, packageName: string) {
66
86
  continue
67
87
  }
68
88
 
69
- const name = rawName.replace(/\s+as\s+/g, ': ')
89
+ const [importName, bindingName = importName] = rawName.split(/\s+as\s+/)
70
90
 
71
- if (name.length > 0) {
72
- names.add(name)
91
+ if (importName !== undefined && importName.length > 0) {
92
+ parts.push({
93
+ importName,
94
+ bindingName,
95
+ })
73
96
  }
74
97
  }
75
98
  }
76
99
 
77
- return [...names]
100
+ return parts
101
+ }
102
+
103
+ function getImportNames(content: string, packageName: string) {
104
+ return [
105
+ ...new Set(
106
+ getImportParts(content, packageName).map(({ importName, bindingName }) =>
107
+ importName === bindingName ? importName : `${importName}: ${bindingName}`,
108
+ ),
109
+ ),
110
+ ]
111
+ }
112
+
113
+ function getImportBindingNames(content: string, packageName: string) {
114
+ return [...new Set(getImportParts(content, packageName).map(({ bindingName }) => bindingName))]
78
115
  }
79
116
 
80
117
  function getGlobalPackageImportLines(content: string) {
@@ -98,6 +135,16 @@ function getGlobalImportLines(content: string) {
98
135
  ].filter((line) => line.length > 0)
99
136
  }
100
137
 
138
+ function getGlobalImportBindingNames(content: string) {
139
+ return [
140
+ ...getImportBindingNames(content, 'vue'),
141
+ ...getImportBindingNames(content, 'quasar'),
142
+ ...(siteConfig.codepen?.globalPackages ?? []).flatMap(({ packageName }: CodepenGlobalPackage) =>
143
+ getImportBindingNames(content, packageName),
144
+ ),
145
+ ]
146
+ }
147
+
101
148
  function stripImports(content: string) {
102
149
  return content
103
150
  .replace(/^\s*import\s+type\s+[\s\S]*?\s+from\s+['"][^'"]+['"];?\s*$/gm, '')
@@ -185,7 +232,9 @@ function createSetupScript(script: string) {
185
232
  const { content } = getScriptBlock(script, true)
186
233
  const globalImports = getGlobalImportLines(content)
187
234
  const setupContent = stripCompilerMacros(stripImports(content))
188
- const returnNames = getSetupReturnNames(setupContent)
235
+ const returnNames = [
236
+ ...new Set([...getGlobalImportBindingNames(content), ...getSetupReturnNames(setupContent)]),
237
+ ]
189
238
  const setupBody = [
190
239
  setupContent.length > 0 ? indent(setupContent, 4) : '',
191
240
  returnNames.length > 0 ? ` return { ${returnNames.join(', ')} }` : '',
@@ -242,7 +291,7 @@ const jsResources = computed(() => {
242
291
  })
243
292
 
244
293
  const css = computed(() => {
245
- return (def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim()
294
+ return rewriteRootRelativeUrls((def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim())
246
295
  })
247
296
 
248
297
  const cssPreprocessor = computed(() => {
@@ -268,13 +317,16 @@ const jsPreProcessor = computed(() => {
268
317
  })
269
318
 
270
319
  const html = computed(() => {
271
- return (def.parts.Template || '')
320
+ const content = (def.parts.Template || '')
272
321
  .replace(/(<template>|<\/template>$)/g, '')
273
322
  .replace(/\n/g, '\n ')
274
323
  .replace(/([\w]+=")([^"]*?)(")/g, function (match, p1, p2, p3) {
275
324
  return p1 + p2.replace(/>/g, '___TEMP_REPLACEMENT___') + p3
276
325
  })
277
- .replace(/<(q-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs, '<$1$2$3></$1>')
326
+ .replace(
327
+ /<([A-Z][\w-]*|[a-z][\w]*-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs,
328
+ '<$1$2$3></$1>',
329
+ )
278
330
  .replace(
279
331
  /(<template[^>]*>)(\s*?(?:[\n\r][\t ]+)?)<(thead|tbody|tfoot)/gs,
280
332
  '$1$2<___PREVENT_TEMPLATE___$3',
@@ -299,6 +351,8 @@ const html = computed(() => {
299
351
  .replace(/___TEMP_REPLACEMENT___/g, '>')
300
352
  .replace(/^\s{2}/gm, '')
301
353
  .trim()
354
+
355
+ return rewriteRootRelativeUrls(content)
302
356
  })
303
357
 
304
358
  const editors = computed(() => {
@@ -310,10 +364,12 @@ const editors = computed(() => {
310
364
  })
311
365
 
312
366
  const computedTitle = computed(() => {
367
+ const titleSuffix = siteConfig.codepen?.titleSuffix ?? `Quasar v${Quasar.version}`
368
+
313
369
  return (
314
370
  (typeof document !== 'undefined' ? document.title.split(' | ')[0] + ': ' : '') +
315
371
  (props.title ? props.title + ' - ' : '') +
316
- `Quasar v${Quasar.version}`
372
+ titleSuffix
317
373
  )
318
374
  })
319
375
 
@@ -96,7 +96,7 @@
96
96
  import { computed, inject, markRaw, ref, reactive, onBeforeUnmount, onMounted } from 'vue'
97
97
  import { openURL } from 'quasar'
98
98
 
99
- import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v6'
99
+ import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v7'
100
100
  // import { mdiCompare } from '@quasar/extras/mdi-v7'
101
101
 
102
102
  import MarkdownCode from './MarkdownCode.vue'
@@ -10,7 +10,7 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  import { computed } from 'vue'
13
- import { mdiLaunch } from '@quasar/extras/mdi-v6'
13
+ import { mdiLaunch } from '@quasar/extras/mdi-v7'
14
14
 
15
15
  const props = defineProps({ to: { type: String, required: true } })
16
16
  const internal = computed(
@@ -35,7 +35,7 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v6'
38
+ import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v7'
39
39
 
40
40
  const props = defineProps({
41
41
  def: {
@@ -113,7 +113,7 @@
113
113
 
114
114
  <script setup lang="ts">
115
115
  import { QIcon } from 'quasar'
116
- import { fabGithub } from '@quasar/extras/fontawesome-v6'
116
+ import { fabGithub } from '@quasar/extras/fontawesome-v7'
117
117
  import { useRouter } from 'vue-router'
118
118
  import siteConfig from '../../siteConfig'
119
119
 
@@ -7,16 +7,16 @@ related:
7
7
  - vite-plugins/vite-md-plugin/overview
8
8
  ---
9
9
 
10
- The `0.1.0` beta line moves MD-Plugins and Q-Press to the Quasar CLI Vite 3 beta toolchain. It is the right version to use when your Quasar application is being upgraded to `@quasar/app-vite` `>=3.0.0-beta.29`.
10
+ The `0.1.0` beta line moves MD-Plugins and Q-Press to the Quasar CLI Vite 3 beta toolchain. It is the right version to use when your Quasar application is being upgraded to `@quasar/app-vite` `>=3.0.0-beta.30`.
11
11
 
12
12
  ::: warning
13
- Q-Press and the Quasar app extensions now target Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29`. They are not intended for Webpack projects or JavaScript-only Quasar projects.
13
+ Q-Press and the Quasar app extensions now target Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30`. They are not intended for Webpack projects or JavaScript-only Quasar projects.
14
14
  :::
15
15
 
16
16
  ## Before You Upgrade
17
17
 
18
18
  - Make sure your app is already on a Quasar Vite setup.
19
- - Upgrade the app to `@quasar/app-vite` `>=3.0.0-beta.29`.
19
+ - Upgrade the app to `@quasar/app-vite` `>=3.0.0-beta.30`.
20
20
  - Use TypeScript in the consuming Quasar project.
21
21
  - Import `defineConfig` in `quasar.config.ts` directly from `@quasar/app-vite`.
22
22
  - Use `/// <reference types="@quasar/app-vite/client" />` in `src/env.d.ts`.
@@ -6,7 +6,7 @@ desc: Q-Press App-Extension for Quasar.
6
6
  The Q-Press App Extension is a powerful tool for Quasar developers that simplifies the integration of Markdown content into Quasar applications. It leverages the capabilities of Vite and various Markdown plugins to transform Markdown files into Vue components, enabling a seamless and efficient workflow for content management.
7
7
 
8
8
  ::: warning
9
- Q-Press is for Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29` at this time. TypeScript processing is also required. Do not use if you are using Webpack or have a JavaScript-only project.
9
+ Q-Press is for Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30` at this time. TypeScript processing is also required. Do not use if you are using Webpack or have a JavaScript-only project.
10
10
  :::
11
11
 
12
12
  ::: tip
@@ -9,7 +9,7 @@ related:
9
9
  The `viteMdPluginAppExt` is a [Quasar App Extension](https://quasar.dev/app-extensions/introduction) that integrates the `viteMdPlugin` into your Quasar project. This extension allows you to use Markdown files as Vue components, enabling a seamless integration of Markdown content into your Quasar application.
10
10
 
11
11
  ::: warning
12
- This app extension targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29`.
12
+ This app extension targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30`.
13
13
  :::
14
14
 
15
15
  ## Key Features
@@ -1,4 +1,4 @@
1
- import { fabGithub, fabXTwitter } from '@quasar/extras/fontawesome-v6'
1
+ import { fabGithub, fabXTwitter } from '@quasar/extras/fontawesome-v7'
2
2
  import { slugify } from '@md-plugins/shared'
3
3
  import { version, productName } from '../../package.json'
4
4
 
@@ -75,6 +75,7 @@ export interface CodepenConfig {
75
75
  jsExternal?: string[]
76
76
  jsSetup?: string
77
77
  jsPreProcessor?: string
78
+ titleSuffix?: string
78
79
  head?: string
79
80
  globalPackages?: {
80
81
  packageName: string
@@ -41,6 +41,26 @@ const defaultJsResources = [
41
41
  `https://cdn.jsdelivr.net/npm/quasar@${Quasar.version}/dist/quasar.umd.prod.js`,
42
42
  ]
43
43
 
44
+ function getAbsolutePublicUrl(path: string) {
45
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`
46
+
47
+ return typeof location === 'undefined' ? normalizedPath : `${location.origin}${normalizedPath}`
48
+ }
49
+
50
+ function rewriteRootRelativeUrls(content: string) {
51
+ return content
52
+ .replace(
53
+ /\b(src|href|poster)=("|')\/(?!\/)([^"']*)\2/g,
54
+ (_match: string, attr: string, quote: string, path: string) =>
55
+ `${attr}=${quote}${getAbsolutePublicUrl(path)}${quote}`,
56
+ )
57
+ .replace(
58
+ /url\(\s*(["']?)\/(?!\/)([^"')]+)\1\s*\)/g,
59
+ (_match: string, quote: string, path: string) =>
60
+ `url(${quote}${getAbsolutePublicUrl(path)}${quote})`,
61
+ )
62
+ }
63
+
44
64
  function indent(code: string, spaces = 2) {
45
65
  const padding = ' '.repeat(spaces)
46
66
  return code
@@ -49,8 +69,8 @@ function indent(code: string, spaces = 2) {
49
69
  .join('\n')
50
70
  }
51
71
 
52
- function getImportNames(content: string, packageName: string) {
53
- const names = new Set<string>()
72
+ function getImportParts(content: string, packageName: string) {
73
+ const parts: { importName: string; bindingName: string }[] = []
54
74
  const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
55
75
  const importRe = new RegExp(
56
76
  `import\\s+(?!type\\b){([^}]*)}\\s+from\\s+['"]${escapedPackageName}['"];?`,
@@ -66,15 +86,32 @@ function getImportNames(content: string, packageName: string) {
66
86
  continue
67
87
  }
68
88
 
69
- const name = rawName.replace(/\s+as\s+/g, ': ')
89
+ const [importName, bindingName = importName] = rawName.split(/\s+as\s+/)
70
90
 
71
- if (name.length > 0) {
72
- names.add(name)
91
+ if (importName !== undefined && importName.length > 0) {
92
+ parts.push({
93
+ importName,
94
+ bindingName,
95
+ })
73
96
  }
74
97
  }
75
98
  }
76
99
 
77
- return [...names]
100
+ return parts
101
+ }
102
+
103
+ function getImportNames(content: string, packageName: string) {
104
+ return [
105
+ ...new Set(
106
+ getImportParts(content, packageName).map(({ importName, bindingName }) =>
107
+ importName === bindingName ? importName : `${importName}: ${bindingName}`,
108
+ ),
109
+ ),
110
+ ]
111
+ }
112
+
113
+ function getImportBindingNames(content: string, packageName: string) {
114
+ return [...new Set(getImportParts(content, packageName).map(({ bindingName }) => bindingName))]
78
115
  }
79
116
 
80
117
  function getGlobalPackageImportLines(content: string) {
@@ -98,6 +135,16 @@ function getGlobalImportLines(content: string) {
98
135
  ].filter((line) => line.length > 0)
99
136
  }
100
137
 
138
+ function getGlobalImportBindingNames(content: string) {
139
+ return [
140
+ ...getImportBindingNames(content, 'vue'),
141
+ ...getImportBindingNames(content, 'quasar'),
142
+ ...(siteConfig.codepen?.globalPackages ?? []).flatMap(({ packageName }: CodepenGlobalPackage) =>
143
+ getImportBindingNames(content, packageName),
144
+ ),
145
+ ]
146
+ }
147
+
101
148
  function stripImports(content: string) {
102
149
  return content
103
150
  .replace(/^\s*import\s+type\s+[\s\S]*?\s+from\s+['"][^'"]+['"];?\s*$/gm, '')
@@ -185,7 +232,9 @@ function createSetupScript(script: string) {
185
232
  const { content } = getScriptBlock(script, true)
186
233
  const globalImports = getGlobalImportLines(content)
187
234
  const setupContent = stripCompilerMacros(stripImports(content))
188
- const returnNames = getSetupReturnNames(setupContent)
235
+ const returnNames = [
236
+ ...new Set([...getGlobalImportBindingNames(content), ...getSetupReturnNames(setupContent)]),
237
+ ]
189
238
  const setupBody = [
190
239
  setupContent.length > 0 ? indent(setupContent, 4) : '',
191
240
  returnNames.length > 0 ? ` return { ${returnNames.join(', ')} }` : '',
@@ -242,7 +291,7 @@ const jsResources = computed(() => {
242
291
  })
243
292
 
244
293
  const css = computed(() => {
245
- return (def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim()
294
+ return rewriteRootRelativeUrls((def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim())
246
295
  })
247
296
 
248
297
  const cssPreprocessor = computed(() => {
@@ -268,13 +317,16 @@ const jsPreProcessor = computed(() => {
268
317
  })
269
318
 
270
319
  const html = computed(() => {
271
- return (def.parts.Template || '')
320
+ const content = (def.parts.Template || '')
272
321
  .replace(/(<template>|<\/template>$)/g, '')
273
322
  .replace(/\n/g, '\n ')
274
323
  .replace(/([\w]+=")([^"]*?)(")/g, function (match, p1, p2, p3) {
275
324
  return p1 + p2.replace(/>/g, '___TEMP_REPLACEMENT___') + p3
276
325
  })
277
- .replace(/<(q-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs, '<$1$2$3></$1>')
326
+ .replace(
327
+ /<([A-Z][\w-]*|[a-z][\w]*-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs,
328
+ '<$1$2$3></$1>',
329
+ )
278
330
  .replace(
279
331
  /(<template[^>]*>)(\s*?(?:[\n\r][\t ]+)?)<(thead|tbody|tfoot)/gs,
280
332
  '$1$2<___PREVENT_TEMPLATE___$3',
@@ -299,6 +351,8 @@ const html = computed(() => {
299
351
  .replace(/___TEMP_REPLACEMENT___/g, '>')
300
352
  .replace(/^\s{2}/gm, '')
301
353
  .trim()
354
+
355
+ return rewriteRootRelativeUrls(content)
302
356
  })
303
357
 
304
358
  const editors = computed(() => {
@@ -310,10 +364,12 @@ const editors = computed(() => {
310
364
  })
311
365
 
312
366
  const computedTitle = computed(() => {
367
+ const titleSuffix = siteConfig.codepen?.titleSuffix ?? `Quasar v${Quasar.version}`
368
+
313
369
  return (
314
370
  (typeof document !== 'undefined' ? document.title.split(' | ')[0] + ': ' : '') +
315
371
  (props.title ? props.title + ' - ' : '') +
316
- `Quasar v${Quasar.version}`
372
+ titleSuffix
317
373
  )
318
374
  })
319
375
 
@@ -96,7 +96,7 @@
96
96
  import { computed, inject, markRaw, ref, reactive, onBeforeUnmount, onMounted } from 'vue'
97
97
  import { openURL } from 'quasar'
98
98
 
99
- import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v6'
99
+ import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v7'
100
100
  // import { mdiCompare } from '@quasar/extras/mdi-v7'
101
101
 
102
102
  import MarkdownCode from './MarkdownCode.vue'
@@ -10,7 +10,7 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  import { computed } from 'vue'
13
- import { mdiLaunch } from '@quasar/extras/mdi-v6'
13
+ import { mdiLaunch } from '@quasar/extras/mdi-v7'
14
14
 
15
15
  const props = defineProps({ to: { type: String, required: true } })
16
16
  const internal = computed(
@@ -35,7 +35,7 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v6'
38
+ import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v7'
39
39
 
40
40
  const props = defineProps({
41
41
  def: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@md-plugins/quasar-app-extension-q-press",
3
- "version": "0.1.0-beta.11",
3
+ "version": "0.1.0-beta.13",
4
4
  "description": "QPress - The Ultimate Markdown Solution for Quasar Framework",
5
5
  "keywords": [
6
6
  "markdown",
@@ -30,27 +30,27 @@
30
30
  "@types/markdown-it": "^14.1.2",
31
31
  "fs-extra": "^11.3.5",
32
32
  "markdown-it": "^14.2.0",
33
- "@md-plugins/md-plugin-blockquote": "0.1.0-beta.11",
34
- "@md-plugins/md-plugin-codeblocks": "0.1.0-beta.11",
35
- "@md-plugins/md-plugin-image": "0.1.0-beta.11",
36
- "@md-plugins/md-plugin-headers": "0.1.0-beta.11",
37
- "@md-plugins/md-plugin-imports": "0.1.0-beta.11",
38
- "@md-plugins/md-plugin-containers": "0.1.0-beta.11",
39
- "@md-plugins/md-plugin-frontmatter": "0.1.0-beta.11",
40
- "@md-plugins/md-plugin-link": "0.1.0-beta.11",
41
- "@md-plugins/md-plugin-table": "0.1.0-beta.11",
42
- "@md-plugins/md-plugin-inlinecode": "0.1.0-beta.11",
43
- "@md-plugins/md-plugin-title": "0.1.0-beta.11",
44
- "@md-plugins/vite-md-plugin": "0.1.0-beta.11",
45
- "@md-plugins/shared": "0.1.0-beta.11"
33
+ "@md-plugins/md-plugin-blockquote": "0.1.0-beta.13",
34
+ "@md-plugins/md-plugin-containers": "0.1.0-beta.13",
35
+ "@md-plugins/md-plugin-headers": "0.1.0-beta.13",
36
+ "@md-plugins/md-plugin-imports": "0.1.0-beta.13",
37
+ "@md-plugins/md-plugin-image": "0.1.0-beta.13",
38
+ "@md-plugins/md-plugin-codeblocks": "0.1.0-beta.13",
39
+ "@md-plugins/md-plugin-frontmatter": "0.1.0-beta.13",
40
+ "@md-plugins/md-plugin-inlinecode": "0.1.0-beta.13",
41
+ "@md-plugins/md-plugin-link": "0.1.0-beta.13",
42
+ "@md-plugins/md-plugin-table": "0.1.0-beta.13",
43
+ "@md-plugins/md-plugin-title": "0.1.0-beta.13",
44
+ "@md-plugins/shared": "0.1.0-beta.13",
45
+ "@md-plugins/vite-md-plugin": "0.1.0-beta.13"
46
46
  },
47
47
  "devDependencies": {
48
- "@quasar/app-vite": "3.0.0-beta.29",
48
+ "@quasar/app-vite": "3.0.0-beta.30",
49
49
  "@types/markdown-it": "^14.1.2",
50
50
  "vite": "^8.0.14"
51
51
  },
52
52
  "peerDependencies": {
53
- "@quasar/app-vite": ">=3.0.0-beta.29",
53
+ "@quasar/app-vite": ">=3.0.0-beta.30",
54
54
  "markdown-it": "^14.2.0"
55
55
  },
56
56
  "engines": {
@@ -41,6 +41,26 @@ const defaultJsResources = [
41
41
  `https://cdn.jsdelivr.net/npm/quasar@${Quasar.version}/dist/quasar.umd.prod.js`,
42
42
  ]
43
43
 
44
+ function getAbsolutePublicUrl(path: string) {
45
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`
46
+
47
+ return typeof location === 'undefined' ? normalizedPath : `${location.origin}${normalizedPath}`
48
+ }
49
+
50
+ function rewriteRootRelativeUrls(content: string) {
51
+ return content
52
+ .replace(
53
+ /\b(src|href|poster)=("|')\/(?!\/)([^"']*)\2/g,
54
+ (_match: string, attr: string, quote: string, path: string) =>
55
+ `${attr}=${quote}${getAbsolutePublicUrl(path)}${quote}`,
56
+ )
57
+ .replace(
58
+ /url\(\s*(["']?)\/(?!\/)([^"')]+)\1\s*\)/g,
59
+ (_match: string, quote: string, path: string) =>
60
+ `url(${quote}${getAbsolutePublicUrl(path)}${quote})`,
61
+ )
62
+ }
63
+
44
64
  function indent(code: string, spaces = 2) {
45
65
  const padding = ' '.repeat(spaces)
46
66
  return code
@@ -49,8 +69,8 @@ function indent(code: string, spaces = 2) {
49
69
  .join('\n')
50
70
  }
51
71
 
52
- function getImportNames(content: string, packageName: string) {
53
- const names = new Set<string>()
72
+ function getImportParts(content: string, packageName: string) {
73
+ const parts: { importName: string; bindingName: string }[] = []
54
74
  const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
55
75
  const importRe = new RegExp(
56
76
  `import\\s+(?!type\\b){([^}]*)}\\s+from\\s+['"]${escapedPackageName}['"];?`,
@@ -66,15 +86,32 @@ function getImportNames(content: string, packageName: string) {
66
86
  continue
67
87
  }
68
88
 
69
- const name = rawName.replace(/\s+as\s+/g, ': ')
89
+ const [importName, bindingName = importName] = rawName.split(/\s+as\s+/)
70
90
 
71
- if (name.length > 0) {
72
- names.add(name)
91
+ if (importName !== undefined && importName.length > 0) {
92
+ parts.push({
93
+ importName,
94
+ bindingName,
95
+ })
73
96
  }
74
97
  }
75
98
  }
76
99
 
77
- return [...names]
100
+ return parts
101
+ }
102
+
103
+ function getImportNames(content: string, packageName: string) {
104
+ return [
105
+ ...new Set(
106
+ getImportParts(content, packageName).map(({ importName, bindingName }) =>
107
+ importName === bindingName ? importName : `${importName}: ${bindingName}`,
108
+ ),
109
+ ),
110
+ ]
111
+ }
112
+
113
+ function getImportBindingNames(content: string, packageName: string) {
114
+ return [...new Set(getImportParts(content, packageName).map(({ bindingName }) => bindingName))]
78
115
  }
79
116
 
80
117
  function getGlobalPackageImportLines(content: string) {
@@ -98,6 +135,16 @@ function getGlobalImportLines(content: string) {
98
135
  ].filter((line) => line.length > 0)
99
136
  }
100
137
 
138
+ function getGlobalImportBindingNames(content: string) {
139
+ return [
140
+ ...getImportBindingNames(content, 'vue'),
141
+ ...getImportBindingNames(content, 'quasar'),
142
+ ...(siteConfig.codepen?.globalPackages ?? []).flatMap(({ packageName }: CodepenGlobalPackage) =>
143
+ getImportBindingNames(content, packageName),
144
+ ),
145
+ ]
146
+ }
147
+
101
148
  function stripImports(content: string) {
102
149
  return content
103
150
  .replace(/^\s*import\s+type\s+[\s\S]*?\s+from\s+['"][^'"]+['"];?\s*$/gm, '')
@@ -185,7 +232,9 @@ function createSetupScript(script: string) {
185
232
  const { content } = getScriptBlock(script, true)
186
233
  const globalImports = getGlobalImportLines(content)
187
234
  const setupContent = stripCompilerMacros(stripImports(content))
188
- const returnNames = getSetupReturnNames(setupContent)
235
+ const returnNames = [
236
+ ...new Set([...getGlobalImportBindingNames(content), ...getSetupReturnNames(setupContent)]),
237
+ ]
189
238
  const setupBody = [
190
239
  setupContent.length > 0 ? indent(setupContent, 4) : '',
191
240
  returnNames.length > 0 ? ` return { ${returnNames.join(', ')} }` : '',
@@ -242,7 +291,7 @@ const jsResources = computed(() => {
242
291
  })
243
292
 
244
293
  const css = computed(() => {
245
- return (def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim()
294
+ return rewriteRootRelativeUrls((def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim())
246
295
  })
247
296
 
248
297
  const cssPreprocessor = computed(() => {
@@ -268,13 +317,16 @@ const jsPreProcessor = computed(() => {
268
317
  })
269
318
 
270
319
  const html = computed(() => {
271
- return (def.parts.Template || '')
320
+ const content = (def.parts.Template || '')
272
321
  .replace(/(<template>|<\/template>$)/g, '')
273
322
  .replace(/\n/g, '\n ')
274
323
  .replace(/([\w]+=")([^"]*?)(")/g, function (match, p1, p2, p3) {
275
324
  return p1 + p2.replace(/>/g, '___TEMP_REPLACEMENT___') + p3
276
325
  })
277
- .replace(/<(q-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs, '<$1$2$3></$1>')
326
+ .replace(
327
+ /<([A-Z][\w-]*|[a-z][\w]*-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs,
328
+ '<$1$2$3></$1>',
329
+ )
278
330
  .replace(
279
331
  /(<template[^>]*>)(\s*?(?:[\n\r][\t ]+)?)<(thead|tbody|tfoot)/gs,
280
332
  '$1$2<___PREVENT_TEMPLATE___$3',
@@ -299,6 +351,8 @@ const html = computed(() => {
299
351
  .replace(/___TEMP_REPLACEMENT___/g, '>')
300
352
  .replace(/^\s{2}/gm, '')
301
353
  .trim()
354
+
355
+ return rewriteRootRelativeUrls(content)
302
356
  })
303
357
 
304
358
  const editors = computed(() => {
@@ -310,10 +364,12 @@ const editors = computed(() => {
310
364
  })
311
365
 
312
366
  const computedTitle = computed(() => {
367
+ const titleSuffix = siteConfig.codepen?.titleSuffix ?? `Quasar v${Quasar.version}`
368
+
313
369
  return (
314
370
  (typeof document !== 'undefined' ? document.title.split(' | ')[0] + ': ' : '') +
315
371
  (props.title ? props.title + ' - ' : '') +
316
- `Quasar v${Quasar.version}`
372
+ titleSuffix
317
373
  )
318
374
  })
319
375
 
@@ -96,7 +96,7 @@
96
96
  import { computed, inject, markRaw, ref, reactive, onBeforeUnmount, onMounted } from 'vue'
97
97
  import { openURL } from 'quasar'
98
98
 
99
- import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v6'
99
+ import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v7'
100
100
  // import { mdiCompare } from '@quasar/extras/mdi-v7'
101
101
 
102
102
  import MarkdownCode from './MarkdownCode.vue'
@@ -10,7 +10,7 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  import { computed } from 'vue'
13
- import { mdiLaunch } from '@quasar/extras/mdi-v6'
13
+ import { mdiLaunch } from '@quasar/extras/mdi-v7'
14
14
 
15
15
  const props = defineProps({ to: { type: String, required: true } })
16
16
  const internal = computed(
@@ -35,7 +35,7 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v6'
38
+ import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v7'
39
39
 
40
40
  const props = defineProps({
41
41
  def: {
@@ -113,7 +113,7 @@
113
113
 
114
114
  <script setup lang="ts">
115
115
  import { QIcon } from 'quasar'
116
- import { fabGithub } from '@quasar/extras/fontawesome-v6'
116
+ import { fabGithub } from '@quasar/extras/fontawesome-v7'
117
117
  import { useRouter } from 'vue-router'
118
118
  import siteConfig from '../../siteConfig'
119
119
 
@@ -7,16 +7,16 @@ related:
7
7
  - vite-plugins/vite-md-plugin/overview
8
8
  ---
9
9
 
10
- The `0.1.0` beta line moves MD-Plugins and Q-Press to the Quasar CLI Vite 3 beta toolchain. It is the right version to use when your Quasar application is being upgraded to `@quasar/app-vite` `>=3.0.0-beta.29`.
10
+ The `0.1.0` beta line moves MD-Plugins and Q-Press to the Quasar CLI Vite 3 beta toolchain. It is the right version to use when your Quasar application is being upgraded to `@quasar/app-vite` `>=3.0.0-beta.30`.
11
11
 
12
12
  ::: warning
13
- Q-Press and the Quasar app extensions now target Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29`. They are not intended for Webpack projects or JavaScript-only Quasar projects.
13
+ Q-Press and the Quasar app extensions now target Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30`. They are not intended for Webpack projects or JavaScript-only Quasar projects.
14
14
  :::
15
15
 
16
16
  ## Before You Upgrade
17
17
 
18
18
  - Make sure your app is already on a Quasar Vite setup.
19
- - Upgrade the app to `@quasar/app-vite` `>=3.0.0-beta.29`.
19
+ - Upgrade the app to `@quasar/app-vite` `>=3.0.0-beta.30`.
20
20
  - Use TypeScript in the consuming Quasar project.
21
21
  - Import `defineConfig` in `quasar.config.ts` directly from `@quasar/app-vite`.
22
22
  - Use `/// <reference types="@quasar/app-vite/client" />` in `src/env.d.ts`.
@@ -6,7 +6,7 @@ desc: Q-Press App-Extension for Quasar.
6
6
  The Q-Press App Extension is a powerful tool for Quasar developers that simplifies the integration of Markdown content into Quasar applications. It leverages the capabilities of Vite and various Markdown plugins to transform Markdown files into Vue components, enabling a seamless and efficient workflow for content management.
7
7
 
8
8
  ::: warning
9
- Q-Press is for Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29` at this time. TypeScript processing is also required. Do not use if you are using Webpack or have a JavaScript-only project.
9
+ Q-Press is for Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30` at this time. TypeScript processing is also required. Do not use if you are using Webpack or have a JavaScript-only project.
10
10
  :::
11
11
 
12
12
  ::: tip
@@ -9,7 +9,7 @@ related:
9
9
  The `viteMdPluginAppExt` is a [Quasar App Extension](https://quasar.dev/app-extensions/introduction) that integrates the `viteMdPlugin` into your Quasar project. This extension allows you to use Markdown files as Vue components, enabling a seamless integration of Markdown content into your Quasar application.
10
10
 
11
11
  ::: warning
12
- This app extension targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.29`.
12
+ This app extension targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.30`.
13
13
  :::
14
14
 
15
15
  ## Key Features
@@ -1,4 +1,4 @@
1
- import { fabGithub, fabXTwitter } from '@quasar/extras/fontawesome-v6'
1
+ import { fabGithub, fabXTwitter } from '@quasar/extras/fontawesome-v7'
2
2
  import { slugify } from '@md-plugins/shared'
3
3
  import { version, productName } from '../../package.json'
4
4
 
@@ -75,6 +75,7 @@ export interface CodepenConfig {
75
75
  jsExternal?: string[]
76
76
  jsSetup?: string
77
77
  jsPreProcessor?: string
78
+ titleSuffix?: string
78
79
  head?: string
79
80
  globalPackages?: {
80
81
  packageName: string
@@ -41,6 +41,26 @@ const defaultJsResources = [
41
41
  `https://cdn.jsdelivr.net/npm/quasar@${Quasar.version}/dist/quasar.umd.prod.js`,
42
42
  ]
43
43
 
44
+ function getAbsolutePublicUrl(path: string) {
45
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`
46
+
47
+ return typeof location === 'undefined' ? normalizedPath : `${location.origin}${normalizedPath}`
48
+ }
49
+
50
+ function rewriteRootRelativeUrls(content: string) {
51
+ return content
52
+ .replace(
53
+ /\b(src|href|poster)=("|')\/(?!\/)([^"']*)\2/g,
54
+ (_match: string, attr: string, quote: string, path: string) =>
55
+ `${attr}=${quote}${getAbsolutePublicUrl(path)}${quote}`,
56
+ )
57
+ .replace(
58
+ /url\(\s*(["']?)\/(?!\/)([^"')]+)\1\s*\)/g,
59
+ (_match: string, quote: string, path: string) =>
60
+ `url(${quote}${getAbsolutePublicUrl(path)}${quote})`,
61
+ )
62
+ }
63
+
44
64
  function indent(code: string, spaces = 2) {
45
65
  const padding = ' '.repeat(spaces)
46
66
  return code
@@ -49,8 +69,8 @@ function indent(code: string, spaces = 2) {
49
69
  .join('\n')
50
70
  }
51
71
 
52
- function getImportNames(content: string, packageName: string) {
53
- const names = new Set<string>()
72
+ function getImportParts(content: string, packageName: string) {
73
+ const parts: { importName: string; bindingName: string }[] = []
54
74
  const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
55
75
  const importRe = new RegExp(
56
76
  `import\\s+(?!type\\b){([^}]*)}\\s+from\\s+['"]${escapedPackageName}['"];?`,
@@ -66,15 +86,32 @@ function getImportNames(content: string, packageName: string) {
66
86
  continue
67
87
  }
68
88
 
69
- const name = rawName.replace(/\s+as\s+/g, ': ')
89
+ const [importName, bindingName = importName] = rawName.split(/\s+as\s+/)
70
90
 
71
- if (name.length > 0) {
72
- names.add(name)
91
+ if (importName !== undefined && importName.length > 0) {
92
+ parts.push({
93
+ importName,
94
+ bindingName,
95
+ })
73
96
  }
74
97
  }
75
98
  }
76
99
 
77
- return [...names]
100
+ return parts
101
+ }
102
+
103
+ function getImportNames(content: string, packageName: string) {
104
+ return [
105
+ ...new Set(
106
+ getImportParts(content, packageName).map(({ importName, bindingName }) =>
107
+ importName === bindingName ? importName : `${importName}: ${bindingName}`,
108
+ ),
109
+ ),
110
+ ]
111
+ }
112
+
113
+ function getImportBindingNames(content: string, packageName: string) {
114
+ return [...new Set(getImportParts(content, packageName).map(({ bindingName }) => bindingName))]
78
115
  }
79
116
 
80
117
  function getGlobalPackageImportLines(content: string) {
@@ -98,6 +135,16 @@ function getGlobalImportLines(content: string) {
98
135
  ].filter((line) => line.length > 0)
99
136
  }
100
137
 
138
+ function getGlobalImportBindingNames(content: string) {
139
+ return [
140
+ ...getImportBindingNames(content, 'vue'),
141
+ ...getImportBindingNames(content, 'quasar'),
142
+ ...(siteConfig.codepen?.globalPackages ?? []).flatMap(({ packageName }: CodepenGlobalPackage) =>
143
+ getImportBindingNames(content, packageName),
144
+ ),
145
+ ]
146
+ }
147
+
101
148
  function stripImports(content: string) {
102
149
  return content
103
150
  .replace(/^\s*import\s+type\s+[\s\S]*?\s+from\s+['"][^'"]+['"];?\s*$/gm, '')
@@ -185,7 +232,9 @@ function createSetupScript(script: string) {
185
232
  const { content } = getScriptBlock(script, true)
186
233
  const globalImports = getGlobalImportLines(content)
187
234
  const setupContent = stripCompilerMacros(stripImports(content))
188
- const returnNames = getSetupReturnNames(setupContent)
235
+ const returnNames = [
236
+ ...new Set([...getGlobalImportBindingNames(content), ...getSetupReturnNames(setupContent)]),
237
+ ]
189
238
  const setupBody = [
190
239
  setupContent.length > 0 ? indent(setupContent, 4) : '',
191
240
  returnNames.length > 0 ? ` return { ${returnNames.join(', ')} }` : '',
@@ -242,7 +291,7 @@ const jsResources = computed(() => {
242
291
  })
243
292
 
244
293
  const css = computed(() => {
245
- return (def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim()
294
+ return rewriteRootRelativeUrls((def.parts.Style || '').replace(/(<style.*?>|<\/style>)/g, '').trim())
246
295
  })
247
296
 
248
297
  const cssPreprocessor = computed(() => {
@@ -268,13 +317,16 @@ const jsPreProcessor = computed(() => {
268
317
  })
269
318
 
270
319
  const html = computed(() => {
271
- return (def.parts.Template || '')
320
+ const content = (def.parts.Template || '')
272
321
  .replace(/(<template>|<\/template>$)/g, '')
273
322
  .replace(/\n/g, '\n ')
274
323
  .replace(/([\w]+=")([^"]*?)(")/g, function (match, p1, p2, p3) {
275
324
  return p1 + p2.replace(/>/g, '___TEMP_REPLACEMENT___') + p3
276
325
  })
277
- .replace(/<(q-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs, '<$1$2$3></$1>')
326
+ .replace(
327
+ /<([A-Z][\w-]*|[a-z][\w]*-[\w-]+|div)([^>]*?)\s*?([\n\r][\t ]+)?\/>/gs,
328
+ '<$1$2$3></$1>',
329
+ )
278
330
  .replace(
279
331
  /(<template[^>]*>)(\s*?(?:[\n\r][\t ]+)?)<(thead|tbody|tfoot)/gs,
280
332
  '$1$2<___PREVENT_TEMPLATE___$3',
@@ -299,6 +351,8 @@ const html = computed(() => {
299
351
  .replace(/___TEMP_REPLACEMENT___/g, '>')
300
352
  .replace(/^\s{2}/gm, '')
301
353
  .trim()
354
+
355
+ return rewriteRootRelativeUrls(content)
302
356
  })
303
357
 
304
358
  const editors = computed(() => {
@@ -310,10 +364,12 @@ const editors = computed(() => {
310
364
  })
311
365
 
312
366
  const computedTitle = computed(() => {
367
+ const titleSuffix = siteConfig.codepen?.titleSuffix ?? `Quasar v${Quasar.version}`
368
+
313
369
  return (
314
370
  (typeof document !== 'undefined' ? document.title.split(' | ')[0] + ': ' : '') +
315
371
  (props.title ? props.title + ' - ' : '') +
316
- `Quasar v${Quasar.version}`
372
+ titleSuffix
317
373
  )
318
374
  })
319
375
 
@@ -96,7 +96,7 @@
96
96
  import { computed, inject, markRaw, ref, reactive, onBeforeUnmount, onMounted } from 'vue'
97
97
  import { openURL } from 'quasar'
98
98
 
99
- import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v6'
99
+ import { fabGithub, fabCodepen } from '@quasar/extras/fontawesome-v7'
100
100
  // import { mdiCompare } from '@quasar/extras/mdi-v7'
101
101
 
102
102
  import MarkdownCode from './MarkdownCode.vue'
@@ -10,7 +10,7 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  import { computed } from 'vue'
13
- import { mdiLaunch } from '@quasar/extras/mdi-v6'
13
+ import { mdiLaunch } from '@quasar/extras/mdi-v7'
14
14
 
15
15
  const props = defineProps({ to: { type: String, required: true } })
16
16
  const internal = computed(
@@ -35,7 +35,7 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v6'
38
+ import { mdiLaunch, mdiInformationOutline } from '@quasar/extras/mdi-v7'
39
39
 
40
40
  const props = defineProps({
41
41
  def: {