New post editor basis

This commit is contained in:
LittleSheep 2024-03-02 21:40:09 +08:00
parent 3ae72cd9e0
commit e0bb05bee8
9 changed files with 105 additions and 7 deletions

View File

@ -16,6 +16,8 @@
"@fontsource/roboto": "^5.0.8", "@fontsource/roboto": "^5.0.8",
"@mdi/font": "^7.4.47", "@mdi/font": "^7.4.47",
"@unocss/reset": "^0.58.5", "@unocss/reset": "^0.58.5",
"dompurify": "^3.0.9",
"marked": "^12.0.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"universal-cookie": "^7.1.0", "universal-cookie": "^7.1.0",
"unocss": "^0.58.5", "unocss": "^0.58.5",
@ -26,7 +28,9 @@
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.3", "@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node20": "^20.1.2", "@tsconfig/node20": "^20.1.2",
"@types/dompurify": "^3.0.5",
"@types/node": "^20.11.10", "@types/node": "^20.11.10",
"@unocss/preset-typography": "^0.58.5",
"@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/eslint-config-prettier": "^8.0.0", "@vue/eslint-config-prettier": "^8.0.0",

View File

@ -13,7 +13,7 @@
<div> <div>
<div class="font-bold">{{ props.item?.author.nick }}</div> <div class="font-bold">{{ props.item?.author.nick }}</div>
{{ props.item?.content }} <div class="prose prose-post" v-html="parseContent(props.item.content)"></div>
</div> </div>
</div> </div>
</template> </template>
@ -21,11 +21,24 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import dompurify from "dompurify";
import { parse } from "marked";
const props = defineProps<{ item: any }>(); const props = defineProps<{ item: any }>();
function parseContent(src: string): string {
return dompurify().sanitize(parse(src) as string);
}
</script> </script>
<style scoped> <style scoped>
.rounded-card { .rounded-card {
border-radius: 8px; border-radius: 8px;
} }
</style>
<style>
.prose.prose-post, p {
margin: 0 !important;
}
</style> </style>

View File

@ -5,7 +5,7 @@
</div> </div>
<v-infinite-scroll :items="props.posts" :onLoad="props.loader"> <v-infinite-scroll :items="props.posts" :onLoad="props.loader">
<template v-for="(item, index) in props.posts" :key="item"> <template v-for="item in props.posts" :key="item">
<div class="mb-3 px-1"> <div class="mb-3 px-1">
<post-item :item="item" /> <post-item :item="item" />
</div> </div>

View File

@ -0,0 +1,47 @@
<template>
<v-dialog v-model="editor.show" class="max-w-[540px]">
<v-card title="New post">
<v-form>
<v-card-text>
<v-textarea
required
hide-details
variant="outlined"
label="What's happened?!"
/>
<div class="flex mt-1">
<v-tooltip text="Planned publish" location="start">
<template #activator="{ props }">
<v-btn v-bind="props" type="button" variant="text" icon="mdi-calendar" size="small" />
</template>
</v-tooltip>
<v-tooltip text="Categories" location="start">
<template #activator="{ props }">
<v-btn v-bind="props" type="button" variant="text" icon="mdi-shape" size="small" />
</template>
</v-tooltip>
<v-tooltip text="Media" location="start">
<template #activator="{ props }">
<v-btn v-bind="props" type="button" variant="text" icon="mdi-camera" size="small" />
</template>
</v-tooltip>
</div>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn type="reset" color="grey" @click="editor.show = false">Cancel</v-btn>
<v-btn type="submit" @click.prevent>Publish</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import { useEditor } from "@/stores/editor";
const editor = useEditor();
</script>

View File

@ -25,11 +25,25 @@
<v-main> <v-main>
<router-view /> <router-view />
</v-main> </v-main>
<v-fab
class="editor-fab"
icon="mdi-pencil"
color="primary"
size="64"
appear
@click="editor.show = true"
/>
<post-editor />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { useEditor } from "@/stores/editor";
import PostEditor from "@/components/publish/PostEditor.vue";
const editor = useEditor()
const navigationMenu = [ const navigationMenu = [
{ name: "Explore", icon: "mdi-compass", to: "explore" } { name: "Explore", icon: "mdi-compass", to: "explore" }
]; ];
@ -40,3 +54,11 @@ function toggleDrawer() {
drawerOpen.value = !drawerOpen.value; drawerOpen.value = !drawerOpen.value;
} }
</script> </script>
<style scoped>
.editor-fab {
position: fixed !important;
bottom: 16px;
right: 20px;
}
</style>

View File

@ -9,6 +9,7 @@ import "vuetify/styles";
import { createVuetify } from "vuetify"; import { createVuetify } from "vuetify";
import { md3 } from "vuetify/blueprints"; import { md3 } from "vuetify/blueprints";
import * as components from "vuetify/components"; import * as components from "vuetify/components";
import * as labsComponents from 'vuetify/labs/components'
import * as directives from "vuetify/directives"; import * as directives from "vuetify/directives";
import "@mdi/font/css/materialdesignicons.min.css"; import "@mdi/font/css/materialdesignicons.min.css";
@ -22,8 +23,11 @@ const app = createApp(index);
app.use( app.use(
createVuetify({ createVuetify({
components,
directives, directives,
components: {
...components,
...labsComponents,
},
blueprint: md3, blueprint: md3,
theme: { theme: {
defaultTheme: "original", defaultTheme: "original",

View File

@ -0,0 +1,8 @@
import { defineStore } from "pinia";
import { ref } from "vue";
export const useEditor = defineStore("editor", () => {
const show = ref(false);
return { show };
});

View File

@ -1,5 +1,5 @@
<template> <template>
<v-container class="flex max-md:flex-col gap-3 overflow-auto max-h-[calc(100vh-72px)] no-scrollbar"> <v-container class="flex max-md:flex-col gap-3 overflow-auto max-h-[calc(100vh-64px)] no-scrollbar">
<div class="timeline flex-grow-1 mt-[-16px]"> <div class="timeline flex-grow-1 mt-[-16px]">
<post-list :loading="loading" :posts="posts" :loader="readMore" /> <post-list :loading="loading" :posts="posts" :loader="readMore" />
</div> </div>
@ -56,4 +56,4 @@ async function readMore({ done }: any) {
} }
readPosts(); readPosts();
</script> </script>

View File

@ -1,5 +1,5 @@
import { defineConfig, presetUno } from "unocss" import { defineConfig, presetAttributify, presetTypography, presetUno } from "unocss";
export default defineConfig({ export default defineConfig({
presets: [presetUno({ preflight: false })] presets: [presetAttributify(), presetTypography(), presetUno({ preflight: false })]
}) })