Docs: add English language support (#170)

* feat: support lang entry build

* feat: vant support lang switch

* move lang iframe-router to utils & fix router link bug

* add en-US config && add some translation

* chang async. to async_ (support superman cdn)

* add layout translation

* change nav style

* upgrade zan-doc

* fix: doc config

* upgrade zan-doc && remove useless code

* fix changelog generate path
This commit is contained in:
Yao 2017-10-06 12:33:28 +08:00 committed by GitHub
parent 265fcbf2ef
commit 64ec6ce5ac
68 changed files with 439 additions and 135 deletions

View File

@ -17,4 +17,4 @@ github_changelog_generator \
--issues-label "**处理的 Issue:**" \
--pr-label "**合并的 Pull Request (可能有不兼容改动):**" \
--no-unreleased \
-o $basepath/../docs/examples-docs/changelog-generated.md
-o $basepath/../docs/examples-docs/zh-CN/changelog-generated.md

View File

@ -16,7 +16,7 @@ const styleLoaders = [
extractExample({
src: path.resolve(__dirname, '../docs/examples-docs'),
dist: path.resolve(__dirname, '../docs/examples-dist'),
nav: docConfig['zh-CN'].nav,
nav: docConfig,
watch: !isProduction
});
@ -31,7 +31,7 @@ module.exports = {
publicPath: '/',
filename: '[name].js',
umdNamedDefine: true,
chunkFilename: 'async.[name].js'
chunkFilename: 'async_[name].js'
},
devServer: {
host: '0.0.0.0',

View File

@ -9,7 +9,7 @@ module.exports = merge(devConfig, {
publicPath: 'https://b.yzcdn.cn/zanui/vue/',
filename: '[name].[hash:8].js',
umdNamedDefine: true,
chunkFilename: 'async.[name].[chunkhash:8].js'
chunkFilename: 'async_[name].[chunkhash:8].js'
},
devtool: false,
plugins: [

View File

@ -0,0 +1,28 @@
## Changelog
### [0.9.9](https://github.com/youzan/vant/tree/v0.9.9)
`2017-09-26`
**Improvements**
- Skusupport Stepper [\#146](https://github.com/youzan/vant/pull/146) [@w91](https://github.com/w91)
**Bug Fixes**
- fix license error in packages.json [\#144](https://github.com/youzan/vant/pull/144) [@airyland](https://github.com/airyland)
- fix Waterfall scroll bug [\#145](https://github.com/youzan/vant/pull/145) [@pangxie1991](https://github.com/pangxie1991)
### [0.9.8](https://github.com/youzan/vant/tree/v0.9.8)
`2017-09-24`
**Improvements**
- add AddressList component [\#138](https://github.com/youzan/vant/pull/138) [@chenjiahan](https://github.com/chenjiahan)
- modify changelog [\#140](https://github.com/youzan/vant/pull/140) [@chenjiahan](https://github.com/chenjiahan)
**Bug Fixes**
- fix Sku message render bug [\#142](https://github.com/youzan/vant/pull/142) [@w91](https://github.com/w91)
### [0.9.7](https://github.com/youzan/vant/tree/v0.9.7)
`2017-09-21`
**Improvements**
- Checkbox: support shape prop [\#137](https://github.com/youzan/vant/pull/137) [@chenjiahan](https://github.com/chenjiahan)

View File

@ -0,0 +1,90 @@
<style>
.demo-layout {
.van-row {
padding: 0 15px;
}
.van-col {
color: #fff;
font-size: 13px;
line-height: 30px;
text-align: center;
margin-bottom: 10px;
background-clip: content-box;
&:nth-child(odd) {
background-color: #39a9ed;
}
&:nth-child(even) {
background-color: #66c6f2;
}
}
}
</style>
## Layout
Quickly and easily create layouts with `van-row` and `van-col`
### Install
``` javascript
import { Row, Col } from 'vant';
Vue.component(Row.name, Row);
Vue.component(Col.name, Col);
```
### Usage
#### Basic
Layout are based on 24-column. The attribute `span` in `Col` means the number of column the grid spans. Of course, You can use `offset` attribute to set number of spacing on the left side of the grid.
:::demo Basic Usage
```html
<van-row>
<van-col span="8">span: 8</van-col>
<van-col span="8">span: 8</van-col>
<van-col span="8">span: 8</van-col>
</van-row>
<van-row>
<van-col span="4">span: 4</van-col>
<van-col span="10" offset="4">offset: 4, span: 10</van-col>
<van-col span="6">span: 6</van-col>
</van-row>
<van-row>
<van-col offset="12" span="12">offset: 12, span: 12</van-col>
</van-row>
```
:::
#### Column Spacing
Set grid spacing using `gutter` attribute. The default value is 0
:::demo Column Spacing
```html
<van-row gutter="20">
<van-col span="8">span: 8</van-col>
<van-col span="8">span: 8</van-col>
<van-col span="8">span: 8</van-col>
</van-row>
```
:::
### API
#### Row
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| gutter | grid spacingpx | `String | Number` | - | - |
| prefix | className prefix | `String` | `van` | - |
#### Column
| Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------|
| span | number of column the grid spans | `String | Number` | - | - |
| offset | number of spacing on the left side of the grid | `String | Number` | - | - |
| prefix | className prefix | `String` | `van` | - |

View File

@ -0,0 +1,49 @@
## Vant
Mobile UI Component based on `Vue 2.0`
### Install
```shell
npm i vant -S
```
### Usage
#### 1. Use [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) (推荐)
```bash
# Install babel-plugin-import
npm i babel-plugin-import -D
```
```js
// set babel config in .babelrc or babel-loader
{
"plugins": [
["import", { "libraryName": "vant", "style": true }]
]
}
```
Then you can import components from vant, equivalent to import manually below.
```js
import { Button } from 'vant';
```
#### 2. Manually import
```js
import { Button } from 'vant/lib/button';
import 'vant/lib/vant-css/button.css';
```
#### 3. Import all components
```js
import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/vant-css/index.css';
Vue.use(Vant);
```

View File

@ -1,6 +1,6 @@
<script>
import { Toast } from 'packages';
import areaList from '../mock/area.json';
import areaList from '../../mock/area.json';
export default {
data() {

View File

@ -1,5 +1,5 @@
<script>
import AreaList from '../mock/area.json';
import AreaList from '../../mock/area.json';
export default {
data() {
@ -31,7 +31,7 @@ Vue.component(Area.name, Area);
<van-area :area-list="areaList"></van-area>
<script>
import AreaList from '../mock/area.json';
import AreaList from '../../mock/area.json';
export default {
data() {

View File

@ -1,7 +1,7 @@
## Sku 商品购买组件
<script>
import data from '../mock/sku';
import data from '../../mock/sku';
const goods = data.goods_info;
goods.picture = goods.picture[0];

View File

@ -4,6 +4,6 @@
<style lang="postcss">
body {
-webkit-font-smoothing: antialiased;
-webkit-font-smoothing: antialiased;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="app">
<zan-doc :simulator="simulator" :config="config">
<zan-doc :simulator="simulator" :config="config" :base="base">
<router-view></router-view>
</zan-doc>
</div>
@ -8,28 +8,36 @@
<script>
import docConfig from './doc.config';
import { getLang } from './utils/lang';
export default {
data() {
if (location.host === 'www.youzanyun.com') {
if (window.location.host === 'www.youzanyun.com') {
const group = docConfig['zh-CN'].nav[0].groups[0];
group.list = group.list.filter(item => item.title !== '业务组件');
}
const hash = window.location.hash;
return {
simulator: this.getSimulatorPath(),
config: docConfig['zh-CN']
simulator: `/zanui/vue/examples${hash}`,
lang: getLang()
};
},
methods: {
getSimulatorPath() {
const dir = location.hash.split('/').pop();
if (dir === 'quickstart' || dir === 'changelog') {
return '/zanui/vue/examples';
} else {
return `/zanui/vue/examples#/component/${dir}`;
}
computed: {
base() {
return `/${this.lang}/component`;
},
config() {
return docConfig[this.lang];
}
},
watch: {
'$route'(to) {
this.lang = to.meta.lang;
}
}
};

View File

@ -3,7 +3,7 @@
<h1 class="zanui-title">Zan UI</h1>
<h2 class="zanui-desc">有赞移动端 Vue 组件库</h2>
<div class="mobile-navs">
<div class="mobile-nav-item" v-for="(item, index) in data" v-if="item.showInMobile" :key="index">
<div class="mobile-nav-item" v-for="(item, index) in navList" v-if="item.showInMobile" :key="index">
<mobile-nav v-for="(group, index) in item.groups" :group="group" :base="base" :nav-key="index" :key="index" />
</div>
</div>
@ -13,17 +13,36 @@
<script>
import docConfig from '../doc.config';
import MobileNav from './mobile-nav';
import { getLang } from '../utils/lang';
export default {
data() {
return {
data: docConfig['zh-CN'].nav,
base: '/component'
docConfig,
lang: getLang()
};
},
beforeRouteEnter(to, from, next) {
next(vm => vm.lang = to.meta.lang);
},
beforeRouteUpdate(to, from, next) {
this.lang = to.meta.lang;
},
components: {
MobileNav
},
computed: {
base() {
return `${this.lang}/component`;
},
navList() {
return this.docConfig[this.lang].nav || [];
}
}
};
</script>

View File

@ -17,7 +17,7 @@
v-if="!navItem.disabled">
<router-link
active-class="active"
:to="base + navItem.path">
:to="'/' + base + navItem.path">
<p>
{{ navItem.title }}
</p>

View File

@ -5,7 +5,8 @@ module.exports = {
'首页': 'https://www.youzanyun.com/zanui',
'PC端': 'https://www.youzanyun.com/zanui/react',
'移动端': 'https://www.youzanyun.com/zanui/vue',
'微信小程序': 'https://github.com/youzan/zanui-weapp'
'微信小程序': 'https://github.com/youzan/zanui-weapp',
'English': '#/en-US/'
},
footer: {
github: 'https://github.com/youzan/vant',
@ -48,87 +49,87 @@ module.exports = {
"list": [
{
"path": "/layout",
"title": "Layout 布局"
"title": "Layout - 布局"
},
{
"path": "/badge",
"title": "Badge 徽章"
"title": "Badge - 徽章"
},
{
"path": "/button",
"title": "Button 按钮"
"title": "Button - 按钮"
},
{
"path": "/card",
"title": "Card 卡片"
"title": "Card - 卡片"
},
{
"path": "/cell",
"title": "Cell 单元格"
"title": "Cell - 单元格"
},
{
"path": "/icon",
"title": "Icon 图标"
"title": "Icon - 图标"
},
{
"path": "/image-preview",
"title": "ImagePreview 图片预览"
"title": "ImagePreview - 图片预览"
},
{
"path": "/lazyload",
"title": "Lazyload 图片懒加载"
"title": "Lazyload - 图片懒加载"
},
{
"path": "/loading",
"title": "Loading 加载"
"title": "Loading - 加载"
},
{
"path": "/nav-bar",
"title": "NavBar 导航栏"
"title": "NavBar - 导航栏"
},
{
"path": "/notice-bar",
"title": "NoticeBar 通告栏"
"title": "NoticeBar - 通告栏"
},
{
"path": "/panel",
"title": "Panel 面板"
"title": "Panel - 面板"
},
{
"path": "/popup",
"title": "Popup 弹出层"
"title": "Popup - 弹出层"
},
{
"path": "/progress",
"title": "Progress 进度条"
"title": "Progress - 进度条"
},
{
"path": "/search",
"title": "Search 搜索"
"title": "Search - 搜索"
},
{
"path": "/stepper",
"title": "Stepper 步进器"
"title": "Stepper - 步进器"
},
{
"path": "/steps",
"title": "Steps 步骤条"
"title": "Steps - 步骤条"
},
{
"path": "/swipe",
"title": "Swipe 轮播"
"title": "Swipe - 轮播"
},
{
"path": "/tab",
"title": "Tab 标签"
"title": "Tab - 标签"
},
{
"path": "/tag",
"title": "Tag 标记"
"title": "Tag - 标记"
},
{
"path": "/waterfall",
"title": "Waterfall 瀑布流"
"title": "Waterfall - 瀑布流"
}
]
},
@ -137,31 +138,31 @@ module.exports = {
"list": [
{
"path": "/checkbox",
"title": "Checkbox 复选框"
"title": "Checkbox - 复选框"
},
{
"path": "/field",
"title": "Field 输入框"
"title": "Field - 输入框"
},
{
"path": "/number-keyboard",
"title": "NumberKeyboard 数字键盘"
"title": "NumberKeyboard - 数字键盘"
},
{
"path": "/password-input",
"title": "PasswordInput 密码输入框"
"title": "PasswordInput - 密码输入框"
},
{
"path": "/radio",
"title": "Radio 单选框"
"title": "Radio - 单选框"
},
{
"path": "/switch",
"title": "Switch 开关"
"title": "Switch - 开关"
},
{
"path": "/uploader",
"title": "Uploader 图片上传"
"title": "Uploader - 图片上传"
}
]
},
@ -170,27 +171,27 @@ module.exports = {
"list": [
{
"path": "/actionsheet",
"title": "Actionsheet 行动按钮"
"title": "Actionsheet - 行动按钮"
},
{
"path": "/datetime-picker",
"title": "DatetimePicker 时间选择"
"title": "DatetimePicker - 时间选择"
},
{
"path": "/dialog",
"title": "Dialog 弹出框"
"title": "Dialog - 弹出框"
},
{
"path": "/picker",
"title": "Picker 选择器"
"title": "Picker - 选择器"
},
{
"path": "/pull-refresh",
"title": "PullRefresh 下拉刷新"
"title": "PullRefresh - 下拉刷新"
},
{
"path": "/toast",
"title": "Toast 轻提示"
"title": "Toast - 轻提示"
}
]
},
@ -199,15 +200,15 @@ module.exports = {
"list": [
{
"path": "/cell-swipe",
"title": "CellSwipe 滑动单元格"
"title": "CellSwipe - 滑动单元格"
},
{
"path": "/switch-cell",
"title": "SwitchCell 开关单元格"
"title": "SwitchCell - 开关单元格"
},
{
"path": "/tree-select",
"title": "TreeSelect 分类选择"
"title": "TreeSelect - 分类选择"
},
]
},
@ -216,40 +217,94 @@ module.exports = {
"list": [
{
"path": "/address-edit",
"title": "AddressEdit 地址编辑"
"title": "AddressEdit - 地址编辑"
},
{
"path": "/address-list",
"title": "AddressList 地址列表"
"title": "AddressList - 地址列表"
},
{
"path": "/area",
"title": "Area 省市区选择"
"title": "Area - 省市区选择"
},
{
"path": "/contact",
"title": "Contact 联系人"
"title": "Contact - 联系人"
},
{
"path": "/coupon",
"title": "Coupon 优惠券选择器"
"title": "Coupon - 优惠券选择器"
},
{
"path": "/goods-action",
"title": "GoodsAction 商品页行动点"
"title": "GoodsAction - 商品页行动点"
},
{
"path": "/submit-bar",
"title": "SubmitBar 提交订单栏"
"title": "SubmitBar - 提交订单栏"
},
{
"path": "/sku",
"title": "Sku 商品规格弹层"
"title": "Sku - 商品规格弹层"
}
]
}
]
}
]
},
"en-US": {
header: {
'Homepage': 'https://www.youzanyun.com/zanui',
'PC': 'https://www.youzanyun.com/zanui/react',
'Mobile': 'https://www.youzanyun.com/zanui/vue',
'Weapp': 'https://github.com/youzan/zanui-weapp',
'中文': '#/zh-CN'
},
footer: {
github: 'https://github.com/youzan/vant',
nav: {
'Youzan': 'https://www.youzan.com/',
'Join us': 'https://job.youzan.com/',
'Feedback': 'https://github.com/youzan/vant/issues'
}
},
nav: [
{
"name": "Essentials",
"groups": [
{
"list": [
{
"path": "/quickstart",
"title": "Getting Started",
noExample: true
},
{
"path": "/changelog",
"title": "Changelog",
noExample: true
}
]
}
]
},
// translation needed
{
"name": "Components",
"showInMobile": true,
"groups": [
{
"groupName": "Base Components",
"list": [
{
"path": "/layout",
"title": "Layout"
}
]
},
]
}
]
}
}

View File

@ -2,9 +2,9 @@ import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './ExamplesApp';
import routes from './router.config';
import { setLang } from './utils/lang';
import Vant, { Lazyload } from 'packages';
import ZanDoc from 'zan-doc';
import DemoList from './components/demo-list';
import 'packages/vant-css/src/index.css';
import 'zan-doc/src/helper/touch-simulator';
@ -16,22 +16,18 @@ Vue.use(Lazyload, {
Vue.use(VueRouter);
const routesConfig = routes(true);
routesConfig.push({
path: '/',
component: DemoList
});
const router = new VueRouter({
mode: 'hash',
base: '/zanui/vue/examples',
routes: routesConfig
});
router.afterEach(() => {
router.afterEach((route) => {
const container = document.querySelector('.examples-container');
if (container) {
document.querySelector('.examples-container').scrollTop = 0;
}
window.syncPath();
setLang(route.meta.lang);
});
window.vueRouter = router;

View File

@ -3,16 +3,12 @@ import VueRouter from 'vue-router';
import App from './ExamplesDocsApp';
import routes from './router.config';
import ZanDoc from 'zan-doc';
import isMobile from './is-mobile';
import isMobile from './utils/is-mobile';
Vue.use(VueRouter);
Vue.use(ZanDoc);
const routesConfig = routes();
routesConfig.push({
path: '/',
redirect: '/component/quickstart'
});
const router = new VueRouter({
mode: 'hash',
@ -30,7 +26,7 @@ router.beforeEach((route, redirect, next) => {
router.afterEach(() => {
window.scrollTo(0, 0);
window.syncPath();
Vue.nextTick(() => window.syncPath());
});
window.vueRouter = router;

View File

@ -1,43 +1,67 @@
import docConfig from './doc.config';
import { getLang } from './utils/lang';
import DemoList from './components/demo-list';
import componentDocs from '../examples-dist/entry-docs';
import componentDemos from '../examples-dist/entry-demos';
import './iframe-router';
const navs = docConfig['zh-CN'].nav;
import './utils/iframe-router';
const registerRoute = (isExample) => {
const route = [{
path: '/',
redirect: to => {
return `/${getLang()}/`;
}
}, {
path: '*',
redirect: '/'
redirect: to => {
return `/${getLang()}/`;
}
}];
navs.forEach(nav => {
if (isExample && !nav.showInMobile) {
return;
Object.keys(docConfig).forEach((lang, index) => {
if (isExample) {
route.push({
path: `/${lang}`,
component: DemoList,
meta: { lang }
});
} else {
route.push({
path: `/${lang}`,
redirect: `/${lang}/component/quickstart`
});
}
if (nav.groups) {
nav.groups.forEach(group => {
group.list.forEach(addRoute);
});
} else if (nav.children) {
nav.children.forEach(addRoute);
} else {
addRoute(nav);
const navs = docConfig[lang].nav || [];
navs.forEach(nav => {
if (isExample && !nav.showInMobile) {
return;
}
if (nav.groups) {
nav.groups.forEach(group => {
group.list.forEach(page => addRoute(page, lang));
});
} else if (nav.children) {
nav.children.forEach(page => addRoute(page, lang));
} else {
addRoute(nav, lang);
}
});
function addRoute(page, lang) {
const { path } = page;
if (path) {
const name = lang + '/' + path.replace('/', '');
route.push({
path: `/${lang}/component${path}`,
component: isExample ? componentDemos[name] : componentDocs[name],
meta: { lang }
});
}
}
});
function addRoute(page) {
const { path } = page;
if (path) {
const name = path.replace('/', '');
route.push({
path: '/component' + path,
component: isExample ? componentDemos[name] : componentDocs[name]
});
}
}
return route;
};

View File

@ -3,6 +3,8 @@
*/
import isMobile from './is-mobile';
import { setLang } from './lang';
import { iframeReady } from './iframe';
window.syncPath = function(dir) {
const router = window.vueRouter;
@ -17,25 +19,13 @@ window.syncPath = function(dir) {
}
};
window.changePath = function(path) {
window.changePath = function(path = '') {
const pathParts = path.split('/');
let lang = pathParts[0];
if (path[0] === '/') {
lang = pathParts[1];
}
setLang(lang);
window.vueRouter.replace(path);
};
function iframeReady(iframe, callback) {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const interval = () => {
if (iframe.contentWindow.changePath) {
callback();
} else {
setTimeout(() => {
interval();
}, 50);
}
};
if (doc.readyState === 'complete') {
interval();
} else {
iframe.onload = interval;
}
}

18
docs/src/utils/iframe.js Normal file
View File

@ -0,0 +1,18 @@
export function iframeReady(iframe, callback) {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const interval = () => {
if (iframe.contentWindow.changePath) {
callback();
} else {
setTimeout(() => {
interval();
}, 50);
}
};
if (doc.readyState === 'complete') {
interval();
} else {
iframe.onload = interval;
}
}

16
docs/src/utils/lang.js Normal file
View File

@ -0,0 +1,16 @@
const userLang = window.localStorage.getItem('VANT_LANGUAGE') || window.navigator.language || 'en-US';
let defaultLang = 'en-US';
if (userLang.indexOf('zh-') !== -1) {
defaultLang = 'zh-CN';
}
let currentLang = defaultLang;
export function getLang() {
return currentLang;
}
export function setLang(lang) {
window.localStorage.setItem('VANT_LANGUAGE', lang);
currentLang = lang;
}

View File

@ -20,7 +20,7 @@
"build:style-entry": "VUE_ENV=server node build/bin/build-style-entry.js",
"build:changelog": "sh build/build-changelog.sh",
"deploy": "npm run deploy:docs && npm run deploy:cdn && gh-pages -d docs/dist --remote youzan && rimraf docs/dist",
"deploy:cdn": "superman cdn /zanui/vue docs/dist/*.js docs/dist/*.css",
"deploy:cdn": "superman cdn /zanui/vue docs/dist/*.js docs/dist/*.css && superman cdn /zanui/vue/async_en-US docs/dist/async_en-US/*.js && superman cdn /zanui/vue/async_zh-CN docs/dist/async_zh-CN/*.js",
"deploy:docs": "rimraf docs/dist && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.config.prod.js",
"dist": "node build/bin/build-lib.js",
"clean": "rimraf lib && rimraf packages/*/lib",
@ -119,6 +119,6 @@
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.7.1",
"webpack-merge": "^4.1.0",
"zan-doc": "0.2.17"
"zan-doc": "0.3.1"
}
}

View File

@ -2973,6 +2973,14 @@ fs-extra@^3.0.1:
jsonfile "^3.0.0"
universalify "^0.1.0"
fs-extra@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950"
@ -4144,6 +4152,12 @@ jsonfile@^3.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
optionalDependencies:
graceful-fs "^4.1.6"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@ -7899,12 +7913,13 @@ yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
zan-doc@0.2.17:
version "0.2.17"
resolved "https://registry.yarnpkg.com/zan-doc/-/zan-doc-0.2.17.tgz#bea711d254d89121b52b47792aec5127fe66fedf"
zan-doc@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/zan-doc/-/zan-doc-0.3.1.tgz#f421a90eeb8e399e4257d52f671bffd14efbd28e"
dependencies:
cheerio "0.22.0"
decamelize "^1.2.0"
fs-extra "^4.0.2"
markdown-it "^8.3.2"
markdown-it-container "^2.0.0"
node-watch "^0.5.5"