feat: add content processer
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
<div class="mb-4 md:mb-8 border rounded overflow-hidden" :id="`message-${item.ID}`">
|
<div class="mb-4 md:mb-8 border rounded overflow-hidden" :id="`message-${item.ID}`">
|
||||||
<div class="bg-slate-100 p-2 md:p-4">
|
<div class="bg-slate-100 p-2 md:p-4">
|
||||||
<div class="mb-2 font-semibold text-right text-gray-400">#{{ item.ID }}</div>
|
<div class="mb-2 font-semibold text-right text-gray-400">#{{ item.ID }}</div>
|
||||||
<div v-if="item.Content.length > 0" class="text-wrap font-sans" v-html="processedContent"></div>
|
|
||||||
|
<MediaContent :content="item.Content" />
|
||||||
|
|
||||||
<div v-if="item.Media.length > 0" class="mt-2 md:mt-4">
|
<div v-if="item.Media.length > 0" class="mt-2 md:mt-4">
|
||||||
<div class="medias grid grid-cols-3 gap-2 md:gap-4">
|
<div class="medias grid grid-cols-3 gap-2 md:gap-4">
|
||||||
@@ -23,29 +24,20 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { deleteMessage, toggleFavorite } from "@/services/messages";
|
import { deleteMessage, toggleFavorite } from "@/services/messages";
|
||||||
import { computed, defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import MediaContent from "./MediaContent.vue";
|
||||||
import MediaItem from "./MediaItem.vue";
|
import MediaItem from "./MediaItem.vue";
|
||||||
|
|
||||||
function nl2br(str, is_xhtml) {
|
|
||||||
var breakTag = is_xhtml || typeof is_xhtml === "undefined" ? "<br />" : "<br>";
|
|
||||||
return (str + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + breakTag + "$2");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MediaItem,
|
MediaItem,
|
||||||
|
MediaContent,
|
||||||
},
|
},
|
||||||
name: "ListItem",
|
name: "ListItem",
|
||||||
props: {
|
props: {
|
||||||
item: { type: Object, required: true },
|
item: { type: Object, required: true },
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const processedContent = computed(() => {
|
|
||||||
let content = props.item.Content.trim();
|
|
||||||
return nl2br(content, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
const toggleLike = async () => {
|
const toggleLike = async () => {
|
||||||
const itemId = props.item.ID
|
const itemId = props.item.ID
|
||||||
await toggleFavorite(itemId);
|
await toggleFavorite(itemId);
|
||||||
|
|||||||
53
frontend/src/components/MediaContent.vue
Normal file
53
frontend/src/components/MediaContent.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="hasContent" class="text-wrap font-sans" v-html="processedContent"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { computed, defineComponent } from "vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
name: "MediaContent",
|
||||||
|
props: {
|
||||||
|
content: { required: true },
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const hasContent = () => {
|
||||||
|
return props.content.trim().length > 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const nl2br = function (content) {
|
||||||
|
var breakTag = typeof is_xhtml === "undefined" ? "<br />" : "<br>";
|
||||||
|
return (content + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + breakTag + "$2");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const replaceTags = (content) => {
|
||||||
|
content = content.replace(/#(\S+)/g, '<a href="/search?tag=$1">#$1</a>');
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceLinks = (content) => {
|
||||||
|
content = content.replace(/(https?:\/\/\S+)/g, '<a href="$1" target="_blank">$1</a>');
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedContent = computed(() => {
|
||||||
|
let content = props.content.trim();
|
||||||
|
|
||||||
|
content = nl2br(content, false);
|
||||||
|
content = replaceTags(content)
|
||||||
|
content = replaceLinks(content)
|
||||||
|
|
||||||
|
return content;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasContent,
|
||||||
|
processedContent,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user