Compare commits
21 Commits
d02bcfe484
...
master
Author | SHA1 | Date | |
---|---|---|---|
d3d0e7c44d | |||
d9b5af7388 | |||
cefdf76045 | |||
92933de4bd | |||
5dd1b7c0ef | |||
945bef0523 | |||
fcf12f7dcf | |||
91b7922464 | |||
540333d431 | |||
7639ed84b3 | |||
1cb252b952 | |||
2684c5d58d | |||
539421bcd3 | |||
9120ad7a8d | |||
8df79b00a0 | |||
76a56ddc68 | |||
fd208f2b41 | |||
ea225d0f41 | |||
e4a73ad77b | |||
0a63d935e7 | |||
4fd2ddf837 |
42
.eslintrc.js
42
.eslintrc.js
@@ -1,14 +1,44 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
node: true
|
node: true,
|
||||||
},
|
},
|
||||||
extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: "babel-eslint"
|
parser: 'babel-eslint',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
semi: [
|
||||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
|
'error',
|
||||||
}
|
'always',
|
||||||
|
],
|
||||||
|
quotes: [
|
||||||
|
2,
|
||||||
|
'single',
|
||||||
|
],
|
||||||
|
'comma-dangle': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'arrays': 'always-multiline',
|
||||||
|
'objects': 'always-multiline',
|
||||||
|
'imports': 'always-multiline',
|
||||||
|
'exports': 'always-multiline',
|
||||||
|
'functions': 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'space-before-function-paren': [
|
||||||
|
'error',
|
||||||
|
'never',
|
||||||
|
],
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
|
'max-len': ['warn', {
|
||||||
|
'code': 100,
|
||||||
|
'ignoreStrings': true,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
|
||||||
|
extends: [
|
||||||
|
'plugin:vue/recommended',
|
||||||
|
'eslint:recommended',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
/dist
|
dist
|
||||||
|
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ["@vue/cli-plugin-babel/preset"]
|
presets: ['@vue/cli-plugin-babel/preset'],
|
||||||
};
|
};
|
||||||
|
261
dist/block-renderer.umd.js
vendored
Normal file
261
dist/block-renderer.umd.js
vendored
Normal file
File diff suppressed because one or more lines are too long
13748
package-lock.json
generated
13748
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
47
package.json
47
package.json
@@ -1,33 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "block-renderer",
|
"name": "block-renderer",
|
||||||
"description": "Content renderer for JSON blocks from Editor.js",
|
"description": "Content renderer for JSON blocks from Editor.js",
|
||||||
"version": "0.1.3",
|
"version": "0.7.7",
|
||||||
"author": "KingOfDog <info@kingofdog.de>",
|
"author": "KingOfDog <info@kingofdog.de>",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.kingofdog.de/KingOfDog/block-renderer"
|
"url": "https://git.kingofdog.de/KingOfDog/block-renderer"
|
||||||
},
|
},
|
||||||
"homepage": "https://git.kingofdog.de/KingOfDog/block-renderer",
|
"homepage": "https://git.kingofdog.de/KingOfDog/block-renderer",
|
||||||
|
"type": "module",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"main": "./dist/block-renderer.umd.js",
|
||||||
|
"module": "./dist/block-renderer.es.js",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/block-renderer.es.js",
|
||||||
|
"require": "./dist/block-renderer.umd.js"
|
||||||
|
},
|
||||||
|
"./dist/block-renderer.css": {
|
||||||
|
"import": "./dist/block-renderer.css",
|
||||||
|
"require": "./dist/block-renderer.css"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types": "./dist/main.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"dev": "vite",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-tsc && vite build",
|
||||||
"build-package": "vue-cli-service build --target lib --name block-renderer ./src/main.js",
|
"preview": "vite preview"
|
||||||
"lint": "vue-cli-service lint"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"katex": "^0.16.8",
|
||||||
"vue": "^2.6.11"
|
"vue": "^3.3.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"path": "^0.12.7",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"rollup-plugin-typescript2": "^0.34.1",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"typescript": "^4.9.3",
|
||||||
"babel-eslint": "^10.1.0",
|
"vite": "^4.0.0",
|
||||||
"eslint": "^6.7.2",
|
"vite-plugin-dts": "^1.7.1",
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
"vue-tsc": "^1.0.11"
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
|
||||||
"prettier": "^1.19.1",
|
|
||||||
"vue-template-compiler": "^2.6.11"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,3 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="40">
|
|
||||||
<path d="M17 0l15 14V3v34a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h20-6zm0 2H3a1 1 0 0 0-1 1v34a1 1 0 0 0 1 1h26a1 1 0 0 0 1-1V14H17V2zm2 10h7.926L19 4.602V12z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 240 B |
@@ -1,6 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="40">
|
|
||||||
<g fill="#A8ACB8" fill-rule="evenodd">
|
|
||||||
<path fill-rule="nonzero" d="M17 0l15 14V3v34a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h20-6zm0 2H3a1 1 0 0 0-1 1v34a1 1 0 0 0 1 1h26a1 1 0 0 0 1-1V14H17V2zm2 10h7.926L19 4.602V12z"/>
|
|
||||||
<path d="M7 22h18v2H7zm0 4h18v2H7zm0 4h18v2H7z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 364 B |
@@ -1,81 +1,84 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="attaches-block">
|
<div class="attaches-block">
|
||||||
<div
|
<a :href="url" target="blank">
|
||||||
:data-extension="data.file.extension"
|
<div :data-extension="data.file.extension" class="attaches-block-file-icon" :style="{ color: color }">
|
||||||
:style="{ color: color }"
|
<svg width="32" height="40">
|
||||||
class="attaches-block-file-icon"
|
<path v-if="color"
|
||||||
>
|
d="M17 0l15 14V3v34a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h20-6zm0 2H3a1 1 0 0 0-1 1v34a1 1 0 0 0 1 1h26a1 1 0 0 0 1-1V14H17V2zm2 10h7.926L19 4.602V12z" />
|
||||||
<svg>
|
<g v-else fill="#A8ACB8" fill-rule="evenodd">
|
||||||
<use
|
<path fill-rule="nonzero"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
d="M17 0l15 14V3v34a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h20-6zm0 2H3a1 1 0 0 0-1 1v34a1 1 0 0 0 1 1h26a1 1 0 0 0 1-1V14H17V2zm2 10h7.926L19 4.602V12z" />
|
||||||
v-bind:xlink:href="color ? customIcon : standardIcon"
|
<path d="M7 22h18v2H7zm0 4h18v2H7zm0 4h18v2H7z" />
|
||||||
/>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
<div class="attaches-block-file-info">
|
<div class="attaches-block-file-info">
|
||||||
<p class="attaches-block-title">{{ data.file.name }}</p>
|
<a :href="url" target="blank">
|
||||||
<p class="attaches-block-size">{{ data.file.size | byteFormatter }}</p>
|
<p class="attaches-block-title">{{ data.title }}</p>
|
||||||
|
</a>
|
||||||
|
<p class="attaches-block-size">
|
||||||
|
{{ fileSize }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<a :href="data.file.url" class="attaches-block-file download-button"></a>
|
<a :href="url" target="_blank" class="attaches-block-file-download-button">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17pt" height="17pt" viewBox="0 0 17 17">
|
||||||
|
<path
|
||||||
|
d="M9.457 8.945V2.848A.959.959 0 0 0 8.5 1.89a.959.959 0 0 0-.957.957v6.097L4.488 5.891a.952.952 0 0 0-1.351 0 .952.952 0 0 0 0 1.351l4.687 4.688a.955.955 0 0 0 1.352 0l4.687-4.688a.952.952 0 0 0 0-1.351.952.952 0 0 0-1.351 0zM3.59 14.937h9.82a.953.953 0 0 0 .953-.957.952.952 0 0 0-.953-.953H3.59a.952.952 0 0 0-.953.953c0 .532.425.957.953.957zm0 0"
|
||||||
|
fill-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import byteFormatter from "../filters/byteFormatter";
|
import byteFormatter from '../filters/byteFormatter';
|
||||||
|
|
||||||
const extensions = {
|
const extensions = {
|
||||||
doc: "#3e74da",
|
doc: '#3e74da',
|
||||||
docx: "#3e74da",
|
docx: '#3e74da',
|
||||||
odt: "#3e74da",
|
odt: '#3e74da',
|
||||||
pdf: "#d47373",
|
pdf: '#d47373',
|
||||||
rtf: "#656ecd",
|
rtf: '#656ecd',
|
||||||
tex: "#5a5a5b",
|
tex: '#5a5a5b',
|
||||||
txt: "#5a5a5b",
|
txt: '#5a5a5b',
|
||||||
pptx: "#e07066",
|
pptx: '#e07066',
|
||||||
ppt: "#e07066",
|
ppt: '#e07066',
|
||||||
mp3: "#eab456",
|
mp3: '#eab456',
|
||||||
mp4: "#f676a6",
|
mp4: '#f676a6',
|
||||||
xls: "#3f9e64",
|
xls: '#3f9e64',
|
||||||
html: "#2988f0",
|
html: '#2988f0',
|
||||||
htm: "#2988f0",
|
htm: '#2988f0',
|
||||||
png: "#f676a6",
|
png: '#f676a6',
|
||||||
jpg: "#f67676",
|
jpg: '#f67676',
|
||||||
jpeg: "#f67676",
|
jpeg: '#f67676',
|
||||||
gif: "#f6af76",
|
gif: '#f6af76',
|
||||||
zip: "#4f566f",
|
zip: '#4f566f',
|
||||||
rar: "#4f566f",
|
rar: '#4f566f',
|
||||||
exe: "#e26f6f",
|
exe: '#e26f6f',
|
||||||
svg: "#bf5252",
|
svg: '#bf5252',
|
||||||
key: "#e07066",
|
key: '#e07066',
|
||||||
sketch: "#df821c",
|
sketch: '#df821c',
|
||||||
ai: "#df821c",
|
ai: '#df821c',
|
||||||
psd: "#388ae5",
|
psd: '#388ae5',
|
||||||
dmg: "#e26f6f",
|
dmg: '#e26f6f',
|
||||||
json: "#2988f0",
|
json: '#2988f0',
|
||||||
csv: "#3f9e64"
|
csv: '#3f9e64',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
filters: {
|
props: ['data'],
|
||||||
byteFormatter
|
inject: ['$baseFileUrl'],
|
||||||
},
|
|
||||||
props: ["data"],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
standardIcon: require("@/assets/svg/standard.svg"),
|
|
||||||
customIcon: require("@/assets/svg/custom.svg")
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
color() {
|
color() {
|
||||||
return extensions[this.data.file.extension];
|
return extensions[this.data.file.extension.toLowerCase()];
|
||||||
|
},
|
||||||
|
url() {
|
||||||
|
return `${this.$baseFileUrl}/${this.data.file.id}?name=${this.data.file.name}`;
|
||||||
|
},
|
||||||
|
fileSize() {
|
||||||
|
return byteFormatter(this.data.file.size)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.attaches-block-file-icon::before {
|
|
||||||
content: attr(data-extension);
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,70 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<component
|
<component :is="block.component" v-for="(block, index) in blocks" :key="index" :data="block.data" />
|
||||||
v-for="(block, index) in blocks"
|
|
||||||
:key="index"
|
|
||||||
:is="block.component"
|
|
||||||
:data="block.data"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AttachesBlock from "./AttachesBlock";
|
import AttachesBlock from './AttachesBlock.vue';
|
||||||
import EmbedBlock from "./EmbedBlock";
|
import ButtonBlock from './ButtonBlock.vue';
|
||||||
import HeaderBlock from "./HeaderBlock";
|
import EmbedBlock from './EmbedBlock.vue';
|
||||||
import ImageBlock from "./ImageBlock";
|
import HeaderBlock from './HeaderBlock.vue';
|
||||||
import LinkBlock from "./LinkBlock";
|
import ImageBlock from './ImageBlock.vue';
|
||||||
import ListBlock from "./ListBlock";
|
import LinkBlock from './LinkBlock.vue';
|
||||||
import ParagraphBlock from "./ParagraphBlock";
|
import ListBlock from './ListBlock.vue';
|
||||||
import QuoteBlock from "./QuoteBlock";
|
import MathBlock from './MathBlock.vue';
|
||||||
import WarningBlock from "./WarningBlock";
|
import ParagraphBlock from './ParagraphBlock.vue';
|
||||||
|
import QuoteBlock from './QuoteBlock.vue';
|
||||||
|
import WarningBlock from './WarningBlock.vue';
|
||||||
|
|
||||||
const componentTypes = {
|
const componentTypes = {
|
||||||
attaches: AttachesBlock,
|
attaches: AttachesBlock,
|
||||||
|
button: ButtonBlock,
|
||||||
embed: EmbedBlock,
|
embed: EmbedBlock,
|
||||||
header: HeaderBlock,
|
header: HeaderBlock,
|
||||||
image: ImageBlock,
|
image: ImageBlock,
|
||||||
link: LinkBlock,
|
linkEmbed: LinkBlock,
|
||||||
list: ListBlock,
|
list: ListBlock,
|
||||||
|
math: MathBlock,
|
||||||
paragraph: ParagraphBlock,
|
paragraph: ParagraphBlock,
|
||||||
quote: QuoteBlock,
|
quote: QuoteBlock,
|
||||||
warning: WarningBlock
|
warning: WarningBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["content"],
|
props: ['content'],
|
||||||
data() {
|
computed: {
|
||||||
return {
|
blocks() {
|
||||||
blocks: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.content) {
|
|
||||||
this.prepareBlocks();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
prepareBlocks() {
|
|
||||||
if (!this.content.blocks) {
|
if (!this.content.blocks) {
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
this.blocks = this.content.blocks.map(block => ({
|
|
||||||
|
return this.content.blocks.map(block => ({
|
||||||
component: componentTypes[block.type],
|
component: componentTypes[block.type],
|
||||||
type: block.type,
|
type: block.type,
|
||||||
data: block.data
|
data: block.data,
|
||||||
}));
|
}));
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
content() {
|
|
||||||
if (this.content) {
|
|
||||||
this.prepareBlocks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
15
src/components/ButtonBlock.vue
Normal file
15
src/components/ButtonBlock.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<div class="button-block">
|
||||||
|
<a
|
||||||
|
:href="data.url"
|
||||||
|
target="_blank"
|
||||||
|
v-html="data.label"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ['data'],
|
||||||
|
};
|
||||||
|
</script>
|
@@ -1,16 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<figure>
|
<figure class="embed-block">
|
||||||
<iframe :src="data.embed" :height="data.height" frameborder="0" allowfullscreen class="w-full"></iframe>
|
<div class="embed-container">
|
||||||
|
<iframe
|
||||||
|
v-if="accepted"
|
||||||
|
:src="data.embed"
|
||||||
|
:height="data.height"
|
||||||
|
frameborder="0"
|
||||||
|
allowfullscreen
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="embed-accept"
|
||||||
|
>
|
||||||
|
<h2>Externer Inhalt</h2>
|
||||||
|
<h3>
|
||||||
|
Originaler Link: <a
|
||||||
|
:href="data.source"
|
||||||
|
target="_blank"
|
||||||
|
>{{ displayUrl }}</a>
|
||||||
|
</h3>
|
||||||
|
<p>
|
||||||
|
An dieser Stelle ist externer Inhalt eingebunden. Um den Datenschutz
|
||||||
|
zu gewährleisten, ist er derzeit ausgeblendet. Deine Privatsphäre kann
|
||||||
|
auf externen Seiten nicht sichergestellt werden. Möchtest du den
|
||||||
|
Inhalt dennoch anzeigen?
|
||||||
|
</p>
|
||||||
|
<button @click="accepted = true">
|
||||||
|
Anzeigen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<figcaption v-html="data.caption"></figcaption>
|
<figcaption v-html="data.caption" />
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
|
data() {
|
||||||
|
return { accepted: false };
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
displayUrl() {
|
||||||
|
if (!this.data) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const url = new URL(this.data.source);
|
||||||
|
return url.hostname;
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
@@ -1,11 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="`h${data.level}`" :id="data.anchor">
|
||||||
|
<span v-html="data.text" />
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
render(createElement) {
|
|
||||||
return createElement("h" + this.data.level, this.data.text);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
@@ -1,16 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<figure>
|
<figure>
|
||||||
<img :src="data.file.url" />
|
<img v-lazyload :src="lowQualityUrl" :data-src="highQualityUrl">
|
||||||
|
|
||||||
<figcaption v-html="data.caption"></figcaption>
|
<figcaption v-html="data.caption" />
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import LazyLoadImage from '../directives/lazy-load-image';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
directives: {
|
||||||
|
lazyload: LazyLoadImage,
|
||||||
|
},
|
||||||
|
props: ['data'],
|
||||||
|
inject: ['$baseFileUrl'],
|
||||||
|
computed: {
|
||||||
|
lowQualityUrl() {
|
||||||
|
return `${this.$baseFileUrl}/${this.data.file.id}?type=jpg&w=100&b=50`;
|
||||||
|
},
|
||||||
|
highQualityUrl() {
|
||||||
|
return `${this.$baseFileUrl}/${this.data.file.id}?w=1200`;
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
@@ -1,22 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="link-block">
|
<div class="link-block">
|
||||||
<div class="link-block-meta">
|
<a
|
||||||
<div class="link-block-title">{{data.meta.title}}</div>
|
:href="data.link"
|
||||||
<p class="link-block-description">{{data.meta.description}}</p>
|
target="_blank"
|
||||||
<div class="link-block-anchor">{{domain}}</div>
|
class="link-block-href"
|
||||||
</div>
|
>
|
||||||
|
<div class="link-block-meta">
|
||||||
|
<div class="link-block-title">{{ data.meta.title }}</div>
|
||||||
|
<p class="link-block-description">{{ data.meta.description }}</p>
|
||||||
|
<div class="link-block-anchor">{{ domain }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="link-block-image" :style="{ 'background-image': data.meta.image.url }"></div>
|
<div
|
||||||
|
class="link-block-image"
|
||||||
|
:style="{ backgroundImage: `url(${data.meta.image.url}` }"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
computed: {
|
computed: {
|
||||||
domain() {
|
domain() {
|
||||||
return this.data.link.replace(/(https|http):\/\//, "").split(/[/?#]/)[0];
|
return this.data.link.replace(/(https|http):\/\//, '').split(/[/?#]/)[0];
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="data.style === 'ordered' ? 'ol' : 'ul'">
|
||||||
|
<li v-for="item in data.items" :key="item" v-html="item"></li>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
render(createElement) {
|
|
||||||
return createElement(
|
|
||||||
this.data.style === "ordered" ? "ol" : "ul",
|
|
||||||
this.data.items.map((item) => createElement("li", item))
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
23
src/components/MathBlock.vue
Normal file
23
src/components/MathBlock.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<figure>
|
||||||
|
<div v-html="content" />
|
||||||
|
</figure>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import katex from 'katex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['data'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
content: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.content = katex.renderToString(this.data.text, {
|
||||||
|
throwOnError: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<p v-html="data.text"></p>
|
<p v-html="data.text" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p v-html="data.text"></p>
|
<p v-html="data.text" />
|
||||||
|
|
||||||
<footer v-html="data.caption"></footer>
|
<footer v-html="data.caption" />
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -1,15 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="warning-block">
|
<div class="warning-block">
|
||||||
<p class="font-semibold mb-4 text-white">{{data.title}}</p>
|
<b v-html="title" />
|
||||||
<p v-html="data.message" class="text-white"></p>
|
<p v-html="data.message" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: ["data"],
|
props: ['data'],
|
||||||
|
computed: {
|
||||||
|
title() {
|
||||||
|
return this.data.title ? this.data.title.replace(/<br>/g, '') : '';
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
38
src/directives/lazy-load-image.js
Normal file
38
src/directives/lazy-load-image.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
export default {
|
||||||
|
mounted: (el) => {
|
||||||
|
function loadImage() {
|
||||||
|
const image = new Image();
|
||||||
|
image.src = el.dataset.src;
|
||||||
|
image.onload = () => {
|
||||||
|
el.src = el.dataset.src;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleIntersect(entries, observer) {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (!entry.isIntersecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadImage();
|
||||||
|
observer.unobserve(el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createObserver() {
|
||||||
|
const options = {
|
||||||
|
root: null,
|
||||||
|
threshold: "0",
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(handleIntersect, options);
|
||||||
|
observer.observe(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.IntersectionObserver) {
|
||||||
|
loadImage();
|
||||||
|
} else {
|
||||||
|
createObserver();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@@ -1,4 +1,4 @@
|
|||||||
module.exports = function(size) {
|
export default function (size) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@@ -27,4 +27,4 @@ module.exports = function(size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
}
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
import BlockContentRenderer from './components/BlockContentRenderer.vue';
|
|
||||||
|
|
||||||
export default BlockContentRenderer;
|
|
||||||
export { BlockContentRenderer };
|
|
13
src/main.ts
Normal file
13
src/main.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { App } from 'vue';
|
||||||
|
import BlockContentRenderer from './components/BlockContentRenderer.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install: (app: App, options: {
|
||||||
|
baseFileUrl?: string
|
||||||
|
}) => {
|
||||||
|
app.provide('$baseFileUrl', options.baseFileUrl);
|
||||||
|
app.component('BlockContentRenderer', BlockContentRenderer);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export { BlockContentRenderer };
|
5
src/vite-env.d.ts
vendored
Normal file
5
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
38
tsconfig.json
Normal file
38
tsconfig.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"declarationDir": "dist",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
"src/**/*.tsx",
|
||||||
|
"src/**/*.vue"
|
||||||
|
],
|
||||||
|
}
|
60
vite.config.ts
Normal file
60
vite.config.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import * as path from 'path'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import typescript2 from 'rollup-plugin-typescript2';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import dts from "vite-plugin-dts";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
dts({
|
||||||
|
insertTypesEntry: true,
|
||||||
|
}),
|
||||||
|
typescript2({
|
||||||
|
check: false,
|
||||||
|
include: ["src/components/**/*.vue"],
|
||||||
|
tsconfigOverride: {
|
||||||
|
compilerOptions: {
|
||||||
|
outDir: "dist",
|
||||||
|
sourceMap: true,
|
||||||
|
declaration: true,
|
||||||
|
declarationMap: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exclude: ["vite.config.ts"]
|
||||||
|
})
|
||||||
|
],
|
||||||
|
build: {
|
||||||
|
cssCodeSplit: true,
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points
|
||||||
|
entry: "src/main.ts",
|
||||||
|
name: 'blockRenderer',
|
||||||
|
formats: ["es", "cjs", "umd"],
|
||||||
|
fileName: format => `block-renderer.${format}.js`
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// make sure to externalize deps that should not be bundled
|
||||||
|
// into your library
|
||||||
|
input: {
|
||||||
|
main: path.resolve(__dirname, "src/main.ts")
|
||||||
|
},
|
||||||
|
external: ['vue'],
|
||||||
|
output: {
|
||||||
|
assetFileNames: (assetInfo) => {
|
||||||
|
if (assetInfo.name === 'main.css') return 'block-renderer.css';
|
||||||
|
return assetInfo.name;
|
||||||
|
},
|
||||||
|
exports: "named",
|
||||||
|
globals: {
|
||||||
|
vue: 'Vue',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, 'src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
Reference in New Issue
Block a user