feat: customize the theme color

This commit is contained in:
qingwei.li 2017-02-04 23:45:35 +08:00 • committed by cinwell.li
commit 5cc9f0514c
13 changed files with 120 additions and 42 deletions

View file

@ -1,6 +1,7 @@
{ {
"extends": ["vue"], "extends": ["vue"],
"globals": { "globals": {
"XMLHttpRequest": true "XMLHttpRequest": true,
"__docsify__": true
} }
} }

View file

@ -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

View file

@ -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)

View file

@ -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'
}
```

View file

@ -511,3 +511,17 @@ window.$docsify = {
} }
``` ```
### themeColor
自定义主题色。
```html
<script src="/lib/docsify.js" data-theme-color="#3F51B5"></script>
```
```js
window.$docsify = {
themeColor: '#3F51B5'
}
```

View file

@ -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
View 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)
})
}
})
}

View file

@ -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>')
} }
/** /**

View file

@ -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 {

View file

@ -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;

View file

@ -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;
} }

View file

@ -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 {

View file

@ -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>`
}