mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
refactor: 调整插件使用 embed
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useBus } from '@fe/support/bus'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { defineComponent, h, onBeforeUnmount, onMounted, PropType, ref, watch } from 'vue'
|
||||
import { useBus } from '@fe/support/bus'
|
||||
|
||||
export function buildSrc (html: string, title = '') {
|
||||
return `/embed/?_t=${Date.now()}&title=${encodeURIComponent(title)}&html=${encodeURIComponent(html)}`
|
||||
@@ -14,7 +14,8 @@ export const IFrame = defineComponent({
|
||||
default: 500
|
||||
},
|
||||
html: String,
|
||||
iframeProps: Object
|
||||
iframeProps: Object,
|
||||
onLoad: Function as PropType<(iframe: HTMLIFrameElement) => void>
|
||||
},
|
||||
setup (props) {
|
||||
const url = ref('')
|
||||
@@ -54,7 +55,7 @@ export const IFrame = defineComponent({
|
||||
// 注入变量
|
||||
win.resize = resize
|
||||
win.ctx = window.ctx
|
||||
props.iframeProps?.onLoad?.call(frame)
|
||||
props.onLoad?.(frame)
|
||||
}
|
||||
|
||||
return () => url.value ? h('iframe', {
|
||||
@@ -63,8 +64,8 @@ export const IFrame = defineComponent({
|
||||
frameBorder: '0',
|
||||
width: '100%',
|
||||
height: '100px',
|
||||
...props.iframeProps,
|
||||
onLoad,
|
||||
...props.iframeProps,
|
||||
}) : null
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,97 +1,9 @@
|
||||
import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { h } from 'vue'
|
||||
import CryptoJS from 'crypto-js'
|
||||
import { debounce } from 'lodash-es'
|
||||
import dayjs from 'dayjs'
|
||||
import Markdown from 'markdown-it'
|
||||
import { useBus } from '@fe/support/bus'
|
||||
import { Plugin } from '@fe/context/plugin'
|
||||
import { getThemeName } from '@fe/context/theme'
|
||||
|
||||
let cssText = ''
|
||||
|
||||
const Applet = defineComponent({
|
||||
name: 'applet',
|
||||
props: {
|
||||
id: String,
|
||||
code: String,
|
||||
title: String,
|
||||
},
|
||||
setup (props) {
|
||||
const bus = useBus()
|
||||
const iframe = ref<HTMLIFrameElement>()
|
||||
const srcdoc = ref('')
|
||||
|
||||
const setSrcdoc = () => {
|
||||
const theme = getThemeName()
|
||||
srcdoc.value = `
|
||||
<html app-theme="${theme}">
|
||||
<head>
|
||||
<style>
|
||||
${cssText}
|
||||
|
||||
button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"]), textarea, select {
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
${props.code}
|
||||
</html>
|
||||
`
|
||||
}
|
||||
|
||||
onMounted(setSrcdoc)
|
||||
watch(() => props.code, debounce(setSrcdoc, 1000))
|
||||
bus.on('theme.change', setSrcdoc)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bus.off('theme.change', setSrcdoc)
|
||||
})
|
||||
|
||||
const onLoad = function (this: HTMLIFrameElement) {
|
||||
const resize = () => {
|
||||
iframe.value!.height = iframe.value!.contentDocument!.documentElement.scrollHeight + 'px'
|
||||
bus.emit('global.resize')
|
||||
}
|
||||
resize()
|
||||
|
||||
const win = iframe.value!.contentWindow as any
|
||||
|
||||
// 注入变量
|
||||
win.resize = resize
|
||||
win.appletFrame = this
|
||||
win.appletId = props.id
|
||||
win.CryptoJS = CryptoJS
|
||||
win.dayjs = dayjs
|
||||
win.ctx = window.ctx
|
||||
|
||||
// 调用初始化方法
|
||||
win.init && win.init()
|
||||
}
|
||||
|
||||
return () => {
|
||||
return h('fieldset', {}, [
|
||||
h('legend', {}, `Applet: ${props.title}`),
|
||||
h('div',
|
||||
{ class: 'applet' },
|
||||
h('iframe', {
|
||||
ref: iframe,
|
||||
srcdoc: srcdoc.value,
|
||||
class: 'applet-iframe',
|
||||
frameBorder: '0',
|
||||
width: '100%',
|
||||
height: '20px',
|
||||
onLoad,
|
||||
})
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
import { IFrame } from '@fe/context/embed'
|
||||
|
||||
const MarkdownItPlugin = (md: Markdown) => {
|
||||
const temp = md.renderer.rules.fence!.bind(md.renderer.rules)
|
||||
@@ -108,40 +20,43 @@ const MarkdownItPlugin = (md: Markdown) => {
|
||||
const appletId = `applet-${hash}-${idx}`
|
||||
const appletTitle = firstLine.replace('<!--', '').replace('-->', '').replace('--applet--', '').trim()
|
||||
|
||||
return h(Applet, {
|
||||
id: appletId,
|
||||
title: appletTitle,
|
||||
code,
|
||||
}) as any
|
||||
}
|
||||
}
|
||||
const html = `
|
||||
<style>
|
||||
button { margin-left: 0; }
|
||||
input:not([type="checkbox"]):not([type="radio"]), textarea, select { margin: 10px 0; }
|
||||
</style>
|
||||
|
||||
export function getCssText () {
|
||||
return [].slice.call(window.document.styleSheets)
|
||||
.map((styleSheet: CSSStyleSheet) => [].slice.call(styleSheet.cssRules))
|
||||
.flat()
|
||||
.filter((cssRule: any) =>
|
||||
(
|
||||
cssRule.conditionText && (
|
||||
cssRule.conditionText === 'screen' ||
|
||||
cssRule.conditionText.includes('prefers-color-scheme')
|
||||
)
|
||||
) || (
|
||||
cssRule.selectorText && (
|
||||
cssRule.selectorText.startsWith('html') ||
|
||||
cssRule.selectorText.startsWith(':root') ||
|
||||
cssRule.selectorText.startsWith('::')
|
||||
)
|
||||
${code}
|
||||
`
|
||||
|
||||
return h('fieldset', {}, [
|
||||
h('legend', {}, `Applet: ${appletTitle}`),
|
||||
h('div',
|
||||
{ class: 'applet' },
|
||||
h(IFrame, {
|
||||
html,
|
||||
debounce: 1000,
|
||||
onLoad (iframe: HTMLIFrameElement) {
|
||||
const win = iframe.contentWindow as any
|
||||
win.appletId = appletId
|
||||
win.CryptoJS = CryptoJS
|
||||
win.dayjs = dayjs
|
||||
win.init?.()
|
||||
win.resize()
|
||||
},
|
||||
iframeProps: {
|
||||
class: 'applet-iframe',
|
||||
height: '20px',
|
||||
}
|
||||
}),
|
||||
)
|
||||
)
|
||||
.map((cssRule: CSSRule) => cssRule.cssText)
|
||||
.join('\n')
|
||||
]) as any
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'applet',
|
||||
register: ctx => {
|
||||
cssText = getCssText()
|
||||
ctx.markdown.registerPlugin(MarkdownItPlugin)
|
||||
}
|
||||
} as Plugin
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Markdown from 'markdown-it'
|
||||
import { defineComponent, h, ref, watch } from 'vue'
|
||||
import { Plugin } from '@fe/context/plugin'
|
||||
import { IFrame } from '@fe/context/embed'
|
||||
import * as api from '@fe/support/api'
|
||||
import { useBus } from '@fe/support/bus'
|
||||
import { openInNewWindow } from '@fe/utils'
|
||||
@@ -46,18 +47,17 @@ const Drawio = defineComponent({
|
||||
button('新窗口打开', () => openInNewWindow('查看图形', srcdoc.value)),
|
||||
]
|
||||
),
|
||||
h(
|
||||
'iframe',
|
||||
{
|
||||
ref: iframe,
|
||||
h(IFrame, {
|
||||
html: srcdoc.value,
|
||||
onLoad (frame) {
|
||||
iframe.value = frame
|
||||
resize()
|
||||
},
|
||||
iframeProps: {
|
||||
class: 'drawio',
|
||||
frameBorder: '0',
|
||||
width: '100%',
|
||||
height: '300px',
|
||||
srcdoc: srcdoc.value,
|
||||
onLoad: resize
|
||||
}
|
||||
),
|
||||
},
|
||||
})
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user