mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
feat: update demo-wrapper container
This commit is contained in:
parent
ea6617554e
commit
0f8acc37dc
@ -106,17 +106,22 @@ H~2~O
|
||||
|
||||
**demo wrapper**
|
||||
|
||||
::: demo-wrapper
|
||||
|
||||
::: demo-wrapper title="示例" no-padding height="200px"
|
||||
<style scoped>
|
||||
.open-door {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
.open-door .main {
|
||||
background: #ccc;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="open-door">
|
||||
<div>main</div>
|
||||
<div>aside</div>
|
||||
<div class="main">main</div>
|
||||
<div class="aside">aside</div>
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
@ -419,22 +419,53 @@
|
||||
/* --------------------- demo-wrapper ------------------------ */
|
||||
|
||||
.plume-content .demo-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 40px;
|
||||
margin: 40px -16px;
|
||||
border: solid 1px var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--vp-shadow-2);
|
||||
|
||||
&.has-title .demo-head {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
&.only-img {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.only-img img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.only-img .demo-container,
|
||||
&.no-padding .demo-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.has-height .demo-container {
|
||||
height: var(--demo-container-height);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.demo-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
min-height: 0;
|
||||
border-bottom: solid 1px var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.demo-ctrl {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 5px 0 5px 8px;
|
||||
border-bottom: solid 1px var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.demo-head i {
|
||||
.demo-ctrl i {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@ -454,8 +485,52 @@
|
||||
}
|
||||
}
|
||||
|
||||
.demo-title {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
padding: 0 16px;
|
||||
margin: 0 20px -1px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
|
||||
.demo-title p {
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
.demo-title::after,
|
||||
.demo-title::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.demo-title::before {
|
||||
left: 100%;
|
||||
background: radial-gradient(16px at right top, transparent 50%, var(--vp-c-bg-alt) 50%);
|
||||
}
|
||||
|
||||
.demo-title::after {
|
||||
right: 100%;
|
||||
background: radial-gradient(16px at left top, transparent 50%, var(--vp-c-bg-alt) 50%);
|
||||
}
|
||||
|
||||
.demo-container {
|
||||
min-height: 0;
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
|
||||
@ -2,13 +2,54 @@ import containerPlugin from '@vuepress/plugin-container'
|
||||
import type { Plugin } from '@vuepress/core'
|
||||
|
||||
export const customContainers: Plugin[] = [
|
||||
/**
|
||||
* :::demo-wrapper img no-padding title="xxx" height="100px"
|
||||
* :::
|
||||
*/
|
||||
containerPlugin({
|
||||
type: 'demo-wrapper',
|
||||
before() {
|
||||
return `<div class="demo-wrapper"><div class="demo-head"><i></i><i></i><i></i></div><div class="demo-container">\n`
|
||||
before(info) {
|
||||
const title = resolveAttr(info, 'title')
|
||||
const wrapperClasses: string[] = ['demo-wrapper']
|
||||
let containerStyle = ''
|
||||
if (title)
|
||||
wrapperClasses.push('has-title')
|
||||
|
||||
if (info.includes('img'))
|
||||
wrapperClasses.push('only-img')
|
||||
|
||||
if (info.includes('no-padding'))
|
||||
wrapperClasses.push('no-padding')
|
||||
|
||||
const height = resolveAttr(info, 'height')
|
||||
if (height) {
|
||||
const h = Number.parseFloat(height) === Number(height) ? `${height}px` : height
|
||||
containerStyle += `--demo-container-height: ${h};`
|
||||
wrapperClasses.push('has-height')
|
||||
}
|
||||
|
||||
return `<div class="${wrapperClasses.join(' ')}">
|
||||
<div class="demo-head">
|
||||
<div class="demo-ctrl"><i></i><i></i><i></i></div>
|
||||
${title ? `<h4 class="demo-title"><p>${title}</p></h4>` : ''}
|
||||
</div>
|
||||
<div class="demo-container" ${containerStyle ? `style="${containerStyle}"` : ''}>\n`
|
||||
},
|
||||
after() {
|
||||
return '</div></div>\n'
|
||||
},
|
||||
}),
|
||||
]
|
||||
|
||||
/**
|
||||
* Resolve the specified attribute from token info
|
||||
*/
|
||||
function resolveAttr(info: string, attr: string): string | null {
|
||||
// try to match specified attr mark
|
||||
const pattern = `\\b${attr}\\s*=\\s*(?<quote>['"])(?<content>.+?)\\k<quote>(\\s|$)`
|
||||
const regex = new RegExp(pattern, 'i')
|
||||
const match = info.match(regex)
|
||||
|
||||
// return content if matched, null if not specified
|
||||
return match?.groups?.content ?? null
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user