mktcms 0.2.16 → 0.3.2

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 (26) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +2 -1
  3. package/dist/runtime/app/components/content/editor/{selectFile/index.vue.d.ts → frontmatter/filePicker/modal.d.vue.ts} +3 -2
  4. package/dist/runtime/app/components/content/editor/frontmatter/filePicker/modal.vue +122 -0
  5. package/dist/runtime/app/components/content/editor/{selectFile/index.d.vue.ts → frontmatter/filePicker/modal.vue.d.ts} +3 -2
  6. package/dist/runtime/app/components/content/editor/{selectFile/breadcrumb.d.vue.ts → frontmatter/filePicker/node.d.vue.ts} +5 -2
  7. package/dist/runtime/app/components/content/editor/frontmatter/filePicker/node.vue +145 -0
  8. package/dist/runtime/app/components/content/editor/{selectFile/breadcrumb.vue.d.ts → frontmatter/filePicker/node.vue.d.ts} +5 -2
  9. package/dist/runtime/app/components/content/editor/frontmatter/form.d.vue.ts +1 -2
  10. package/dist/runtime/app/components/content/editor/frontmatter/form.vue +175 -193
  11. package/dist/runtime/app/components/content/editor/frontmatter/form.vue.d.ts +1 -2
  12. package/dist/runtime/app/components/content/editor/frontmatter/input.d.vue.ts +4 -0
  13. package/dist/runtime/app/components/content/editor/frontmatter/input.vue +41 -30
  14. package/dist/runtime/app/components/content/editor/frontmatter/input.vue.d.ts +4 -0
  15. package/dist/runtime/app/components/content/editor/frontmatter/modal.d.vue.ts +1 -0
  16. package/dist/runtime/app/components/content/editor/frontmatter/modal.vue +17 -87
  17. package/dist/runtime/app/components/content/editor/frontmatter/modal.vue.d.ts +1 -0
  18. package/dist/runtime/app/components/content/editor/markdown.vue +3 -1
  19. package/dist/runtime/app/styles/admin.css +1 -1
  20. package/dist/runtime/app/styles/admin.min.css +1 -1
  21. package/dist/runtime/server/api/admin/list.js +13 -5
  22. package/dist/runtime/server/api/admin/md.d.ts +1 -0
  23. package/dist/runtime/server/api/admin/md.js +15 -2
  24. package/package.json +2 -1
  25. package/dist/runtime/app/components/content/editor/selectFile/breadcrumb.vue +0 -51
  26. package/dist/runtime/app/components/content/editor/selectFile/index.vue +0 -89
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mktcms",
3
3
  "configKey": "mktcms",
4
- "version": "0.2.16",
4
+ "version": "0.3.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -32,7 +32,8 @@ const module$1 = defineNuxtModule({
32
32
  mailerTo: "",
33
33
  gitUser: "",
34
34
  gitRepo: "",
35
- gitToken: ""
35
+ gitToken: "",
36
+ frontmatter: _options.frontmatter || {}
36
37
  }));
