Skip to content

Commit

Permalink
feat(plugin-md-power): add <Plot /> and =||= syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
pengzhanbo committed Apr 20, 2024
1 parent 7daf764 commit 9a5eda4
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 5 deletions.
4 changes: 3 additions & 1 deletion docs/.vuepress/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const theme: Theme = themePlume({
url: '/plume.png',
name: 'Plume Theme',
description: 'The Theme for Vuepress 2.0',
location: 'Guangzhou, China',
location: 'GuangZhou, China',
organization: 'pengzhanbo',
},

Expand All @@ -40,6 +40,7 @@ export const theme: Theme = themePlume({
{ icon: 'steam', link: 'https://pengzhanbo.cn' },
{ icon: 'xbox', link: 'https://pengzhanbo.cn' },
],
navbarSocialInclude: ['github'],

watermark: {
global: false,
Expand Down Expand Up @@ -74,6 +75,7 @@ export const theme: Theme = themePlume({
markdownPower: {
pdf: true,
caniuse: true,
plot: true,
bilibili: true,
youtube: true,
icons: true,
Expand Down
97 changes: 97 additions & 0 deletions plugins/plugin-md-power/src/client/components/Plot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script setup lang="ts">
import { computed, ref, shallowRef } from 'vue'
import { onClickOutside, useMediaQuery } from '@vueuse/core'
import { usePageFrontmatter } from 'vuepress/client'
import type { PlotOptions } from '../../shared/plot.js'
import { pluginOptions } from '../options.js'
const props = defineProps<Omit<PlotOptions, 'tag'>>()
const matter = usePageFrontmatter()
const options = computed(() => {
const plot = typeof pluginOptions.plot === 'object' ? pluginOptions.plot : {}
return {
trigger: props.trigger || matter.value.plotTrigger || plot.trigger || 'hover',
color: props.color || plot.color,
mask: props.mask || plot.mask,
}
})
const styles = computed(() => {
const plot = options.value
if (!plot.color && !plot.mask)
return {}
const style: Record<string, string> = {}
if (plot.color) {
if (typeof plot.color === 'string') {
style['--vp-c-plot-light'] = plot.color
}
else {
style['--vp-c-plot-light'] = plot.color.light
style['--vp-c-plot-dark'] = plot.color.dark
}
}
if (plot.mask) {
if (typeof plot.mask === 'string') {
style['--vp-c-bg-plot-light'] = plot.mask
}
else {
style['--vp-c-bg-plot-light'] = plot.mask.light
style['--vp-c-bg-plot-dark'] = plot.mask.dark
}
}
return style
})
const isMobile = useMediaQuery('(max-width: 768px)')
const active = ref(false)
const el = shallowRef<HTMLElement>()
onClickOutside(el, () => {
if (options.value.trigger === 'click' || isMobile.value)
active.value = false
})
function onClick() {
if (props.trigger === 'click' || isMobile.value)
active.value = !active.value
}
</script>

<template>
<span
ref="el"
class="vp-plot"
:class="{ hover: options.trigger !== 'click', active }"
:style="styles"
@click="onClick"
>
<slot />
</span>
</template>

<style>
.vp-plot {
padding-right: 2px;
padding-left: 2px;
color: transparent;
background-color: var(--vp-c-bg-plot-light, #000);
transition: color ease 0.25s, background-color ease 0.25s;
}
.dark .vp-plot {
background-color: var(--vp-c-bg-plot-dark, #fff);
}
.vp-plot.hover:hover,
.vp-plot.active {
color: var(--vp-c-plot-light, #fff);
}
.dark .vp-plot.hover:hover,
.dark .vp-plot.active {
color: var(--vp-c-plot-dark, #000);
}
</style>
73 changes: 73 additions & 0 deletions plugins/plugin-md-power/src/node/features/plot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* =|这里的文本将被黑幕隐藏,通过点击或者 hover 才可重现|=
*/
import type { PluginWithOptions } from 'markdown-it'
import type { RuleInline } from 'markdown-it/lib/parser_inline.mjs'

const [openTag, endTag] = ['=|', '|=']

function createTokenizer(): RuleInline {
return (state, silent) => {
let found = false
const max = state.posMax
const start = state.pos

if (state.src.slice(start, start + 2) !== openTag)
return false

if (silent)
return false

// =||=
if (max - start < 5)
return false

state.pos = start + 2

while (state.pos < max) {
if (state.src.slice(state.pos - 1, state.pos + 1) === endTag) {
found = true
break
}

state.md.inline.skipToken(state)
}

if (!found || start + 2 === state.pos) {
state.pos = start

return false
}
const content = state.src.slice(start + 2, state.pos - 1)

// 不允许前后带有空格
if (/^\s|\s$/.test(content)) {
state.pos = start
return false
}

// found!
state.posMax = state.pos - 1
state.pos = start + 2

const open = state.push('plot_open', 'Plot', 1)
open.markup = openTag

const text = state.push('text', '', 0)
text.content = content

const close = state.push('plot_close', 'Plot', -1)
close.markup = endTag

state.pos = state.posMax + 2
state.posMax = max

return true
}
}

export const plotPlugin: PluginWithOptions<never> = (
md,
) => {
md.inline.ruler.before('emphasis', 'plot', createTokenizer())
}
1 change: 1 addition & 0 deletions plugins/plugin-md-power/src/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export * from './codepen.js'
export * from './codeSandbox.js'
export * from './replit.js'
export * from './jsfiddle.js'
export * from './plot.js'

export * from './plugin.js'
24 changes: 24 additions & 0 deletions plugins/plugin-md-power/src/shared/plot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export interface PlotOptions {
/**
* 是否启用 `=| |=` markdown (该标记为非标准标记,脱离插件将不生效)
* @default true
*/
tag?: boolean

/**
* 遮罩层颜色
*/
mask?: string | { light: string, dark: string }

/**
* 文本颜色
*/
color?: string | { light: string, dark: string }

/**
* 触发方式
*
* @default 'hover'
*/
trigger?: 'hover' | 'click'
}
2 changes: 2 additions & 0 deletions plugins/plugin-md-power/src/shared/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { CanIUseOptions } from './caniuse.js'
import type { PDFOptions } from './pdf.js'
import type { IconsOptions } from './icons.js'
import type { PlotOptions } from './plot.js'

export interface MarkdownPowerPluginOptions {
pdf?: boolean | PDFOptions

// new syntax
icons?: boolean | IconsOptions
plot?: boolean | PlotOptions

// video embed
bilibili?: boolean
Expand Down
8 changes: 8 additions & 0 deletions theme/src/client/styles/vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -666,3 +666,11 @@ html.dark {
--code-bg-color: var(--vp-code-block-bg);
--medium-zoom-bg-color: var(--vp-c-bg);
}

/* md power plot */
:root {
--vp-c-plot-light: var(--vp-c-bg);
--vp-c-bg-plot-light: var(--vp-c-text-1);
--vp-c-plot-dark: var(--vp-c-bg);
--vp-c-bg-plot-dark: var(--vp-c-text-2);
}
4 changes: 2 additions & 2 deletions theme/src/node/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { iconifyPlugin } from '@vuepress-plume/plugin-iconify'
import { notesDataPlugin } from '@vuepress-plume/plugin-notes-data'
import { shikiPlugin } from '@vuepress-plume/plugin-shikiji'
import { commentPlugin } from '@vuepress/plugin-comment'
import { type MarkdownEnhanceOptions, mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { type MarkdownEnhancePluginOptions, mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
import { seoPlugin } from '@vuepress/plugin-seo'
import { sitemapPlugin } from '@vuepress/plugin-sitemap'
Expand Down Expand Up @@ -196,7 +196,7 @@ export function setupPlugins(
alert: true,
footnote: true,
katex: true,
} as MarkdownEnhanceOptions,
} as MarkdownEnhancePluginOptions,
options.markdownEnhance || {},
),
))
Expand Down
4 changes: 2 additions & 2 deletions theme/src/shared/options/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { BaiduTongjiOptions } from '@vuepress-plume/plugin-baidu-tongji'
import type { CopyCodeOptions } from '@vuepress-plume/plugin-copy-code'
import type { ShikiPluginOptions } from '@vuepress-plume/plugin-shikiji'
import type { CommentPluginOptions } from '@vuepress/plugin-comment'
import type { MarkdownEnhanceOptions } from 'vuepress-plugin-md-enhance'
import type { MarkdownEnhancePluginOptions } from 'vuepress-plugin-md-enhance'
import type { ReadingTimePluginOptions } from '@vuepress/plugin-reading-time'
import type { MarkdownPowerPluginOptions } from 'vuepress-plugin-md-power'

Expand Down Expand Up @@ -54,7 +54,7 @@ export interface PlumeThemePluginOptions {

copyCode?: false | CopyCodeOptions

markdownEnhance?: false | MarkdownEnhanceOptions
markdownEnhance?: false | MarkdownEnhancePluginOptions

markdownPower?: false | MarkdownPowerPluginOptions

Expand Down

0 comments on commit 9a5eda4

Please sign in to comment.