@hywax/cms 0.0.5 → 0.0.7
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/.nuxt/cms/editor/callout.ts +21 -0
- package/.nuxt/cms/editor/index.ts +2 -0
- package/.nuxt/cms/editor/uplora-image.ts +5 -0
- package/.nuxt/cms/editor-content-full.ts +6 -0
- package/.nuxt/cms/editor-content-light.ts +6 -0
- package/.nuxt/cms/index.ts +3 -0
- package/.nuxt/cms/input-uplora-image.ts +15 -0
- package/cli/templates.mjs +7 -7
- package/dist/module.d.mts +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +193 -56
- package/dist/runtime/components/ButtonDelete.vue +13 -5
- package/dist/runtime/components/ButtonDelete.vue.d.ts +9 -2
- package/dist/runtime/components/EditorContentFull.vue +53 -0
- package/dist/runtime/components/EditorContentFull.vue.d.ts +20 -0
- package/dist/runtime/components/EditorContentLight.vue +46 -0
- package/dist/runtime/components/EditorContentLight.vue.d.ts +20 -0
- package/dist/runtime/components/InputSlug.vue +6 -2
- package/dist/runtime/components/InputSlug.vue.d.ts +3 -1
- package/dist/runtime/components/InputUploraImage.vue +131 -0
- package/dist/runtime/components/InputUploraImage.vue.d.ts +35 -0
- package/dist/runtime/components/ModalConfirm.vue +14 -8
- package/dist/runtime/components/ModalConfirm.vue.d.ts +8 -2
- package/dist/runtime/components/TablePanel.vue +2 -2
- package/dist/runtime/components/TablePanelColumnSorting.vue +1 -1
- package/dist/runtime/components/UploraImage.vue +2 -2
- package/dist/runtime/components/UploraImage.vue.d.ts +1 -1
- package/dist/runtime/components/prose/UploraImage.vue +1 -1
- package/dist/runtime/composables/useAdmin.d.ts +6 -0
- package/dist/runtime/composables/useAdmin.js +14 -0
- package/dist/runtime/composables/useAsyncHandler.d.ts +12 -0
- package/dist/runtime/composables/useAsyncHandler.js +30 -0
- package/dist/runtime/composables/useDeleteConfirm.js +1 -3
- package/dist/runtime/composables/useUplora.d.ts +20 -0
- package/dist/runtime/composables/useUplora.js +52 -0
- package/dist/runtime/editor/components/BlockMenu.vue +43 -0
- package/dist/runtime/editor/components/BlockMenu.vue.d.ts +2 -0
- package/dist/runtime/editor/components/SlashCommand.vue +92 -0
- package/dist/runtime/editor/components/SlashCommand.vue.d.ts +7 -0
- package/dist/runtime/editor/components/TooltipLink.vue +81 -0
- package/dist/runtime/editor/components/TooltipLink.vue.d.ts +9 -0
- package/dist/runtime/editor/components/TooltipMenu.vue +75 -0
- package/dist/runtime/editor/components/TooltipMenu.vue.d.ts +9 -0
- package/dist/runtime/editor/extensions/callout/CalloutView.vue +85 -0
- package/dist/runtime/editor/extensions/callout/CalloutView.vue.d.ts +7 -0
- package/dist/runtime/editor/extensions/callout/extension.d.ts +13 -0
- package/dist/runtime/editor/extensions/callout/extension.js +48 -0
- package/dist/runtime/editor/extensions/callout/index.d.ts +2 -0
- package/dist/runtime/editor/extensions/callout/index.js +2 -0
- package/dist/runtime/editor/extensions/callout/types.d.ts +3 -0
- package/dist/runtime/editor/extensions/callout/types.js +0 -0
- package/dist/runtime/editor/extensions/index.d.ts +26 -0
- package/dist/runtime/editor/extensions/index.js +85 -0
- package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue +29 -0
- package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue.d.ts +7 -0
- package/dist/runtime/editor/extensions/uplora-image/extension.d.ts +13 -0
- package/dist/runtime/editor/extensions/uplora-image/extension.js +60 -0
- package/dist/runtime/editor/extensions/uplora-image/index.d.ts +2 -0
- package/dist/runtime/editor/extensions/uplora-image/index.js +2 -0
- package/dist/runtime/editor/extensions/uplora-image/types.d.ts +5 -0
- package/dist/runtime/editor/extensions/uplora-image/types.js +0 -0
- package/dist/runtime/index.css +1 -1
- package/dist/runtime/server/api/uplora/[id].delete.d.ts +2 -0
- package/dist/runtime/server/api/uplora/[id].delete.js +4 -0
- package/dist/runtime/server/api/uplora/index.post.d.ts +5 -0
- package/dist/runtime/server/api/uplora/index.post.js +8 -0
- package/dist/runtime/types/index.d.ts +4 -0
- package/dist/runtime/types/index.js +3 -0
- package/dist/runtime/types/tv.d.ts +11 -5
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"slots": {
|
|
3
|
+
"root": "px-4 py-3 text-sm/6 rounded-md border flex gap-2"
|
|
4
|
+
},
|
|
5
|
+
"variants": {
|
|
6
|
+
"type": {
|
|
7
|
+
"caution": {
|
|
8
|
+
"root": "border border-error/25 bg-error/10 text-error-600 dark:text-error-300"
|
|
9
|
+
},
|
|
10
|
+
"note": {
|
|
11
|
+
"root": "border border-info/25 bg-info/10 text-info-600 dark:text-info-300"
|
|
12
|
+
},
|
|
13
|
+
"warning": {
|
|
14
|
+
"root": "border border-warning/25 bg-warning/10 text-warning-600 dark:text-warning-300"
|
|
15
|
+
},
|
|
16
|
+
"tip": {
|
|
17
|
+
"root": "border border-success/25 bg-success/10 text-success-600 dark:text-success-300"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/.nuxt/cms/index.ts
CHANGED
|
@@ -2,11 +2,14 @@ export { default as autocompleteSelect } from './autocomplete-select'
|
|
|
2
2
|
export { default as buttonClear } from './button-clear'
|
|
3
3
|
export { default as buttonCopy } from './button-copy'
|
|
4
4
|
export { default as buttonDelete } from './button-delete'
|
|
5
|
+
export { default as editorContentFull } from './editor-content-full'
|
|
6
|
+
export { default as editorContentLight } from './editor-content-light'
|
|
5
7
|
export { default as formPanel } from './form-panel'
|
|
6
8
|
export { default as formPanelAsideSection } from './form-panel-aside-section'
|
|
7
9
|
export { default as formPanelSection } from './form-panel-section'
|
|
8
10
|
export { default as inputSeo } from './input-seo'
|
|
9
11
|
export { default as inputSlug } from './input-slug'
|
|
12
|
+
export { default as inputUploraImage } from './input-uplora-image'
|
|
10
13
|
export { default as modalConfirm } from './modal-confirm'
|
|
11
14
|
export { default as tableCellPreview } from './table-cell-preview'
|
|
12
15
|
export { default as tableCellSeo } from './table-cell-seo'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"slots": {
|
|
3
|
+
"root": "relative w-full rounded-md overflow-hidden border border-default aspect-3/2 text-sm",
|
|
4
|
+
"image": "",
|
|
5
|
+
"imageActions": "absolute top-4 right-4 flex gap-2",
|
|
6
|
+
"uploader": "flex flex-col items-center justify-center w-full h-full p-4",
|
|
7
|
+
"uploaderPendingIcon": "size-6 animate-spin",
|
|
8
|
+
"uploaderIdleButton": "cursor-pointer bg-muted/50 border border-default border-dashed rounded-md h-full w-full",
|
|
9
|
+
"uploaderIdleIcon": "size-10 text-primary",
|
|
10
|
+
"uploaderIdleText": "mt-2 font-medium",
|
|
11
|
+
"uploaderIdleExtensions": "mt-2 text-xs text-muted uppercase",
|
|
12
|
+
"uploaderErrorText": "text-center font-medium",
|
|
13
|
+
"uploaderErrorActions": "flex gap-2 mt-4"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/cli/templates.mjs
CHANGED
|
@@ -66,16 +66,16 @@ import { describe, expect, it } from 'vitest'
|
|
|
66
66
|
import ${upperName} from '../../../src/runtime/components/${upperName}.vue'
|
|
67
67
|
import ComponentRender from '../../component-render'
|
|
68
68
|
|
|
69
|
-
describe('${upperName}', () => {
|
|
69
|
+
describe('${upperName}.vue', () => {
|
|
70
70
|
it.each([
|
|
71
71
|
// Props
|
|
72
|
-
['
|
|
73
|
-
['
|
|
74
|
-
['
|
|
75
|
-
['
|
|
72
|
+
['base component', { props: {} }],
|
|
73
|
+
['with as', { props: { as: 'section' } }],
|
|
74
|
+
['with class', { props: { class: '' } }],
|
|
75
|
+
['with ui', { props: { ui: {} } }],
|
|
76
76
|
// Slots
|
|
77
|
-
['
|
|
78
|
-
])('
|
|
77
|
+
['with default slot', { slots: { default: () => 'Default slot' } }],
|
|
78
|
+
])('renders %s correctly', async (nameOrHtml: string, options: { props?: ${upperName}Props, slots?: Partial<${upperName}Slots> }) => {
|
|
79
79
|
const html = await ComponentRender(nameOrHtml, options, ${upperName})
|
|
80
80
|
expect(html).toMatchSnapshot()
|
|
81
81
|
})
|
package/dist/module.d.mts
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule
|
|
2
|
-
import { defu } from 'defu';
|
|
1
|
+
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, hasNuxtModule, installModule, addServerHandler, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule } from '@nuxt/kit';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { dirname } from 'pathe';
|
|
3
|
+
import { dirname, join } from 'pathe';
|
|
4
|
+
import { defu } from 'defu';
|
|
5
5
|
import { snakeCase, kebabCase } from 'scule';
|
|
6
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
7
|
|
|
7
8
|
const name = "@hywax/cms";
|
|
8
|
-
const version = "0.0.
|
|
9
|
+
const version = "0.0.7";
|
|
9
10
|
|
|
10
11
|
function createContext(options, nuxt) {
|
|
11
12
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -20,9 +21,7 @@ function createContext(options, nuxt) {
|
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
24
|
+
const defaultCMSConfig = {};
|
|
26
25
|
const defaultModuleOptions = {
|
|
27
26
|
name: "cms",
|
|
28
27
|
prefix: "C",
|
|
@@ -77,6 +76,115 @@ function prepareAutoImports({ resolve, options, nuxt }) {
|
|
|
77
76
|
addServerImportsDir(resolve("./runtime/server/utils"));
|
|
78
77
|
nuxt.options.nitro.alias ||= {};
|
|
79
78
|
nuxt.options.nitro.alias["#cms/http-codes"] = httpCodesPath;
|
|
79
|
+
nuxt.options.alias["#cms"] = resolve("./runtime");
|
|
80
|
+
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, defaultCMSConfig);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function prepareGenerateEnv({ nuxt }) {
|
|
84
|
+
const runtimeConfig = nuxt.options.runtimeConfig;
|
|
85
|
+
if (nuxt.options.dev && !runtimeConfig.uploraApiKey) {
|
|
86
|
+
const envPath = join(nuxt.options.rootDir, ".env");
|
|
87
|
+
const envContent = await readFile(envPath, "utf-8").catch(() => "");
|
|
88
|
+
const envKey = `${runtimeConfig.nitro?.envPrefix || "NUXT_"}UPLORA_API_KEY`;
|
|
89
|
+
if (!envContent.includes(envKey)) {
|
|
90
|
+
await writeFile(
|
|
91
|
+
envPath,
|
|
92
|
+
`${envContent ? `${envContent}
|
|
93
|
+
` : envContent}${envKey}=put-your-api-key-here`,
|
|
94
|
+
"utf-8"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function prepareInstallModules(_context) {
|
|
101
|
+
if (!hasNuxtModule("@nuxt/ui-pro")) {
|
|
102
|
+
await installModule("@nuxt/ui-pro");
|
|
103
|
+
}
|
|
104
|
+
if (!hasNuxtModule("@nuxtjs/mdc")) {
|
|
105
|
+
await installModule("@nuxtjs/mdc");
|
|
106
|
+
}
|
|
107
|
+
if (!hasNuxtModule("@vueuse/nuxt")) {
|
|
108
|
+
await installModule("@vueuse/nuxt");
|
|
109
|
+
}
|
|
110
|
+
if (!hasNuxtModule("nuxt-auth-utils")) {
|
|
111
|
+
await installModule("nuxt-auth-utils");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const icons = {
|
|
116
|
+
edit: "lucide:pencil",
|
|
117
|
+
trash: "lucide:trash-2",
|
|
118
|
+
imageUp: "lucide:image-up",
|
|
119
|
+
arrowDownUp: "lucide:arrow-down-up",
|
|
120
|
+
sortAsc: "lucide:arrow-up-wide-narrow",
|
|
121
|
+
sortDesc: "lucide:arrow-down-wide-narrow",
|
|
122
|
+
columns: "lucide:columns-3-cog",
|
|
123
|
+
filter: "lucide:filter",
|
|
124
|
+
link: "lucide:link-2",
|
|
125
|
+
linkOff: "lucide:link-2-off",
|
|
126
|
+
ellipsisVertical: "lucide:ellipsis-vertical",
|
|
127
|
+
heading2: "lucide:heading-2",
|
|
128
|
+
heading3: "lucide:heading-3",
|
|
129
|
+
heading4: "lucide:heading-4",
|
|
130
|
+
list: "lucide:list",
|
|
131
|
+
listOrdered: "lucide:list-ordered",
|
|
132
|
+
checkSquare: "lucide:check-square",
|
|
133
|
+
image: "lucide:image",
|
|
134
|
+
quote: "lucide:quote",
|
|
135
|
+
code: "lucide:code",
|
|
136
|
+
paragraph: "lucide:paragraph",
|
|
137
|
+
pilcrow: "lucide:pilcrow",
|
|
138
|
+
info: "lucide:info",
|
|
139
|
+
bold: "lucide:bold",
|
|
140
|
+
italic: "lucide:italic",
|
|
141
|
+
underline: "lucide:underline",
|
|
142
|
+
strike: "lucide:strikethrough"
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
function prepareMergeConfigs({ nuxt, options }) {
|
|
146
|
+
nuxt.options.runtimeConfig.public = defu(nuxt.options.runtimeConfig.public || {}, {
|
|
147
|
+
fluxorUrl: options.fluxorUrl,
|
|
148
|
+
version: ""
|
|
149
|
+
});
|
|
150
|
+
nuxt.options.runtimeConfig.nitro ||= {};
|
|
151
|
+
nuxt.options.runtimeConfig.nitro.envPrefix = options.envPrefix;
|
|
152
|
+
nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
|
|
153
|
+
icons
|
|
154
|
+
});
|
|
155
|
+
nuxt.options.ui = defu(nuxt.options.ui || {}, {
|
|
156
|
+
colorMode: true,
|
|
157
|
+
fonts: true
|
|
158
|
+
});
|
|
159
|
+
nuxt.options.colorMode = defu(nuxt.options.colorMode || {}, {
|
|
160
|
+
storageKey: `${options.name}-color-mode`
|
|
161
|
+
});
|
|
162
|
+
nuxt.options.mdc = defu(nuxt.options.mdc || {}, {
|
|
163
|
+
components: {
|
|
164
|
+
map: {
|
|
165
|
+
"uplora-image": "ProseUploraImage"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
nuxt.options.auth = defu(nuxt.options.auth || {}, {
|
|
170
|
+
name: `${options.name}-session`
|
|
171
|
+
});
|
|
172
|
+
nuxt.options.runtimeConfig.uplora = defu(nuxt.options.runtimeConfig.uplora || {}, {
|
|
173
|
+
apiKey: ""
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function prepareServerRoutes({ resolve }) {
|
|
178
|
+
addServerHandler({
|
|
179
|
+
route: "/api/_uplora",
|
|
180
|
+
method: "post",
|
|
181
|
+
handler: resolve("./runtime/server/api/uplora/index.post.ts")
|
|
182
|
+
});
|
|
183
|
+
addServerHandler({
|
|
184
|
+
route: "/api/_uplora/:id",
|
|
185
|
+
method: "delete",
|
|
186
|
+
handler: resolve("./runtime/server/api/uplora/[id].delete.ts")
|
|
187
|
+
});
|
|
80
188
|
}
|
|
81
189
|
|
|
82
190
|
const autocompleteSelect = {
|
|
@@ -103,6 +211,20 @@ const buttonDelete = {
|
|
|
103
211
|
}
|
|
104
212
|
};
|
|
105
213
|
|
|
214
|
+
const editorContentFull = {
|
|
215
|
+
slots: {
|
|
216
|
+
root: "h-full w-full relative",
|
|
217
|
+
editor: "min-h-full w-full focus:outline-none editor-content-full relative"
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const editorContentLight = {
|
|
222
|
+
slots: {
|
|
223
|
+
root: "relative",
|
|
224
|
+
editor: "w-full focus:outline-none editor-content-light relative"
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
106
228
|
const formPanel = {
|
|
107
229
|
slots: {
|
|
108
230
|
root: "",
|
|
@@ -150,6 +272,22 @@ const inputSlug = {
|
|
|
150
272
|
}
|
|
151
273
|
};
|
|
152
274
|
|
|
275
|
+
const inputUploraImage = {
|
|
276
|
+
slots: {
|
|
277
|
+
root: "relative w-full rounded-md overflow-hidden border border-default aspect-3/2 text-sm",
|
|
278
|
+
image: "",
|
|
279
|
+
imageActions: "absolute top-4 right-4 flex gap-2",
|
|
280
|
+
uploader: "flex flex-col items-center justify-center w-full h-full p-4",
|
|
281
|
+
uploaderPendingIcon: "size-6 animate-spin",
|
|
282
|
+
uploaderIdleButton: "cursor-pointer bg-muted/50 border border-default border-dashed rounded-md h-full w-full",
|
|
283
|
+
uploaderIdleIcon: "size-10 text-primary",
|
|
284
|
+
uploaderIdleText: "mt-2 font-medium",
|
|
285
|
+
uploaderIdleExtensions: "mt-2 text-xs text-muted uppercase",
|
|
286
|
+
uploaderErrorText: "text-center font-medium",
|
|
287
|
+
uploaderErrorActions: "flex gap-2 mt-4"
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
153
291
|
const modalConfirm = {
|
|
154
292
|
slots: {
|
|
155
293
|
root: ""
|
|
@@ -205,7 +343,7 @@ const tablePanelFilters = {
|
|
|
205
343
|
}
|
|
206
344
|
};
|
|
207
345
|
|
|
208
|
-
const uploraImage$
|
|
346
|
+
const uploraImage$2 = {
|
|
209
347
|
slots: {
|
|
210
348
|
root: "relative grid grid-cols-[100%] grid-rows-[100%] overflow-hidden",
|
|
211
349
|
lqip: "bg-cover bg-no-repeat bg-center col-[1] row-[1]",
|
|
@@ -220,11 +358,14 @@ const theme = {
|
|
|
220
358
|
buttonClear: buttonClear,
|
|
221
359
|
buttonCopy: buttonCopy,
|
|
222
360
|
buttonDelete: buttonDelete,
|
|
361
|
+
editorContentFull: editorContentFull,
|
|
362
|
+
editorContentLight: editorContentLight,
|
|
223
363
|
formPanel: formPanel,
|
|
224
364
|
formPanelAsideSection: formPanelAsideSection,
|
|
225
365
|
formPanelSection: formPanelSection,
|
|
226
366
|
inputSeo: inputSeo,
|
|
227
367
|
inputSlug: inputSlug,
|
|
368
|
+
inputUploraImage: inputUploraImage,
|
|
228
369
|
modalConfirm: modalConfirm,
|
|
229
370
|
tableCellPreview: tableCellPreview,
|
|
230
371
|
tableCellSeo: tableCellSeo,
|
|
@@ -233,6 +374,40 @@ const theme = {
|
|
|
233
374
|
tablePanelColumnSorting: tablePanelColumnSorting,
|
|
234
375
|
tablePanelColumnVisibility: tablePanelColumnVisibility,
|
|
235
376
|
tablePanelFilters: tablePanelFilters,
|
|
377
|
+
uploraImage: uploraImage$2
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
const callout = {
|
|
381
|
+
slots: {
|
|
382
|
+
root: "px-4 py-3 text-sm/6 rounded-md border flex gap-2"
|
|
383
|
+
},
|
|
384
|
+
variants: {
|
|
385
|
+
type: {
|
|
386
|
+
caution: {
|
|
387
|
+
root: "border border-error/25 bg-error/10 text-error-600 dark:text-error-300"
|
|
388
|
+
},
|
|
389
|
+
note: {
|
|
390
|
+
root: "border border-info/25 bg-info/10 text-info-600 dark:text-info-300"
|
|
391
|
+
},
|
|
392
|
+
warning: {
|
|
393
|
+
root: "border border-warning/25 bg-warning/10 text-warning-600 dark:text-warning-300"
|
|
394
|
+
},
|
|
395
|
+
tip: {
|
|
396
|
+
root: "border border-success/25 bg-success/10 text-success-600 dark:text-success-300"
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const uploraImage$1 = {
|
|
403
|
+
slots: {
|
|
404
|
+
root: ""
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const themeEditor = {
|
|
409
|
+
__proto__: null,
|
|
410
|
+
callout: callout,
|
|
236
411
|
uploraImage: uploraImage$1
|
|
237
412
|
};
|
|
238
413
|
|
|
@@ -284,12 +459,18 @@ function getAppTemplates({ options }) {
|
|
|
284
459
|
}
|
|
285
460
|
}
|
|
286
461
|
writeThemeTemplate(themeProse, "prose");
|
|
462
|
+
writeThemeTemplate(themeEditor, "editor");
|
|
287
463
|
writeThemeTemplate(theme);
|
|
288
464
|
templates.push({
|
|
289
465
|
filename: `cms/prose/index.ts`,
|
|
290
466
|
write: true,
|
|
291
467
|
getContents: () => Object.keys(themeProse).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n")
|
|
292
468
|
});
|
|
469
|
+
templates.push({
|
|
470
|
+
filename: `cms/editor/index.ts`,
|
|
471
|
+
write: true,
|
|
472
|
+
getContents: () => Object.keys(themeEditor).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n")
|
|
473
|
+
});
|
|
293
474
|
templates.push({
|
|
294
475
|
filename: "cms.css",
|
|
295
476
|
write: true,
|
|
@@ -359,14 +540,6 @@ function prepareTemplates(context) {
|
|
|
359
540
|
}
|
|
360
541
|
}
|
|
361
542
|
|
|
362
|
-
const icons = {
|
|
363
|
-
sortAsc: "lucide:arrow-up-wide-narrow",
|
|
364
|
-
sortDesc: "lucide:arrow-down-wide-narrow",
|
|
365
|
-
columns: "lucide:columns-3-cog",
|
|
366
|
-
filter: "lucide:filter",
|
|
367
|
-
link: "lucide:link-2"
|
|
368
|
-
};
|
|
369
|
-
|
|
370
543
|
const module = defineNuxtModule({
|
|
371
544
|
meta: {
|
|
372
545
|
name,
|
|
@@ -376,48 +549,12 @@ const module = defineNuxtModule({
|
|
|
376
549
|
defaults: defaultModuleOptions,
|
|
377
550
|
async setup(options, nuxt) {
|
|
378
551
|
const context = createContext(options, nuxt);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
version: ""
|
|
382
|
-
});
|
|
383
|
-
nuxt.options.runtimeConfig.nitro ||= {};
|
|
384
|
-
nuxt.options.runtimeConfig.nitro.envPrefix = options.envPrefix;
|
|
385
|
-
nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
|
|
386
|
-
icons
|
|
387
|
-
});
|
|
388
|
-
nuxt.options.ui = defu(nuxt.options.ui || {}, {
|
|
389
|
-
colorMode: true,
|
|
390
|
-
fonts: true
|
|
391
|
-
});
|
|
392
|
-
nuxt.options.colorMode = defu(nuxt.options.colorMode || {}, {
|
|
393
|
-
storageKey: `${options.name}-color-mode`
|
|
394
|
-
});
|
|
395
|
-
nuxt.options.mdc = defu(nuxt.options.mdc || {}, {
|
|
396
|
-
components: {
|
|
397
|
-
map: {
|
|
398
|
-
"uplora-image": "ProseUploraImage"
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
nuxt.options.auth = defu(nuxt.options.auth || {}, {
|
|
403
|
-
name: `${options.name}-session`
|
|
404
|
-
});
|
|
405
|
-
if (!hasNuxtModule("@nuxt/ui-pro")) {
|
|
406
|
-
await installModule("@nuxt/ui-pro");
|
|
407
|
-
}
|
|
408
|
-
if (!hasNuxtModule("@nuxtjs/mdc")) {
|
|
409
|
-
await installModule("@nuxtjs/mdc");
|
|
410
|
-
}
|
|
411
|
-
if (!hasNuxtModule("@vueuse/nuxt")) {
|
|
412
|
-
await installModule("@vueuse/nuxt");
|
|
413
|
-
}
|
|
414
|
-
if (!hasNuxtModule("nuxt-auth-utils")) {
|
|
415
|
-
await installModule("nuxt-auth-utils");
|
|
416
|
-
}
|
|
417
|
-
nuxt.options.alias["#cms"] = context.resolve("./runtime");
|
|
418
|
-
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, getDefaultCMSConfig());
|
|
552
|
+
prepareMergeConfigs(context);
|
|
553
|
+
await prepareInstallModules();
|
|
419
554
|
prepareAutoImports(context);
|
|
420
555
|
prepareTemplates(context);
|
|
556
|
+
prepareServerRoutes(context);
|
|
557
|
+
await prepareGenerateEnv(context);
|
|
421
558
|
}
|
|
422
559
|
});
|
|
423
560
|
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
disable-closing-trigger
|
|
8
8
|
>
|
|
9
9
|
<UButton
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
:color="color"
|
|
11
|
+
:variant="variant"
|
|
12
|
+
:size="size"
|
|
13
|
+
:icon="icon"
|
|
13
14
|
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
15
|
+
auto-loading
|
|
14
16
|
@click="handleDeleteClick()"
|
|
15
17
|
/>
|
|
16
18
|
</UTooltip>
|
|
@@ -26,11 +28,15 @@ import ModalConfirm from "./ModalConfirm.vue";
|
|
|
26
28
|
<script setup>
|
|
27
29
|
const props = defineProps({
|
|
28
30
|
modalProps: { type: Object, required: false },
|
|
29
|
-
buttonProps: { type: Object, required: false },
|
|
30
31
|
confirmText: { type: String, required: false },
|
|
32
|
+
confirmLabel: { type: String, required: false, default: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
|
|
31
33
|
title: { type: String, required: false },
|
|
32
34
|
message: { type: String, required: false },
|
|
33
35
|
tooltipText: { type: String, required: false },
|
|
36
|
+
color: { type: null, required: false, default: "error" },
|
|
37
|
+
variant: { type: null, required: false },
|
|
38
|
+
icon: { type: null, required: false },
|
|
39
|
+
size: { type: null, required: false },
|
|
34
40
|
class: { type: null, required: false },
|
|
35
41
|
ui: { type: null, required: false },
|
|
36
42
|
onConfirm: { type: Function, required: false }
|
|
@@ -43,7 +49,9 @@ function handleDeleteClick() {
|
|
|
43
49
|
...props.modalProps,
|
|
44
50
|
title: props.title ?? "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435",
|
|
45
51
|
message: props.message ?? "\u0412\u044B \u0434\u0435\u0438\u0306\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043B\u0438\u0442\u044C?",
|
|
46
|
-
|
|
52
|
+
color: "error",
|
|
53
|
+
variant: props.variant,
|
|
54
|
+
confirmLabel: props.confirmLabel,
|
|
47
55
|
confirmText: props.confirmText,
|
|
48
56
|
onConfirm: props.onConfirm
|
|
49
57
|
});
|
|
@@ -8,11 +8,15 @@ import ModalConfirm from './ModalConfirm.vue';
|
|
|
8
8
|
type ButtonDelete = ComponentConfig<typeof theme, AppConfig, 'buttonDelete'>;
|
|
9
9
|
export interface ButtonDeleteProps extends Pick<ModalConfirmProps, 'onConfirm'> {
|
|
10
10
|
modalProps?: Omit<ModalProps & ComponentProps<typeof ModalConfirm>, 'title' | 'message' | 'onConfirm' | 'confirmButton'>;
|
|
11
|
-
buttonProps?: Omit<ButtonProps, 'color'>;
|
|
12
11
|
confirmText?: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
13
|
title?: string;
|
|
14
14
|
message?: string;
|
|
15
15
|
tooltipText?: string;
|
|
16
|
+
color?: ButtonProps['color'];
|
|
17
|
+
variant?: ButtonProps['variant'];
|
|
18
|
+
icon?: ButtonProps['icon'];
|
|
19
|
+
size?: ButtonProps['size'];
|
|
16
20
|
class?: any;
|
|
17
21
|
ui?: ButtonDelete['slots'];
|
|
18
22
|
}
|
|
@@ -24,5 +28,8 @@ declare const _default: import("vue").DefineComponent<ButtonDeleteProps, {}, {},
|
|
|
24
28
|
}, string, import("vue").PublicProps, Readonly<ButtonDeleteProps> & Readonly<{
|
|
25
29
|
onClose?: (() => any) | undefined;
|
|
26
30
|
onConfirm?: (() => any) | undefined;
|
|
27
|
-
}>, {
|
|
31
|
+
}>, {
|
|
32
|
+
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
33
|
+
confirmLabel: string;
|
|
34
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
35
|
export default _default;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<ProseKit :editor="editor">
|
|
4
|
+
<div ref="editorRef" :class="ui.editor({ class: [props.ui?.editor, 'pl-14'] })" />
|
|
5
|
+
|
|
6
|
+
<BlockMenu />
|
|
7
|
+
<SlashCommand />
|
|
8
|
+
<TooltipMenu />
|
|
9
|
+
</ProseKit>
|
|
10
|
+
</Primitive>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import theme from "#build/cms/editor-content-full";
|
|
15
|
+
import { computed, useAppConfig, useTemplateRef, watchPostEffect } from "#imports";
|
|
16
|
+
import { createEditor } from "prosekit/core";
|
|
17
|
+
import { ProseKit, useDocChange } from "prosekit/vue";
|
|
18
|
+
import { Primitive } from "reka-ui";
|
|
19
|
+
import BlockMenu from "../editor/components/BlockMenu.vue";
|
|
20
|
+
import SlashCommand from "../editor/components/SlashCommand.vue";
|
|
21
|
+
import TooltipMenu from "../editor/components/TooltipMenu.vue";
|
|
22
|
+
import { defineFullExtension } from "../editor/extensions";
|
|
23
|
+
import { docToMarkdown, markdownToDoc } from "../editor/markdown";
|
|
24
|
+
import { tv } from "../utils/tv";
|
|
25
|
+
import "prosekit/basic/style.css";
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<script setup>
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
as: { type: null, required: false },
|
|
31
|
+
class: { type: null, required: false },
|
|
32
|
+
ui: { type: null, required: false }
|
|
33
|
+
});
|
|
34
|
+
const modelValue = defineModel({ type: String, ...{ default: "" } });
|
|
35
|
+
const appConfig = useAppConfig();
|
|
36
|
+
const editor = createEditor({
|
|
37
|
+
extension: defineFullExtension(),
|
|
38
|
+
defaultContent: await markdownToDoc(modelValue.value)
|
|
39
|
+
});
|
|
40
|
+
const editorRef = useTemplateRef("editorRef");
|
|
41
|
+
useDocChange(async () => {
|
|
42
|
+
modelValue.value = await docToMarkdown(editor.getDocJSON());
|
|
43
|
+
}, { editor });
|
|
44
|
+
watchPostEffect((onCleanup) => {
|
|
45
|
+
editor.mount(editorRef.value);
|
|
46
|
+
onCleanup(() => editor.unmount());
|
|
47
|
+
});
|
|
48
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editorContentFull || {} })());
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<style scoped>
|
|
52
|
+
::v-deep(.editor-content-full){line-height:calc(var(--spacing)*7)}::v-deep(.editor-content-full) [data-placeholder]:before{color:var(--ui-text-dimmed);content:attr(data-placeholder);height:0;pointer-events:none;position:absolute}::v-deep(.editor-content-full) h2,::v-deep(.editor-content-full) h3,::v-deep(.editor-content-full) h4{font-weight:600;margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) h2{font-size:var(--text-2xl)}::v-deep(.editor-content-full) h3{font-size:var(--text-xl)}::v-deep(.editor-content-full) h4{font-size:var(--text-lg)}::v-deep(.editor-content-full) blockquote{border-left:4px solid var(--ui-border-accented);margin-block:calc(var(--spacing)*4);padding-inline-start:calc(var(--spacing)*4)}::v-deep(.editor-content-full) [data-node-view-root=true],::v-deep(.editor-content-full)>p{margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) hr{border-block-start:1px solid var(--ui-border);margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-full) pre{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);line-height:calc(var(--spacing)*6);overflow-x:auto;padding-block:calc(var(--spacing)*3);padding-inline:calc(var(--spacing)*4)}::v-deep(.editor-content-full) p>code{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);padding-inline:var(--spacing)}::v-deep(.editor-content-full) a{color:var(--ui-primary);cursor:pointer;text-decoration:underline;-webkit-user-select:all;-moz-user-select:all;user-select:all}
|
|
53
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ComponentConfig } from '../types';
|
|
3
|
+
import theme from '#build/cms/editor-content-full';
|
|
4
|
+
import 'prosekit/basic/style.css';
|
|
5
|
+
type EditorContentFull = ComponentConfig<typeof theme, AppConfig, 'editorContentFull'>;
|
|
6
|
+
export interface EditorContentFullProps {
|
|
7
|
+
as?: any;
|
|
8
|
+
class?: any;
|
|
9
|
+
ui?: EditorContentFull['slots'];
|
|
10
|
+
}
|
|
11
|
+
declare const _default: import("vue").DefineComponent<EditorContentFullProps & {
|
|
12
|
+
modelValue?: string;
|
|
13
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
+
"update:modelValue": (value: string) => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<EditorContentFullProps & {
|
|
16
|
+
modelValue?: string;
|
|
17
|
+
}> & Readonly<{
|
|
18
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<ProseKit :editor="editor">
|
|
4
|
+
<div ref="editorRef" :class="ui.editor({ class: props.ui?.editor })" />
|
|
5
|
+
</ProseKit>
|
|
6
|
+
</Primitive>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import theme from "#build/cms/editor-content-light";
|
|
11
|
+
import { computed, useAppConfig, useTemplateRef, watchPostEffect } from "#imports";
|
|
12
|
+
import { createEditor } from "prosekit/core";
|
|
13
|
+
import { ProseKit, useDocChange } from "prosekit/vue";
|
|
14
|
+
import { Primitive } from "reka-ui";
|
|
15
|
+
import { defineLightExtension } from "../editor/extensions";
|
|
16
|
+
import { docToMarkdown, markdownToDoc } from "../editor/markdown";
|
|
17
|
+
import { tv } from "../utils/tv";
|
|
18
|
+
import "prosekit/basic/style.css";
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<script setup>
|
|
22
|
+
const props = defineProps({
|
|
23
|
+
as: { type: null, required: false },
|
|
24
|
+
class: { type: null, required: false },
|
|
25
|
+
ui: { type: null, required: false }
|
|
26
|
+
});
|
|
27
|
+
const modelValue = defineModel({ type: String, ...{ default: "" } });
|
|
28
|
+
const appConfig = useAppConfig();
|
|
29
|
+
const editor = createEditor({
|
|
30
|
+
extension: defineLightExtension(),
|
|
31
|
+
defaultContent: await markdownToDoc(modelValue.value)
|
|
32
|
+
});
|
|
33
|
+
const editorRef = useTemplateRef("editorRef");
|
|
34
|
+
useDocChange(async () => {
|
|
35
|
+
modelValue.value = await docToMarkdown(editor.getDocJSON());
|
|
36
|
+
}, { editor });
|
|
37
|
+
watchPostEffect((onCleanup) => {
|
|
38
|
+
editor.mount(editorRef.value);
|
|
39
|
+
onCleanup(() => editor.unmount());
|
|
40
|
+
});
|
|
41
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editorContentLight || {} })());
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
::v-deep(.editor-content-light){line-height:calc(var(--spacing)*7)}::v-deep(.editor-content-light) [data-placeholder]:before{color:var(--ui-text-dimmed);content:attr(data-placeholder);height:0;pointer-events:none;position:absolute}::v-deep(.editor-content-light) blockquote{border-left:4px solid var(--ui-border-accented);margin-block:calc(var(--spacing)*4);padding-inline-start:calc(var(--spacing)*4)}::v-deep(.editor-content-light) [data-node-view-root=true],::v-deep(.editor-content-light)>p{margin-block:calc(var(--spacing)*5)}::v-deep(.editor-content-light) pre{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);line-height:calc(var(--spacing)*6);overflow-x:auto;padding-block:calc(var(--spacing)*3);padding-inline:calc(var(--spacing)*4)}::v-deep(.editor-content-light) p>code{background-color:var(--ui-bg-muted);border:1px solid var(--ui-border-muted);border-radius:calc(var(--ui-radius)*1.5);font-family:var(--font-mono);font-size:var(--text-sm);padding-inline:var(--spacing)}::v-deep(.editor-content-light) a{color:var(--ui-primary);cursor:pointer;text-decoration:underline;-webkit-user-select:all;-moz-user-select:all;user-select:all}
|
|
46
|
+
</style>
|