37
38
  _nuxt.options.runtimeConfig.public.mktcms = defu((_nuxt.options.runtimeConfig.public.mktcms, {
38
39
  siteUrl: "",
@@ -1,11 +1,12 @@
1
1
  type __VLS_Props = {
2
2
  isOpen: boolean;
3
+ uiHint: 'image' | 'pdf' | 'file';
3
4
  };
4
5
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
- select: (filePath: string) => any;
6
+ select: (path: string) => any;
6
7
  close: () => any;
7
8
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
- onSelect?: ((filePath: string) => any) | undefined;
9
+ onSelect?: ((path: string) => any) | undefined;
9
10
  onClose?: (() => any) | undefined;
10
11
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
12
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,122 @@
1
+ <script setup>
2
+ import { computed, watch } from "vue";
3
+ import { useFetch } from "#app";
4
+ import FileIcon from "../../../fileIcon.vue";
5
+ import PickerNode from "./node.vue";
6
+ const props = defineProps({
7
+ isOpen: { type: Boolean, required: true },
8
+ uiHint: { type: String, required: true }
9
+ });
10
+ const emit = defineEmits(["close", "select"]);
11
+ const listQuery = computed(() => ({
12
+ path: "",
13
+ type: props.uiHint
14
+ }));
15
+ const { data: list, pending, refresh } = await useFetch("/api/admin/list", {
16
+ query: listQuery
17
+ });
18
+ watch(() => props.isOpen, (isOpen) => {
19
+ if (isOpen) {
20
+ refresh();
21
+ }
22
+ });
23
+ function fileExtension(filename) {
24
+ const match = filename.match(/\.([^.]+)$/);
25
+ return match && match[1] ? match[1] : "";
26
+ }
27
+ function filenameWithoutExtension(filename) {
28
+ return filename.replace(/\.[^/.]+$/, "");
29
+ }
30
+ function selectFile(path) {
31
+ emit("select", path);
32
+ emit("close");
33
+ }
34
+ const title = computed(() => {
35
+ if (props.uiHint === "image") {
36
+ return "Bild ausw\xE4hlen";
37
+ }
38
+ if (props.uiHint === "pdf") {
39
+ return "PDF ausw\xE4hlen";
40
+ }
41
+ return "Datei ausw\xE4hlen";
42
+ });
43
+ </script>
44
+
45
+ <template>
46
+ <div
47
+ v-if="props.isOpen"
48
+ class="fixed inset-0 bg-black/45 flex items-center justify-center p-4 z-9999"
49
+ role="presentation"
50
+ @click.self="emit('close')"
51
+ >
52
+ <div
53
+ class="w-full max-w-220 bg-white rounded-[10px] border border-black/10 shadow-[0_10px_40px_rgba(0,0,0,0.28)] p-6 flex flex-col gap-3"
54
+ role="dialog"
55
+ aria-modal="true"
56
+ :aria-label="title"
57
+ >
58
+ <div class="flex items-center justify-between gap-2">
59
+ <h2 class="font-bold text-2xl">
60
+ {{ title }}
61
+ </h2>
62
+ <button
63
+ type="button"
64
+ class="button secondary small"
65
+ @click="emit('close')"
66
+ >
67
+ Schließen
68
+ </button>
69
+ </div>
70
+
71
+ <div class="max-h-[70vh] overflow-auto pl-1 pr-3">
72
+ <div
73
+ v-if="pending"
74
+ class="text-sm text-gray-500"
75
+ >
76
+ Laden...
77
+ </div>
78
+
79
+ <div
80
+ v-else
81
+ class="space-y-2"
82
+ >
83
+ <button
84
+ v-for="file in list?.files ?? []"
85
+ :key="file"
86
+ type="button"
87
+ class="w-full button secondary"
88
+ @click="selectFile(file)"
89
+ >
90
+ <FileIcon :file-path="file" />
91
+ <div class="w-full flex text-left">
92
+ {{ filenameWithoutExtension(file) }}
93
+ <span
94
+ v-if="fileExtension(file)"
95
+ class="text-sm text-gray-400 ml-auto"
96
+ >
97
+ .{{ fileExtension(file) }}
98
+ </span>
99
+ </div>
100
+ </button>
101
+
102
+ <PickerNode
103
+ v-for="dir in list?.dirs ?? []"
104
+ :key="dir"
105
+ :path="dir"
106
+ :name="dir"
107
+ :level="0"
108
+ :ui-hint="props.uiHint"
109
+ @select="selectFile"
110
+ />
111
+
112
+ <div
113
+ v-if="(list?.files?.length ?? 0) === 0 && (list?.dirs?.length ?? 0) === 0"
114
+ class="text-sm text-gray-600"
115
+ >
116
+ Keine passenden Dateien gefunden.
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </template>
@@ -1,11 +1,12 @@
1
1
  type __VLS_Props = {
2
2
  isOpen: boolean;
3
+ uiHint: 'image' | 'pdf' | 'file';
3
4
  };
4
5
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
- select: (filePath: string) => any;
6
+ select: (path: string) => any;
6
7
  close: () => any;
7
8
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
- onSelect?: ((filePath: string) => any) | undefined;
9
+ onSelect?: ((path: string) => any) | undefined;
9
10
  onClose?: (() => any) | undefined;
10
11
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
12
  declare const _default: typeof __VLS_export;
@@ -1,10 +1,13 @@
1
1
  type __VLS_Props = {
2
2
  path: string;
3
+ name: string;
4
+ level: number;
5
+ uiHint: 'image' | 'pdf' | 'file';
3
6
  };
4
7
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
- "update-path": (newPathParts: string[]) => any;
8
+ select: (path: string) => any;
6
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
- "onUpdate-path"?: ((newPathParts: string[]) => any) | undefined;
10
+ onSelect?: ((path: string) => any) | undefined;
8
11
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
12
  declare const _default: typeof __VLS_export;
10
13
  export default _default;
@@ -0,0 +1,145 @@
1
+ <script setup>
2
+ import { computed, ref } from "vue";
3
+ import FileIcon from "../../../fileIcon.vue";
4
+ defineOptions({
5
+ name: "PickerNode"
6
+ });
7
+ const props = defineProps({
8
+ path: { type: String, required: true },
9
+ name: { type: String, required: true },
10
+ level: { type: Number, required: true },
11
+ uiHint: { type: String, required: true }
12
+ });
13
+ const emit = defineEmits(["select"]);
14
+ const isExpanded = ref(false);
15
+ const isLoading = ref(false);
16
+ const files = ref([]);
17
+ const dirs = ref([]);
18
+ function filenameWithoutExtension(filename) {
19
+ return filename.replace(/\.[^/.]+$/, "");
20
+ }
21
+ function fileExtension(filename) {
22
+ const match = filename.match(/\.([^.]+)$/);
23
+ return match && match[1] ? match[1] : "";
24
+ }
25
+ function joinPath(basePath, name) {
26
+ return `${basePath}${basePath ? ":" : ""}${name}`;
27
+ }
28
+ async function toggleExpand() {
29
+ isExpanded.value = !isExpanded.value;
30
+ if (isExpanded.value && files.value.length === 0 && dirs.value.length === 0 && !isLoading.value) {
31
+ isLoading.value = true;
32
+ const data = await $fetch("/api/admin/list", {
33
+ query: { path: props.path, type: props.uiHint }
34
+ });
35
+ files.value = data.files;
36
+ dirs.value = data.dirs;
37
+ isLoading.value = false;
38
+ }
39
+ }
40
+ const indentStyle = computed(() => ({
41
+ paddingLeft: `${props.level * 1.5}rem`
42
+ }));
43
+ function selectFile(fileName) {
44
+ emit("select", joinPath(props.path, fileName));
45
+ }
46
+ </script>
47
+
48
+ <template>
49
+ <div>
50
+ <div :style="indentStyle">
51
+ <button
52
+ type="button"
53
+ class="button directory w-full flex items-center text-left"
54
+ @click="toggleExpand"
55
+ >
56
+ <svg
57
+ xmlns="http://www.w3.org/2000/svg"
58
+ fill="none"
59
+ viewBox="0 0 24 24"
60
+ stroke-width="1.5"
61
+ stroke="currentColor"
62
+ class="size-6 opacity-20"
63
+ >
64
+ <path
65
+ stroke-linecap="round"
66
+ stroke-linejoin="round"
67
+ d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 0 0-1.883 2.542l.857 6a2.25 2.25 0 0 0 2.227 1.932H19.05a2.25 2.25 0 0 0 2.227-1.932l.857-6a2.25 2.25 0 0 0-1.883-2.542m-16.5 0V6A2.25 2.25 0 0 1 6 3.75h3.879a1.5 1.5 0 0 1 1.06.44l2.122 2.12a1.5 1.5 0 0 0 1.06.44H18A2.25 2.25 0 0 1 20.25 9v.776"
68
+ />
69
+ </svg>
70
+
71
+ <span>{{ props.name }}</span>
72
+
73
+ <svg
74
+ xmlns="http://www.w3.org/2000/svg"
75
+ fill="none"
76
+ viewBox="0 0 24 24"
77
+ stroke-width="1.5"
78
+ stroke="currentColor"
79
+ class="size-4 ml-auto transition-transform duration-300"
80
+ :class="isExpanded ? 'rotate-90' : ''"
81
+ >
82
+ <path
83
+ stroke-linecap="round"
84
+ stroke-linejoin="round"
85
+ d="m8.25 4.5 7.5 7.5-7.5 7.5"
86
+ />
87
+ </svg>
88
+ </button>
89
+ </div>
90
+
91
+ <div
92
+ class="grid transition-[grid-template-rows] duration-300 ease-in-out"
93
+ :class="isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'"
94
+ >
95
+ <div class="overflow-hidden">
96
+ <div
97
+ v-if="isLoading"
98
+ class="py-2"
99
+ :style="{ paddingLeft: `${(props.level + 1) * 1.5}rem` }"
100
+ >
101
+ <span class="text-sm text-gray-500">Laden...</span>
102
+ </div>
103
+
104
+ <div
105
+ v-else
106
+ class="py-2 space-y-2"
107
+ >
108
+ <div
109
+ v-for="file in files"
110
+ :key="file"
111
+ class="flex"
112
+ :style="{ paddingLeft: `${(props.level + 1) * 1.5}rem` }"
113
+ >
114
+ <button
115
+ type="button"
116
+ class="w-full button secondary"
117
+ @click="selectFile(file)"
118
+ >
119
+ <FileIcon :file-path="joinPath(props.path, file)" />
120
+ <div class="w-full flex text-left">
121
+ {{ filenameWithoutExtension(file) }}
122
+ <span
123
+ v-if="fileExtension(file)"
124
+ class="text-sm text-gray-400 ml-auto"
125
+ >
126
+ .{{ fileExtension(file) }}
127
+ </span>
128
+ </div>
129
+ </button>
130
+ </div>
131
+
132
+ <PickerNode
133
+ v-for="dir in dirs"
134
+ :key="dir"
135
+ :path="joinPath(props.path, dir)"
136
+ :name="dir"
137
+ :level="props.level + 1"
138
+ :ui-hint="props.uiHint"
139
+ @select="emit('select', $event)"
140
+ />
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </template>
@@ -1,10 +1,13 @@
1
1
  type __VLS_Props = {
2
2
  path: string;
3
+ name: string;
4
+ level: number;
5
+ uiHint: 'image' | 'pdf' | 'file';
3
6
  };
4
7
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
5
- "update-path": (newPathParts: string[]) => any;
8
+ select: (path: string) => any;
6
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
- "onUpdate-path"?: ((newPathParts: string[]) => any) | undefined;
10
+ onSelect?: ((path: string) => any) | undefined;
8
11
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
12
  declare const _default: typeof __VLS_export;
10
13
  export default _default;
@@ -1,6 +1,6 @@
1
1
  type __VLS_Props = {
2
- label?: string;
3
2
  depth?: number;
3
+ schema: Record<string, any> | null;
4
4
  };
5
5
  type __VLS_ModelProps = {
6
6
  'frontmatter': any;
@@ -11,7 +11,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
11
11
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
12
12
  "onUpdate:frontmatter"?: ((value: any) => any) | undefined;
13
13
  }>, {
14
- label: string;
15
14
  depth: number;
16
15
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
16
  declare const _default: typeof __VLS_export;