feat: customize the theme color
This commit is contained in:
parent
ae1ad735d5
commit
5cc9f0514c
13 changed files with 120 additions and 42 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": ["vue"],
|
"extends": ["vue"],
|
||||||
"globals": {
|
"globals": {
|
||||||
"XMLHttpRequest": true
|
"XMLHttpRequest": true,
|
||||||
|
"__docsify__": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
## 2.0.0
|
||||||
|
### Features
|
||||||
|
- Customize the theme color
|
||||||
|
|
||||||
## 1.10.5
|
## 1.10.5
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- fix initialize the Vue instance
|
- fix initialize the Vue instance
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,15 @@ var cssnano = require('cssnano').process
|
||||||
var resolve = require('path').resolve
|
var resolve = require('path').resolve
|
||||||
var postcss = require('postcss')
|
var postcss = require('postcss')
|
||||||
|
|
||||||
var processor = postcss([require('postcss-salad')])
|
var processor = postcss([require('postcss-salad')({
|
||||||
|
features: {
|
||||||
|
precss: {
|
||||||
|
properties: {
|
||||||
|
preserve: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})])
|
||||||
|
|
||||||
var saveMin = function (file, content) {
|
var saveMin = function (file, content) {
|
||||||
fs.writeFileSync(resolve(__dirname, '../lib/themes/', file), content)
|
fs.writeFileSync(resolve(__dirname, '../lib/themes/', file), content)
|
||||||
|
|
|
||||||
|
|
@ -503,4 +503,17 @@ window.$docsify = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### theme-color
|
||||||
|
|
||||||
|
Customize the theme color.
|
||||||
|
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/lib/docsify.js" data-theme-color="#3F51B5"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
themeColor: '#3F51B5'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -511,3 +511,17 @@ window.$docsify = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### themeColor
|
||||||
|
|
||||||
|
自定义主题色。
|
||||||
|
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/lib/docsify.js" data-theme-color="#3F51B5"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
themeColor: '#3F51B5'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ const OPTIONS = merge({
|
||||||
basePath: '',
|
basePath: '',
|
||||||
auto2top: false,
|
auto2top: false,
|
||||||
name: '',
|
name: '',
|
||||||
|
themeColor: '',
|
||||||
nameLink: window.location.pathname
|
nameLink: window.location.pathname
|
||||||
}, window.$docsify)
|
}, window.$docsify)
|
||||||
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
|
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
|
||||||
|
|
@ -35,6 +36,9 @@ if (script) {
|
||||||
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
|
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// utils
|
||||||
|
window.__docsify__ = OPTIONS
|
||||||
|
|
||||||
// load options
|
// load options
|
||||||
render.init(OPTIONS)
|
render.init(OPTIONS)
|
||||||
|
|
||||||
|
|
|
||||||
27
src/polyfill.js
Normal file
27
src/polyfill.js
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { load } from './util'
|
||||||
|
|
||||||
|
function replaceVar (block) {
|
||||||
|
block.innerHTML = block.innerHTML.replace(/var\(\s*--theme-color.*?\)/g, __docsify__.themeColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cssVars () {
|
||||||
|
// variable support
|
||||||
|
if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) return
|
||||||
|
|
||||||
|
const styleBlocks = document.querySelectorAll('style:not(.inserted),link')
|
||||||
|
|
||||||
|
;[].forEach.call(styleBlocks, block => {
|
||||||
|
if (block.nodeName === 'STYLE') {
|
||||||
|
replaceVar(block)
|
||||||
|
} else if (block.nodeName === 'LINK') {
|
||||||
|
load(block.getAttribute('href'))
|
||||||
|
.then(res => {
|
||||||
|
const style = document.createElement('style')
|
||||||
|
|
||||||
|
style.innerHTML = res
|
||||||
|
document.head.appendChild(style)
|
||||||
|
replaceVar(style)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ import marked from 'marked'
|
||||||
import Prism from 'prismjs'
|
import Prism from 'prismjs'
|
||||||
import * as tpl from './tpl'
|
import * as tpl from './tpl'
|
||||||
import * as event from './event'
|
import * as event from './event'
|
||||||
|
import * as polyfill from './polyfill'
|
||||||
import { genTree, getRoute, isMobile, slugify, merge, emojify } from './util'
|
import { genTree, getRoute, isMobile, slugify, merge, emojify } from './util'
|
||||||
|
|
||||||
let OPTIONS = {}
|
|
||||||
let markdown = marked
|
let markdown = marked
|
||||||
let toc = []
|
let toc = []
|
||||||
const CACHE = {}
|
const CACHE = {}
|
||||||
|
|
@ -19,11 +19,8 @@ const renderTo = function (dom, content) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init render
|
* init render
|
||||||
* @param {Object} options
|
|
||||||
*/
|
*/
|
||||||
export function init (options) {
|
export function init () {
|
||||||
OPTIONS = options
|
|
||||||
|
|
||||||
const renderer = new marked.Renderer()
|
const renderer = new marked.Renderer()
|
||||||
/**
|
/**
|
||||||
* render anchor tag
|
* render anchor tag
|
||||||
|
|
@ -33,7 +30,7 @@ export function init (options) {
|
||||||
const slug = slugify(text)
|
const slug = slugify(text)
|
||||||
let route = ''
|
let route = ''
|
||||||
|
|
||||||
if (OPTIONS.router) {
|
if (__docsify__.router) {
|
||||||
route = `#/${getRoute()}`
|
route = `#/${getRoute()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +45,7 @@ export function init (options) {
|
||||||
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${hl.replace(/:/g, '__colon__')}</code></pre>`
|
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${hl.replace(/:/g, '__colon__')}</code></pre>`
|
||||||
}
|
}
|
||||||
renderer.link = function (href, title, text) {
|
renderer.link = function (href, title, text) {
|
||||||
if (OPTIONS.router && !/:/.test(href)) {
|
if (__docsify__.router && !/:/.test(href)) {
|
||||||
href = `#/${href}`.replace(/\/\//g, '/')
|
href = `#/${href}`.replace(/\/\//g, '/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,11 +60,11 @@ export function init (options) {
|
||||||
return `<p>${text}</p>`
|
return `<p>${text}</p>`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof OPTIONS.markdown === 'function') {
|
if (typeof __docsify__.markdown === 'function') {
|
||||||
markdown.setOptions({ renderer })
|
markdown.setOptions({ renderer })
|
||||||
markdown = OPTIONS.markdown.call(this, markdown)
|
markdown = __docsify__.markdown.call(this, markdown)
|
||||||
} else {
|
} else {
|
||||||
markdown.setOptions(merge({ renderer }, OPTIONS.markdown))
|
markdown.setOptions(merge({ renderer }, __docsify__.markdown))
|
||||||
}
|
}
|
||||||
|
|
||||||
const md = markdown
|
const md = markdown
|
||||||
|
|
@ -81,17 +78,23 @@ export function init (options) {
|
||||||
export function renderApp (dom, replace) {
|
export function renderApp (dom, replace) {
|
||||||
const nav = document.querySelector('nav') || document.createElement('nav')
|
const nav = document.querySelector('nav') || document.createElement('nav')
|
||||||
|
|
||||||
if (!OPTIONS.repo) nav.classList.add('no-badge')
|
if (!__docsify__.repo) nav.classList.add('no-badge')
|
||||||
|
|
||||||
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner(OPTIONS.repo) +
|
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner(__docsify__.repo) +
|
||||||
(OPTIONS.coverpage ? tpl.cover() : '') +
|
(__docsify__.coverpage ? tpl.cover() : '') +
|
||||||
tpl.main(OPTIONS.sidebarToggle ? tpl.toggle() : '')
|
tpl.main(__docsify__.sidebarToggle ? tpl.toggle() : '')
|
||||||
document.body.insertBefore(nav, document.body.children[0])
|
document.body.insertBefore(nav, document.body.children[0])
|
||||||
|
|
||||||
|
// theme color
|
||||||
|
if (__docsify__.themeColor) {
|
||||||
|
document.head.innerHTML += tpl.theme(__docsify__.themeColor)
|
||||||
|
polyfill.cssVars()
|
||||||
|
}
|
||||||
|
|
||||||
// bind toggle
|
// bind toggle
|
||||||
event.bindToggle('button.sidebar-toggle')
|
event.bindToggle('button.sidebar-toggle')
|
||||||
// bind sticky effect
|
// bind sticky effect
|
||||||
if (OPTIONS.coverpage) {
|
if (__docsify__.coverpage) {
|
||||||
!isMobile() && window.addEventListener('scroll', event.sticky)
|
!isMobile() && window.addEventListener('scroll', event.sticky)
|
||||||
} else {
|
} else {
|
||||||
document.body.classList.add('sticky')
|
document.body.classList.add('sticky')
|
||||||
|
|
@ -103,7 +106,7 @@ export function renderApp (dom, replace) {
|
||||||
*/
|
*/
|
||||||
export function renderArticle (content) {
|
export function renderArticle (content) {
|
||||||
renderTo('article', content ? markdown(content) : 'not found')
|
renderTo('article', content ? markdown(content) : 'not found')
|
||||||
if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
|
if (!__docsify__.sidebar && !__docsify__.loadSidebar) renderSidebar()
|
||||||
|
|
||||||
if (content && typeof Vue !== 'undefined') {
|
if (content && typeof Vue !== 'undefined') {
|
||||||
CACHE.vm && CACHE.vm.$destroy()
|
CACHE.vm && CACHE.vm.$destroy()
|
||||||
|
|
@ -120,7 +123,7 @@ export function renderArticle (content) {
|
||||||
: new Vue({ el: 'main' }) // eslint-disable-line
|
: new Vue({ el: 'main' }) // eslint-disable-line
|
||||||
CACHE.vm && CACHE.vm.$nextTick(_ => event.scrollActiveSidebar())
|
CACHE.vm && CACHE.vm.$nextTick(_ => event.scrollActiveSidebar())
|
||||||
}
|
}
|
||||||
if (OPTIONS.auto2top) setTimeout(() => event.scroll2Top(OPTIONS.auto2top), 0)
|
if (__docsify__.auto2top) setTimeout(() => event.scroll2Top(__docsify__.auto2top), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -144,13 +147,13 @@ export function renderSidebar (content) {
|
||||||
html = markdown(content)
|
html = markdown(content)
|
||||||
// find url tag
|
// find url tag
|
||||||
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
|
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
|
||||||
} else if (OPTIONS.sidebar) {
|
} else if (__docsify__.sidebar) {
|
||||||
html = tpl.tree(OPTIONS.sidebar, '<ul>')
|
html = tpl.tree(__docsify__.sidebar, '<ul>')
|
||||||
} else {
|
} else {
|
||||||
html = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
html = tpl.tree(genTree(toc, __docsify__.maxLevel), '<ul>')
|
||||||
}
|
}
|
||||||
|
|
||||||
html = (OPTIONS.name ? `<h1><a href="${OPTIONS.nameLink}">${OPTIONS.name}</a></h1>` : '') + html
|
html = (__docsify__.name ? `<h1><a href="${__docsify__.nameLink}">${__docsify__.name}</a></h1>` : '') + html
|
||||||
renderTo('aside.sidebar', html)
|
renderTo('aside.sidebar', html)
|
||||||
const target = event.activeLink('aside.sidebar', true)
|
const target = event.activeLink('aside.sidebar', true)
|
||||||
if (target) renderSubSidebar(target)
|
if (target) renderSubSidebar(target)
|
||||||
|
|
@ -160,8 +163,8 @@ export function renderSidebar (content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderSubSidebar (target) {
|
export function renderSubSidebar (target) {
|
||||||
if (!OPTIONS.subMaxLevel) return
|
if (!__docsify__.subMaxLevel) return
|
||||||
target.parentNode.innerHTML += tpl.tree(genTree(toc, OPTIONS.subMaxLevel), '<ul>')
|
target.parentNode.innerHTML += tpl.tree(genTree(toc, __docsify__.subMaxLevel), '<ul>')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,9 @@ section.cover {
|
||||||
|
|
||||||
.cover-main p:last-child a {
|
.cover-main p:last-child a {
|
||||||
border-radius: 2em;
|
border-radius: 2em;
|
||||||
border: 1px solid $color-primary;
|
border: 1px solid var(--theme-color, $color-primary);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
font-size: 1.05em;
|
font-size: 1.05em;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
padding: 0.75em 2em;
|
padding: 0.75em 2em;
|
||||||
|
|
@ -85,7 +85,7 @@ section.cover {
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
background-color: $color-primary;
|
background-color: var(--theme-color, $color-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress {
|
.progress {
|
||||||
background-color: $color-primary;
|
background-color: var(--theme-color, $color-primary);
|
||||||
height: 2px;
|
height: 2px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
@ -86,12 +86,12 @@ nav {
|
||||||
transition: color .3s;
|
transition: color .3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
border-bottom: 2px solid $color-primary;
|
border-bottom: 2px solid var(--theme-color, $color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +103,7 @@ nav {
|
||||||
ul {
|
ul {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: rgba($color-bg, .6);
|
background-color: rgba($color-bg, .6);
|
||||||
border: 1px solid $color-primary;
|
border: 1px solid var(--theme-color, $color-primary);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
@ -160,7 +160,7 @@ nav {
|
||||||
color: $color-bg;
|
color: $color-bg;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
fill: $color-primary;
|
fill: var(--theme-color, $color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,7 +246,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
background-color: $color-primary;
|
background-color: var(--theme-color, $color-primary);
|
||||||
display: block;
|
display: block;
|
||||||
size: 16px 2px;
|
size: 16px 2px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ $sidebar-width: 16em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-section a {
|
.markdown-section a {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ $sidebar-width: 16em;
|
||||||
|
|
||||||
.markdown-section blockquote {
|
.markdown-section blockquote {
|
||||||
color: #858585;
|
color: #858585;
|
||||||
border-left: 4px solid $color-primary;
|
border-left: 4px solid var(--theme-color, $color-primary);
|
||||||
margin: 2em 0;
|
margin: 2em 0;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
ul li.active>a {
|
ul li.active>a {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-section a {
|
.markdown-section a {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ body {
|
||||||
|
|
||||||
.markdown-section blockquote {
|
.markdown-section blockquote {
|
||||||
color: #858585;
|
color: #858585;
|
||||||
border-left: 4px solid $color-primary;
|
border-left: 4px solid var(--theme-color, $color-primary);
|
||||||
margin: 2em 0;
|
margin: 2em 0;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.token.string {
|
.token.string {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.token.selector {
|
.token.selector {
|
||||||
|
|
@ -201,7 +201,7 @@ body {
|
||||||
.token.control,
|
.token.control,
|
||||||
.token.directive,
|
.token.directive,
|
||||||
.token.unit {
|
.token.unit {
|
||||||
color: $color-primary;
|
color: var(--theme-color, $color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.token.keyword {
|
.token.keyword {
|
||||||
|
|
|
||||||
|
|
@ -75,3 +75,7 @@ export function tree (toc, tpl = '') {
|
||||||
export function helper (className, content) {
|
export function helper (className, content) {
|
||||||
return `<p class="${className}">${content.slice(5).trim()}</p>`
|
return `<p class="${className}">${content.slice(5).trim()}</p>`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function theme (color) {
|
||||||
|
return `<style>:root{--theme-color: ${color};}</style>`
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue