Merge pull request #963 from endiliey/v2

v2: move v2 wip to Docusaurus
This commit is contained in:
Endilie Y 2018-09-17 12:22:45 +08:00 committed by GitHub
commit adbae6b2ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
181 changed files with 16758 additions and 1 deletions

View file

@ -1,3 +1,4 @@
static/**/*.js
build
node_modules
v2

View file

@ -6,3 +6,4 @@ yarn.lock
website
docs
docusaurus-init
v2

1
.prettierignore Normal file
View file

@ -0,0 +1 @@
v2

View file

@ -41,7 +41,8 @@
"jest": {
"testPathIgnorePatterns": [
"/node_modules/",
"__fixtures__"
"__fixtures__",
"v2"
],
"testURL": "http://localhost/"
},

3
v2/.babelrc Normal file
View file

@ -0,0 +1,3 @@
{
"presets": ["env", "react"]
}

4
v2/.eslintignore Normal file
View file

@ -0,0 +1,4 @@
generated
__fixtures__
dist
website

23
v2/.eslintrc.js Normal file
View file

@ -0,0 +1,23 @@
const OFF = 0;
const WARNING = 1;
const ERROR = 2;
module.exports = {
env: {
browser: true,
commonjs: true,
jest: true,
node: true,
},
extends: ['airbnb', 'prettier'],
rules: {
'no-console': OFF,
'func-names': OFF,
'react/jsx-filename-extension': OFF,
'react/jsx-one-expression-per-line': OFF,
'react/prop-types': OFF,
'react/destructuring-assignment': OFF, // too many lines
'import/no-unresolved': WARNING, // because it couldn't resolve webpack alias
'react/prefer-stateless-function': WARNING,
},
};

10
v2/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
.DS_Store
.vscode
.idea
.eslintcache
node_modules
dist
yarn-error.log
generated
website/node_modules
build

3
v2/.prettierignore Normal file
View file

@ -0,0 +1,3 @@
generated
__fixtures__
dist

8
v2/.prettierrc Normal file
View file

@ -0,0 +1,8 @@
{
"bracketSpacing": false,
"jsxBracketSameLine": true,
"parser": "flow",
"printWidth": 80,
"proseWrap": "never",
"singleQuote": true
}

13
v2/README.md Normal file
View file

@ -0,0 +1,13 @@
# Munseo
## Development Server
```bash
yarn start # open http://localhost:3000/
```
## Production Build
```bash
yarn build # check website/build
```

73
v2/bin/munseo.js Normal file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env node
const chalk = require('chalk');
const semver = require('semver');
const path = require('path');
const program = require('commander');
const {build, eject, init, start} = require('../lib');
const requiredVersion = require('../package.json').engines.node;
if (!semver.satisfies(process.version, requiredVersion)) {
console.log(
chalk.red(`\nMinimum node version not met :)`) +
chalk.yellow(
`\nYou are using Node ${
process.version
}, Requirement: Node ${requiredVersion}.\n`
)
);
process.exit(1);
}
function wrapCommand(fn) {
return (...args) =>
fn(...args).catch(err => {
console.error(chalk.red(err.stack));
process.exitCode = 1;
});
}
program
.version(require('../package.json').version)
.usage('<command> [options]');
program
.command('build [siteDir]')
.description('Build website')
.option(
'-sic, --skip-image-compression <skipImageCompression>',
'Skip compression of image assets (default: false)'
)
.action((siteDir = '.', {skipImageCompression}) => {
wrapCommand(build)(path.resolve(siteDir), {skipImageCompression});
});
program
.command('eject [siteDir]')
.description('copy the default theme into website folder for customization.')
.action((siteDir = '.') => {
wrapCommand(eject)(path.resolve(siteDir));
});
program
.command('init [projectDir]')
.description('Initialize website')
.action((projectDir = '.') => {
wrapCommand(init)(path.resolve(projectDir));
});
program
.command('start [siteDir]')
.description('Start development server')
.option('-p, --port <port>', 'use specified port (default: 3000)')
.option('-h, --host <host>', 'use specified host (default: localhost')
.option('-nw, --no-watch <noWatch>', 'disable live reload (default: false)')
.action((siteDir = '.', {port, noWatch}) => {
wrapCommand(start)(path.resolve(siteDir), {port, noWatch});
});
program.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}

26
v2/docs/docusaurus.md Normal file
View file

@ -0,0 +1,26 @@
---
id: docusaurus
title: docusaurus
---
<h1 align="center">
<p align="center">Docusaurus</p>
<a href="https://docusaurus.io"><img src="/img/slash-introducing.png" alt="Docusaurus"></a>
</h1>
<p align="center">
<a href="https://www.npmjs.com/package/docusaurus"><a href="#backers" alt="sponsors on Open Collective"><img src="https://opencollective.com/Docusaurus/backers/badge.svg" /></a> <a href="#sponsors" alt="Sponsors on Open Collective"><img src="https://opencollective.com/Docusaurus/sponsors/badge.svg" /></a> <img src="https://img.shields.io/npm/v/docusaurus.svg?style=flat" alt="npm version"></a>
<a href="https://circleci.com/gh/facebook/Docusaurus"><img src="https://circleci.com/gh/facebook/Docusaurus.svg?style=shield" alt="CircleCI Status"></a>
<a href="CONTRIBUTING.md#pull-requests"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome"></a>
<a href="https://discord.gg/docusaurus"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
<a href="https://github.com/prettier/prettier"><img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"></a>
<a href="https://github.com/facebook/jest"><img src="https://img.shields.io/badge/tested_with-jest-99424f.svg" alt="Tested with Jest"></a>
</p>
## Introduction
Docusaurus is a project for easily building, deploying, and maintaining open source project websites.
* **Simple to Start** Docusaurus is built to be easy to [get up and running](https://docusaurus.io/docs/en/installation.html) in as little time possible. We've built Docusaurus to handle the website build process so you can focus on your project.
* **Localizable** Docusaurus ships with [localization support](https://docusaurus.io/docs/en/translation.html) via CrowdIn. Empower and grow your international community by translating your documentation.
* **Customizable** While Docusaurus ships with the key pages and sections you need to get started, including a home page, a docs section, a [blog](https://docusaurus.io/docs/en/blog.html), and additional support pages, it is also [customizable](https://docusaurus.io/docs/en/custom-pages.html) as well to ensure you have a site that is [uniquely yours](https://docusaurus.io/docs/en/api-pages.html).

51
v2/docs/foo/bar.md Normal file
View file

@ -0,0 +1,51 @@
---
id: bar
title: My Title
---
# Remarkable
> Experience real-time editing with Remarkable!
Click the `clear` link to start with a clean slate, or get the `permalink` to share or save your results.
***
# h1 Heading
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
## Horizontal Rules
This is horizontal rule
___
***
***
## Emphasis
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Deleted text~~
Superscript: 19^th^
Subscript: H~2~O
++Inserted text++
==Marked text==

74
v2/docs/foo/baz.md Normal file
View file

@ -0,0 +1,74 @@
---
id: baz
title: Test Markdown
---
## Images
![Sakura](/img/sakura.png)
Like links, Images also have a footnote style syntax
![Alt text][id]
With a reference later in the document defining the URL location:
## Links
[link text](http://dev.nodeca.com)
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
## Footnotes
Footnote 1 link[^first].
Footnote 2 link[^second].
Inline footnote^[Text of inline footnote] definition.
Duplicated footnote reference[^second].
[^first]: Footnote **can have markup**
and multiple paragraphs.
[^second]: Footnote text.
## Definition lists
Term 1
: Definition 1
with lazy continuation.
Term 2 with *inline markup*
: Definition 2
{ some code, part of Definition 2 }
Third paragraph of definition 2.
_Compact style:_
Term 1
~ Definition 1
Term 2
~ Definition 2a
~ Definition 2b
## Abbreviations
This is HTML abbreviation example.
It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.
*[HTML]: Hyper Text Markup Language

52
v2/docs/hello.md Normal file
View file

@ -0,0 +1,52 @@
---
id: hello
title: Hello, World !
---
## Relative links
Replace this
[highlight](highlight.md) [docusaurus](docusaurus.md)
Can't replace this
[file](file.md)
Do not replace below
```
[highlight](highlight.md) [docusaurus](docusaurus.md)
```
## Blockquotes
> Blockquotes can also be nested...
>> ...by using additional greater-than signs right next to each other...
> > > ...or with spaces between arrows.
## Lists
Unordered
+ Create a list by starting a line with `+`, `-`, or `*`
+ Sub-lists are made by indenting 2 spaces:
- Marker character change forces new list start:
* Ac tristique libero volutpat at
+ Facilisis in pretium nisl aliquet
- Nulla volutpat aliquam velit
+ Very easy!
Ordered
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
1. You can use sequential numbers...
1. ...or keep all the numbers as `1.`
Start numbering with offset:
57. foo
1. bar

44
v2/docs/highlight.md Normal file
View file

@ -0,0 +1,44 @@
---
id: highlight
title: Syntax highlighting demo
---
```cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
cout << "Hello world\n";
return 0;
}
```
```cpp
#include <iostream>
using namespace std;
int main()
{
int n, i;
bool isPrime = true;
cout << "Enter a positive integer: ";
cin >> n;
for(i = 2; i <= n / 2; ++i)
{
if(n % i == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
cout << "This is a prime number";
else
cout << "This is not a prime number";
return 0;
}
```

77
v2/lib/commands/build.js Normal file
View file

@ -0,0 +1,77 @@
const webpack = require('webpack');
const path = require('path');
const chalk = require('chalk');
const fs = require('fs-extra');
const globby = require('globby');
const load = require('../load');
const createServerConfig = require('../webpack/server');
const createClientConfig = require('../webpack/client');
const {applyConfigureWebpack} = require('../webpack/utils');
function compile(config) {
return new Promise((resolve, reject) => {
webpack(config, (err, stats) => {
if (err) {
reject(err);
}
if (stats.hasErrors()) {
stats.toJson().errors.forEach(e => {
console.error(e);
});
reject(new Error(`Failed to compile with errors.`));
}
if (stats.hasWarnings()) {
stats.toJson().warnings.forEach(warning => {
console.warn(warning);
});
}
resolve(stats.toJson({modules: false}));
});
});
}
module.exports = async function build(siteDir, cliOptions = {}) {
process.env.NODE_ENV = 'production';
console.log('Build command invoked ...');
console.log(cliOptions);
const props = await load(siteDir);
let serverConfig = createServerConfig(props).toConfig();
let clientConfig = createClientConfig(props).toConfig();
// apply user webpack config
const {
siteConfig: {configureWebpack}
} = props;
clientConfig = applyConfigureWebpack(configureWebpack, clientConfig, false);
serverConfig = applyConfigureWebpack(configureWebpack, serverConfig, true);
// Build the client bundles first.
// We cannot run them in parallel because the server need to pickup the correct client bundle name
await compile(clientConfig);
// Build the server bundles (render the static HTML and pick client bundle)
await compile(serverConfig);
// copy static files
const {outDir} = props;
const staticDir = path.resolve(siteDir, 'static');
const staticFiles = await globby(['**'], {
cwd: staticDir
});
await Promise.all(
staticFiles.map(async source => {
const fromPath = path.resolve(staticDir, source);
const toPath = path.resolve(outDir, source);
return fs.copy(fromPath, toPath);
})
);
const relativeDir = path.relative(process.cwd(), outDir);
console.log(
`\n${chalk.green('Success!')} Generated static files in ${chalk.cyan(
relativeDir
)}.\n`
);
};

16
v2/lib/commands/eject.js Normal file
View file

@ -0,0 +1,16 @@
const fs = require('fs-extra');
const chalk = require('chalk');
const path = require('path');
module.exports = async function eject(siteDir) {
const defaultTheme = path.resolve(__dirname, '..', 'theme');
const customTheme = path.resolve(siteDir, 'theme');
await fs.copy(defaultTheme, customTheme);
const relativeDir = path.relative(process.cwd(), customTheme);
console.log(
`\n${chalk.green('Success!')} Copied default theme files to ${chalk.cyan(
relativeDir
)}.\n`
);
};

7
v2/lib/commands/init.js Normal file
View file

@ -0,0 +1,7 @@
module.exports = async function init(projectDir, cliOptions = {}) {
console.log('Init command invoked ...');
console.log(projectDir);
console.log(cliOptions);
// TODO
};

124
v2/lib/commands/start.js Normal file
View file

@ -0,0 +1,124 @@
const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const webpack = require('webpack');
const chokidar = require('chokidar');
const convert = require('koa-connect');
const range = require('koa-range');
const mount = require('koa-mount');
const serveStatic = require('koa-static');
const history = require('connect-history-api-fallback');
const portfinder = require('portfinder');
const serve = require('webpack-serve');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const load = require('../load');
const createClientConfig = require('../webpack/client');
const {applyConfigureWebpack} = require('../webpack/utils');
function getHost(reqHost) {
return reqHost || 'localhost';
}
async function getPort(reqPort) {
portfinder.basePort = parseInt(reqPort, 10) || 3000;
const port = await portfinder.getPortPromise();
return port;
}
module.exports = async function start(siteDir, cliOptions = {}) {
console.log('Start command invoked ...');
console.log(cliOptions);
// Process all related files as a prop
const props = await load(siteDir);
// Reload files processing
if (!cliOptions.noWatch) {
const reload = () => {
load(siteDir).catch(err => {
console.error(chalk.red(err.stack));
});
};
const docsRelativeDir = props.siteConfig.customDocsPath;
const fsWatcher = chokidar.watch(
[`../${docsRelativeDir}/**/*.md`, 'blog/**/*.md', 'siteConfig.js'],
{
cwd: siteDir,
ignoreInitial: true
}
);
fsWatcher.on('add', reload);
fsWatcher.on('change', reload);
fsWatcher.on('unlink', reload);
fsWatcher.on('addDir', reload);
fsWatcher.on('unlinkDir', reload);
}
const port = await getPort(cliOptions.port);
const hotPort = await getPort(port + 1);
const host = getHost(cliOptions.host);
const {baseUrl} = props;
// create compiler from generated webpack config
let config = createClientConfig(props);
const {siteConfig} = props;
config.plugin('html-webpack-plugin').use(HtmlWebpackPlugin, [
{
inject: false,
hash: true,
template: path.resolve(__dirname, '../core/devTemplate.ejs'),
filename: 'index.html',
title: siteConfig.title
}
]);
config = config.toConfig();
// apply user webpack config
const {
siteConfig: {configureWebpack}
} = props;
config = applyConfigureWebpack(configureWebpack, config, false);
const compiler = webpack(config);
// webpack-serve
setTimeout(async () => {
await serve(
{},
{
compiler,
open: true,
devMiddleware: {
logLevel: 'silent'
},
hotClient: {
port: hotPort,
logLevel: 'error'
},
logLevel: 'error',
port,
host,
add: app => {
// serve static files
const staticDir = path.resolve(siteDir, 'static');
if (fs.existsSync(staticDir)) {
app.use(mount(baseUrl, serveStatic(staticDir)));
}
// enable HTTP range requests
app.use(range);
// rewrite request to `/` since dev is only a SPA
app.use(
convert(
history({
rewrites: [{from: /\.html$/, to: '/'}]
})
)
);
}
}
);
}, 1000);
};

15
v2/lib/core/App.js Normal file
View file

@ -0,0 +1,15 @@
import {renderRoutes} from 'react-router-config';
import routes from '@generated/routes'; // eslint-disable-line
import docsMetadatas from '@generated/docsMetadatas'; // eslint-disable-line
import docsSidebars from '@generated/docsSidebars'; // eslint-disable-line
import pagesMetadatas from '@generated/pagesMetadatas'; // eslint-disable-line
import siteConfig from '@generated/siteConfig'; //eslint-disable-line
export default () =>
renderRoutes(routes, {
docsMetadatas,
docsSidebars,
pagesMetadatas,
siteConfig
});

View file

@ -0,0 +1,19 @@
import React from 'react';
import {BrowserRouter} from 'react-router-dom';
import ReactDOM from 'react-dom';
import App from './App';
import prerender from './prerender';
import routes from '@generated/routes'; // eslint-disable-line
// Client side render (e.g: running in browser) to become single-page application (SPA)
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
prerender(routes, window.location.pathname).then(() => {
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('app')
);
});
}

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
</body>
</html>

18
v2/lib/core/prerender.js Normal file
View file

@ -0,0 +1,18 @@
import {matchRoutes} from 'react-router-config';
/**
* This helps us to make sure all the async component for that particular route
* is loaded before rendering. This is to avoid loading screens on first page load
*/
export default function prerender(routeConfig, providedLocation) {
const matches = matchRoutes(routeConfig, providedLocation);
return Promise.all(
matches.map(match => {
const {component} = match.route;
if (component && component.preload) {
return component.preload();
}
return undefined;
})
);
}

View file

@ -0,0 +1,59 @@
import React from 'react';
import {StaticRouter} from 'react-router-dom';
import ReactDOMServer from 'react-dom/server';
import Helmet from 'react-helmet';
import App from './App';
import prerender from './prerender';
import routes from '@generated/routes'; // eslint-disable-line
import webpackClientStats from '@build/client.stats.json'; //eslint-disable-line
// Renderer for static-site-generator-webpack-plugin (async rendering via promises)
export default function render(locals) {
return prerender(routes, locals.path).then(() => {
const context = {};
const appHtml = ReactDOMServer.renderToString(
<StaticRouter location={locals.path} context={context}>
<App />
</StaticRouter>
);
const helmet = Helmet.renderStatic();
const htmlAttributes = helmet.htmlAttributes.toString();
const bodyAttributes = helmet.bodyAttributes.toString();
const metaStrings = [
helmet.title.toString(),
helmet.meta.toString(),
helmet.link.toString()
];
const metaHtml = metaStrings.filter(Boolean).join('\n ');
const assets = webpackClientStats.assetsByChunkName.main;
const jsFiles = assets.filter(value => value.match(/\.js$/));
const cssFiles = assets.filter(value => value.match(/\.css$/));
const {baseUrl} = locals;
const html = `
<!DOCTYPE html>
<html${htmlAttributes ? ` ${htmlAttributes}` : ''}>
<head>
${metaHtml}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${cssFiles.map(
cssFile =>
`<link rel="stylesheet" type="text/css" href="${baseUrl}${cssFile}" />`
)}
</head>
<body${bodyAttributes ? ` ${bodyAttributes}` : ''}>
<div id="app">${appHtml}</div>
${jsFiles.map(
jsFile =>
`<script type="text/javascript" src="${baseUrl}${jsFile}"></script>`
)}
</body>
</html>
`;
return html;
});
}

11
v2/lib/index.js Normal file
View file

@ -0,0 +1,11 @@
const build = require('./commands/build');
const init = require('./commands/init');
const start = require('./commands/start');
const eject = require('./commands/eject');
module.exports = {
build,
eject,
init,
start
};

67
v2/lib/load/config.js Normal file
View file

@ -0,0 +1,67 @@
const fs = require('fs-extra');
const path = require('path');
module.exports = function loadConfig(siteDir, deleteCache = true) {
const configPath = path.resolve(siteDir, 'siteConfig.js');
if (deleteCache) {
delete require.cache[configPath];
}
let config = {};
if (fs.existsSync(configPath)) {
config = require(configPath); // eslint-disable-line
}
const requiredFields = [
'title',
'tagline',
'organizationName',
'projectName',
'baseUrl'
];
const optionalFields = [
'customDocsPath',
'defaultLanguage',
'highlight',
'markdownPlugins',
'configureWebpack',
'chainWebpack',
'docsUrl',
'customFields'
];
const missingFields = requiredFields.filter(field => !config[field]);
if (missingFields && missingFields.length > 0) {
throw new Error(
`${missingFields.join(', ')} fields are missing in siteConfig.js`
);
}
/* Fill default value */
const defaultConfig = {
customDocsPath: 'docs',
docsUrl: 'docs'
};
Object.keys(defaultConfig).forEach(field => {
if (!config[field]) {
config[field] = defaultConfig[field];
}
});
/*
User's own array of custom fields,
e.g: if they want to include some field so they can access it later from `props.siteConfig`
*/
const {customFields = []} = config;
/* We don't allow useless/ not meaningful field */
const allowedFields = [...requiredFields, ...optionalFields, ...customFields];
const uselessFields = Object.keys(config).filter(
field => !allowedFields.includes(field)
);
if (uselessFields && uselessFields.length > 0) {
throw new Error(
`${uselessFields.join(', ')} fields are useless in siteConfig.js`
);
}
return config;
};

129
v2/lib/load/docs/index.js Normal file
View file

@ -0,0 +1,129 @@
const path = require('path');
const globby = require('globby');
const createOrder = require('./order');
const loadSidebars = require('./sidebars');
const processMetadata = require('./metadata');
const {getSubFolder, idx} = require('../utils');
async function loadDocs({siteDir, docsDir, env, siteConfig}) {
// @tested - load all sidebars including versioned sidebars
const docsSidebars = loadSidebars({siteDir, env});
// @tested - build the docs ordering such as next, previous, category and sidebar
const order = createOrder(docsSidebars);
/* Settle versions & translations from environment */
const translationEnabled = idx(env, ['translation', 'enabled']);
const enabledLanguages =
translationEnabled && idx(env, ['translation', 'enabledLanguages']);
const enabledLangTags =
(enabledLanguages && enabledLanguages.map(lang => lang.tag)) || [];
const defaultLangTag = idx(env, ['translation', 'defaultLanguage', 'tag']);
const versioningEnabled = idx(env, ['versioning', 'enabled']);
const versions =
(versioningEnabled && idx(env, ['versioning', 'versions'])) || [];
/* Prepare metadata container */
const docsMetadatas = {};
/* metadata for default docs files */
const docsFiles = await globby(['**/*.md'], {
cwd: docsDir
});
await Promise.all(
docsFiles.map(async source => {
/*
Do not allow reserved version/ translated folder name in 'docs'
e.g: 'docs/version-1.0.0/' should not be allowed as it can cause unwanted bug
*/
const subFolder = getSubFolder(path.resolve(docsDir, source), docsDir);
const versionsFolders = versions.map(version => `version-${version}`);
if ([...enabledLangTags, ...versionsFolders].includes(subFolder)) {
throw new Error(`You cannot have a folder named 'docs/${subFolder}/'`);
}
const metadata = await processMetadata(
source,
docsDir,
env,
order,
siteConfig
);
docsMetadatas[metadata.id] = metadata;
})
);
/* metadata for non-default-language docs */
if (translationEnabled) {
const translatedDir = path.join(siteDir, 'translated_docs');
const translatedFiles = await globby(['**/*.md'], {
cwd: translatedDir
});
await Promise.all(
translatedFiles.map(async source => {
/*
Do not process disabled & default languages folder in `translated_docs`
e.g: 'translated_docs/ja/**' should not be processed if lang 'ja' is disabled
*/
const translatedFilePath = path.resolve(translatedDir, source);
const detectedLangTag = getSubFolder(translatedFilePath, translatedDir);
if (
detectedLangTag === defaultLangTag ||
!enabledLangTags.includes(detectedLangTag)
) {
return;
}
const metadata = await processMetadata(
source,
translatedDir,
env,
order,
siteConfig
);
docsMetadatas[metadata.id] = metadata;
})
);
}
/* metadata for versioned docs */
if (versioningEnabled) {
const versionedDir = path.join(siteDir, 'versioned_docs');
const versionedFiles = await globby(['**/*.md'], {
cwd: versionedDir
});
await Promise.all(
versionedFiles.map(async source => {
const metadata = await processMetadata(
source,
versionedDir,
env,
order,
siteConfig
);
docsMetadatas[metadata.id] = metadata;
})
);
}
/* Get the titles of the previous and next ids so that we can use them */
Object.keys(docsMetadatas).forEach(currentID => {
const previousID = idx(docsMetadatas, [currentID, 'previous']);
if (previousID) {
const previousTitle = idx(docsMetadatas, [previousID, 'title']);
docsMetadatas[currentID].previous_title = previousTitle || 'Previous';
}
const nextID = idx(docsMetadatas, [currentID, 'next']);
if (nextID) {
const nextTitle = idx(docsMetadatas, [nextID, 'title']);
docsMetadatas[currentID].next_title = nextTitle || 'Next';
}
});
return {
docsSidebars,
docsMetadatas
};
}
module.exports = loadDocs;

View file

@ -0,0 +1,170 @@
const fs = require('fs-extra');
const path = require('path');
const {getSubFolder, idx, parse} = require('../utils');
function getLanguage(filepath, refDir, env) {
const translationEnabled = idx(env, ['translation', 'enabled']);
if (translationEnabled) {
const detectedLangTag = getSubFolder(filepath, refDir);
const enabledLanguages = idx(env, ['translation', 'enabledLanguages']);
const langTags =
(enabledLanguages && enabledLanguages.map(lang => lang.tag)) || [];
if (langTags.includes(detectedLangTag)) {
return detectedLangTag;
}
const defaultLanguage = idx(env, ['translation', 'defaultLanguage']);
if (defaultLanguage && defaultLanguage.tag) {
return defaultLanguage.tag;
}
}
return undefined;
}
function getVersion(filepath, refDir, env) {
const versioningEnabled = idx(env, ['versioning', 'enabled']);
if (versioningEnabled) {
const subFolder = getSubFolder(filepath, refDir);
if (subFolder) {
const detectedVersion = subFolder.replace(/^version-/, '');
const versions = idx(env, ['versioning', 'versions']) || [];
if (versions.includes(detectedVersion)) {
return detectedVersion;
}
}
return 'next';
}
return undefined;
}
module.exports = async function processMetadata(
source,
refDir,
env,
order,
siteConfig
) {
const filepath = path.resolve(refDir, source);
const fileString = await fs.readFile(filepath, 'utf-8');
const {metadata} = parse(fileString);
/* default id is the file name */
if (!metadata.id) {
metadata.id = path.basename(source, path.extname(source));
}
if (metadata.id.includes('/')) {
throw new Error('Document id cannot include "/".');
}
/* default title is the id */
if (!metadata.title) {
metadata.title = metadata.id;
}
/* language */
const language = getLanguage(filepath, refDir, env);
metadata.language = language;
const langPart = (language && `${language}/`) || '';
/* version */
const defaultLangTag = idx(env, ['translation', 'defaultLanguage', 'tag']);
let versionRefDir = refDir;
if (language && language !== defaultLangTag) {
versionRefDir = path.join(refDir, language);
}
const version = getVersion(filepath, versionRefDir, env);
metadata.version = version;
const latestVersion = idx(env, ['versioning', 'latestVersion']);
const versionPart =
(version && version !== latestVersion && `${version}/`) || '';
/*
Convert temporarily metadata.id to the form of dirname/id without version/lang prefix
ex: file `versioned_docs/version-1.0.0/en/foo/bar.md` with id `version-1.0.0-bar` => `foo/bar`
*/
if (language) {
metadata.id = metadata.id.replace(new RegExp(`^${language}-`), '');
}
if (version) {
metadata.id = metadata.id.replace(new RegExp(`^version-${version}-`), '');
}
const dirName = path.dirname(source);
if (dirName !== '.') {
let prefix = dirName;
if (language) {
prefix = prefix.replace(new RegExp(`^${language}`), '');
}
prefix = prefix.replace(/^\//, '');
if (version) {
prefix = prefix.replace(new RegExp(`^version-${version}`), '');
}
prefix = prefix.replace(/^\//, '');
if (prefix) {
metadata.id = `${prefix}/${metadata.id}`;
}
}
/*
The docs file source
e.g: `@docs/hello.md` or `@versioned_docs/version-1.0.0/hello.md`
*/
if (language && language !== defaultLangTag) {
metadata.source = `@translated_docs/${source}`;
} else if (version && version !== 'next') {
metadata.source = `@versioned_docs/${source}`;
} else {
metadata.source = `@docs/${source}`;
}
/* Build the permalink */
const {baseUrl, docsUrl} = siteConfig;
/*
if user has own custom permalink defined in frontmatter
e.g: :baseUrl:docsUrl/:langPart/:versionPart/endiliey/:id
*/
if (metadata.permalink) {
metadata.permalink = path.resolve(
metadata.permalink
.replace(/:baseUrl/, baseUrl)
.replace(/:docsUrl/, docsUrl)
.replace(/:langPart/, langPart)
.replace(/:versionPart/, versionPart)
.replace(/:id/, metadata.id)
);
} else {
metadata.permalink = `${baseUrl}${docsUrl}/${langPart}${versionPart}${
metadata.id
}`;
}
/* if version */
if (version && version !== 'next') {
metadata.id = `version-${version}-${metadata.id}`;
}
/* save localized id before adding language on it */
metadata.localized_id = metadata.id;
/* if language */
if (language) {
metadata.id = `${language}-${metadata.id}`;
}
/* Determine order */
const id = metadata.localized_id;
if (order[id]) {
metadata.sidebar = order[id].sidebar;
metadata.category = order[id].category;
if (order[id].next) {
metadata.next_id = order[id].next;
metadata.next = (language ? `${language}-` : '') + order[id].next;
}
if (order[id].previous) {
metadata.previous_id = order[id].previous;
metadata.previous = (language ? `${language}-` : '') + order[id].previous;
}
}
return metadata;
};

36
v2/lib/load/docs/order.js Normal file
View file

@ -0,0 +1,36 @@
// build the docs meta such as next, previous, category and sidebar
module.exports = function createOrder(allSidebars = {}) {
const order = {};
if (!allSidebars) {
return order;
}
Object.keys(allSidebars).forEach(sidebar => {
const categories = allSidebars[sidebar];
let ids = [];
const categoryOrder = [];
Object.keys(categories).forEach(category => {
ids = ids.concat(categories[category]);
// eslint-disable-next-line
for (let i = 0; i < categories[category].length; i++) {
categoryOrder.push(category);
}
});
// eslint-disable-next-line
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
let previous;
let next;
if (i > 0) previous = ids[i - 1];
if (i < ids.length - 1) next = ids[i + 1];
order[id] = {
previous,
next,
sidebar,
category: categoryOrder[i]
};
}
});
return order;
};

View file

@ -0,0 +1,35 @@
const fs = require('fs-extra');
const path = require('path');
const {idx} = require('../utils');
module.exports = function loadSidebars({siteDir, env}) {
let allSidebars = {};
// current sidebars
const sidebarsJSONFile = path.join(siteDir, 'sidebars.json');
if (fs.existsSync(sidebarsJSONFile)) {
allSidebars = require(sidebarsJSONFile); // eslint-disable-line
}
// versioned sidebars
if (idx(env, ['versioning', 'enabled'])) {
const versions = idx(env, ['versioning', 'versions']);
if (Array.isArray(versions)) {
versions.forEach(version => {
const versionedSidebarsJSONFile = path.join(
siteDir,
'versioned_sidebars',
`version-${version}-sidebars.json`
);
if (fs.existsSync(versionedSidebarsJSONFile)) {
const sidebar = require(versionedSidebarsJSONFile); // eslint-disable-line
Object.assign(allSidebars, sidebar);
} else {
const missingFile = path.relative(siteDir, versionedSidebarsJSONFile);
throw new Error(`Failed to load ${missingFile}. It does not exist.`);
}
});
}
}
return allSidebars;
};

60
v2/lib/load/env.js Normal file
View file

@ -0,0 +1,60 @@
const fs = require('fs-extra');
const path = require('path');
const {idx} = require('./utils');
module.exports = function loadEnv({siteDir, siteConfig}) {
// Translation
const translation = {
enabled: false,
enabledLanguages: [],
defaultLanguage: {}
};
const languagesFile = path.join(siteDir, 'languages.js');
if (fs.existsSync(languagesFile)) {
const languages = require(languagesFile); // eslint-disable-line
/* Enabled languages */
const enabledLanguages = languages.filter(lang => lang.enabled);
if (!enabledLanguages || enabledLanguages.length === 0) {
throw new Error(`Please at least enable one language in 'languages.js'`);
}
translation.enabledLanguages = enabledLanguages;
/* Default Language */
const {defaultLanguage: defaultLanguageTag} = siteConfig;
const defaultLanguage = enabledLanguages.find(
lang => lang.tag === defaultLanguageTag
);
if (!defaultLanguage) {
throw new Error(
`Please set a default language in 'siteConfig.js' which is enabled in 'languages.js'`
);
}
translation.defaultLanguage = defaultLanguage;
translation.enabled = true;
}
// Versioning
const versioning = {
enabled: false,
latestVersion: null,
defaultVersion: null,
versions: []
};
const versionsJSONFile = path.join(siteDir, 'versions.json');
if (fs.existsSync(versionsJSONFile)) {
versioning.enabled = true;
versioning.versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8'));
versioning.latestVersion = idx(versioning, ['versions', 0]);
const {defaultVersionShown} = siteConfig;
versioning.defaultVersion = defaultVersionShown || versioning.latestVersion;
}
return {
translation,
versioning
};
};

90
v2/lib/load/index.js Normal file
View file

@ -0,0 +1,90 @@
const path = require('path');
const loadConfig = require('./config');
const loadDocs = require('./docs');
const loadEnv = require('./env');
const loadPages = require('./pages');
const loadTheme = require('./theme');
const {generate} = require('./utils');
const genRoutesConfig = require('./routes');
module.exports = async function load(siteDir) {
// @tested - siteConfig
const siteConfig = loadConfig(siteDir);
await generate(
'siteConfig.js',
`export default ${JSON.stringify(siteConfig, null, 2)};`
);
// @tested - env
const env = loadEnv({siteDir, siteConfig});
// docs
const docsDir = path.resolve(siteDir, '..', siteConfig.customDocsPath);
const {docsMetadatas, docsSidebars} = await loadDocs({
siteDir,
docsDir,
env,
siteConfig
});
await generate(
'docsMetadatas.js',
`export default ${JSON.stringify(docsMetadatas, null, 2)};`
);
await generate(
'docsSidebars.js',
`export default ${JSON.stringify(docsSidebars, null, 2)};`
);
/* Create source to metadata mapping */
const sourceToMetadata = {};
Object.values(docsMetadatas).forEach(
({source, version, permalink, language}) => {
sourceToMetadata[source] = {
version,
permalink,
language
};
}
);
// pages
const pagesDir = path.resolve(siteDir, 'pages');
const pagesMetadatas = await loadPages(pagesDir);
await generate(
'pagesMetadatas.js',
`export default ${JSON.stringify(pagesMetadatas, null, 2)};`
);
// resolve outDir
const outDir = path.resolve(siteDir, 'build');
// resolve the theme
const themePath = loadTheme(siteDir);
const {baseUrl} = siteConfig;
const versionedDir = path.join(siteDir, 'versioned_docs');
const translatedDir = path.join(siteDir, 'translated_docs');
const props = {
siteConfig,
siteDir,
docsDir,
docsMetadatas,
docsSidebars,
env,
pagesDir,
pagesMetadatas,
outDir,
themePath,
baseUrl,
sourceToMetadata,
versionedDir,
translatedDir
};
// Generate React Router Config
const routesConfig = await genRoutesConfig(props);
await generate('routes.js', routesConfig);
return props;
};

18
v2/lib/load/pages.js Normal file
View file

@ -0,0 +1,18 @@
const globby = require('globby');
const {encodePath, fileToPath} = require('./utils');
async function loadPages(pagesDir) {
const pagesFiles = await globby(['**/*.js'], {
cwd: pagesDir
});
const pagesMetadatas = await Promise.all(
pagesFiles.map(async source => ({
path: encodePath(fileToPath(source)),
source
}))
);
return pagesMetadatas;
}
module.exports = loadPages;

58
v2/lib/load/routes.js Normal file
View file

@ -0,0 +1,58 @@
async function genRoutesConfig({docsMetadatas = {}, pagesMetadatas = []}) {
function genDocsRoute(metadata) {
const {permalink, source} = metadata;
return `
{
path: ${JSON.stringify(permalink)},
exact: true,
component: Loadable({
loader: () => import(${JSON.stringify(source)}),
loading: Loading,
render(loaded, props) {
let Content = loaded.default;
return (
<Docs {...props} metadata={${JSON.stringify(metadata)}}>
<Content />
</Docs>
);
}
})
}`;
}
function genPagesRoute({path: pagesPath, source}) {
return `
{
path: ${JSON.stringify(pagesPath)},
exact: true,
component: Loadable({
loader: () => import('@pages/${source}'),
loading: Loading
})
}`;
}
const notFoundRoute = `,
{
path: '*',
component: NotFound
}`;
const docsRoutes = Object.values(docsMetadatas)
.map(genDocsRoute)
.join(',');
return (
`import React from 'react';\n` +
`import Loadable from 'react-loadable';\n` +
`import Loading from '@theme/Loading';\n` +
`import Docs from '@theme/Docs';\n` +
`import NotFound from '@theme/NotFound';\n` +
`const routes = [${docsRoutes},${pagesMetadatas
.map(genPagesRoute)
.join(',')}${notFoundRoute}\n];\n` +
`export default routes;\n`
);
}
module.exports = genRoutesConfig;

20
v2/lib/load/theme.js Normal file
View file

@ -0,0 +1,20 @@
const fs = require('fs-extra');
const path = require('path');
module.exports = function loadConfig(siteDir) {
const customThemePath = path.resolve(siteDir, 'theme');
const themePath = fs.existsSync(customThemePath)
? customThemePath
: path.resolve(__dirname, '../theme');
const themeComponents = ['Docs', 'Loading', 'NotFound', 'Markdown'];
themeComponents.forEach(component => {
if (!require.resolve(path.join(themePath, component))) {
throw new Error(
`Failed to load ${themePath}/${component}. It does not exist.`
);
}
});
return themePath;
};

81
v2/lib/load/utils.js Normal file
View file

@ -0,0 +1,81 @@
const path = require('path');
const fm = require('front-matter');
const escapeStringRegexp = require('escape-string-regexp');
const fs = require('fs-extra');
const genPath = path.resolve(__dirname, '../core/generated');
fs.ensureDirSync(genPath);
const genCache = new Map();
async function generate(file, content) {
const cached = genCache.get(file);
if (cached !== content) {
await fs.writeFile(path.join(genPath, file), content);
genCache.set(file, content);
}
}
const indexRE = /(^|.*\/)index\.(md|js)$/i;
const extRE = /\.(md|js)$/;
function fileToPath(file) {
if (indexRE.test(file)) {
return file.replace(indexRE, '/$1');
}
return `/${file.replace(extRE, '').replace(/\\/g, '/')}`;
}
function encodePath(userpath) {
return userpath
.split('/')
.map(item => encodeURIComponent(item))
.join('/');
}
function fileToComponentName(file) {
const ext = extRE.exec(file)[1];
let str = file.replace(extRE, '');
str = str.replace(/([A-Z])/g, ' $1');
str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase();
str = str.charAt(0).toUpperCase() + str.slice(1);
str = str.replace(/[\W_]+(\w|$)/g, (_, ch) => ch.toUpperCase());
return ext ? ext.toUpperCase() + str : str;
}
function idx(target, keyPaths) {
return (
target &&
(Array.isArray(keyPaths)
? keyPaths.reduce((obj, key) => obj && obj[key], target)
: target[keyPaths])
);
}
function getSubFolder(file, refDir) {
const separator = escapeStringRegexp(path.sep);
const baseDir = escapeStringRegexp(path.basename(refDir));
const regexSubFolder = new RegExp(
`${baseDir}${separator}(.*?)${separator}.*`
);
const match = regexSubFolder.exec(file);
return match && match[1];
}
function parse(fileString) {
if (!fm.test(fileString)) {
return {metadata: null, content: fileString};
}
const {attributes: metadata, body: content} = fm(fileString);
return {metadata, content};
}
module.exports = {
encodePath,
generate,
fileToPath,
fileToComponentName,
getSubFolder,
idx,
parse
};

View file

@ -0,0 +1,80 @@
/* eslint-disable */
import React from 'react';
import {Link} from 'react-router-dom';
import Helmet from 'react-helmet';
import styles from './styles.css';
import Layout from '@theme/Layout'; // eslint-disable-line
export default class Docs extends React.Component {
renderSidebar(metadata, docsSidebars, docsMetadatas) {
const {sidebar, language, id: thisID} = metadata;
if (!sidebar || !docsSidebars) {
return null;
}
const thisSidebar = docsSidebars[sidebar];
return (
thisSidebar &&
Object.keys(thisSidebar).map(categoryName => {
return (
<div className="navGroup" key={categoryName}>
<h3 className="navGroupCategoryTitle">{categoryName}</h3>
<ul>
{thisSidebar[categoryName].map(rawLinkID => {
const linkID = (language ? `${language}-` : '') + rawLinkID;
const linkMetadata = docsMetadatas[linkID];
if (!linkMetadata) {
throw new Error(
`Improper sidebars.json file, document with id '${linkID}' not found.`
);
}
const linkClassName =
linkID === thisID ? 'navListItemActive' : 'navListItem';
return (
<li className={linkClassName} key={linkID}>
<Link className="navItem" to={linkMetadata.permalink}>
{linkMetadata.sidebar_label || linkMetadata.title}
</Link>
</li>
);
})}
</ul>
</div>
);
})
);
}
render() {
const {
route,
siteConfig,
docsMetadatas,
docsSidebars,
metadata
} = this.props;
return (
<Layout {...this.props}>
<Helmet>
<title>{(metadata && metadata.title) || siteConfig.title}</title>
</Helmet>
<div>{this.renderSidebar(metadata, docsSidebars, docsMetadatas)}</div>
<div>
{metadata.previous &&
docsMetadatas[metadata.previous] && (
<Link to={docsMetadatas[metadata.previous].permalink}>
<span> {metadata.previous_title}</span>
</Link>
)}
{' ⚫️ '}
{metadata.next &&
docsMetadatas[metadata.next] && (
<Link to={docsMetadatas[metadata.next].permalink}>
<span>{metadata.next_title} </span>
</Link>
)}
</div>
<div className={styles.mainContainer}>{this.props.children}</div>
</Layout>
);
}
}

View file

@ -0,0 +1,10 @@
.mainContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 40px;
margin-bottom: 30px;
margin-left: auto;
margin-right: auto;
justify-content: center;
}

View file

@ -0,0 +1,29 @@
import React from 'react';
import {Link} from 'react-router-dom';
import styles from './styles.css';
/* eslint-disable react/prefer-stateless-function */
export default class Layout extends React.Component {
render() {
const {children, pagesMetadatas, docsMetadatas = {}, location} = this.props;
const docsLinks = Object.values(docsMetadatas).map(data => ({
path: `${data.permalink}`
}));
const routeLinks = [...pagesMetadatas, ...docsLinks].map(
data =>
data.path !== location.pathname && (
<li key={data.path}>
<Link to={data.path}>{data.path}</Link>
</li>
)
);
return (
<div>
{children}
<div className={styles.footer}>
<ul className={styles.routeLinks}>{routeLinks}</ul>
</div>
</div>
);
}
}

View file

@ -0,0 +1,39 @@
.footer {
color: #777;
margin-top: 30px;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.routeLinks {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.routeLinks li {
display: inline;
}
.routeLinks li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.routeLinks li a.selected,
.routeLinks li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.routeLinks li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}

11
v2/lib/theme/Loading.js Normal file
View file

@ -0,0 +1,11 @@
import React from 'react';
export default props => {
if (props.error) {
return <div align="center">Error</div>;
}
if (props.pastDelay) {
return <div align="center">Loading...</div>;
}
return null;
};

View file

@ -0,0 +1,22 @@
import toSlug from './toSlug';
function anchors(md) {
const originalRender = md.renderer.rules.heading_open;
// eslint-disable-next-line
md.renderer.rules.heading_open = function(tokens, idx, options, env) {
const textToken = tokens[idx + 1];
if (textToken.content) {
const anchor = toSlug(textToken.content, env);
return `<h${
tokens[idx].hLevel
}><a class="anchor" aria-hidden="true" id="${anchor}"></a><a href="#${anchor}" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>`;
}
return originalRender(tokens, idx, options, env);
};
}
module.exports = anchors;

View file

@ -0,0 +1,22 @@
const hljs = require('highlight.js');
const chalk = require('chalk');
const escapeHtml = require('escape-html');
export default (str, rawLang) => {
if (rawLang === 'text' || !rawLang) {
return escapeHtml(str);
}
const lang = rawLang.toLowerCase();
try {
if (hljs.getLanguage(lang)) {
return hljs.highlight(lang, str).value;
}
} catch (e) {
console.error(
chalk.yellow(
`Highlight.js syntax highlighting for language "${lang}" is not supported.`
)
);
}
return hljs.highlightAuto(str).value;
};

View file

@ -0,0 +1,94 @@
/* eslint-disable */
import React from 'react';
import Markdown from 'remarkable';
import Helmet from 'react-helmet';
import highlight from './highlight';
import anchors from './anchors';
class MarkdownBlock extends React.Component {
content() {
if (this.props.source) {
return (
<span
dangerouslySetInnerHTML={{
__html: this.renderMarkdown(this.props.source)
}}
/>
);
}
return React.Children.map(this.props.children, child => {
if (typeof child === 'string') {
return (
<span
dangerouslySetInnerHTML={{__html: this.renderMarkdown(child)}}
/>
);
}
return child;
});
}
renderMarkdown(source) {
const alias = {
js: 'jsx'
};
const {siteConfig} = this.props;
const md = new Markdown({
langPrefix: 'hljs css language-',
highlight: highlight,
html: true,
linkify: true
});
// Register anchors plugin
md.use(anchors);
// Allow client sites to register their own plugins
if (siteConfig.markdownPlugins) {
siteConfig.markdownPlugins.forEach(plugin => {
md.use(plugin);
});
}
const html = md.render(source);
// Ensure fenced code blocks use Highlight.js hljs class
// https://github.com/jonschlinkert/remarkable/issues/224
return html.replace(/<pre><code>/g, '<pre><code class="hljs">');
}
render() {
const {siteConfig} = this.props;
const highlight = Object.assign(
{},
{
version: '9.12.0',
theme: 'default'
},
siteConfig.highlight
);
// Use user-provided themeUrl if it exists, else construct one from version and theme.
const highlightThemeURL = highlight.themeUrl
? highlight.themeUrl
: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${
highlight.version
}/styles/${highlight.theme}.min.css`;
return (
<div>
<Helmet>
<link rel="stylesheet" type="text/css" href={highlightThemeURL} />
</Helmet>
{this.content()}
</div>
);
}
}
MarkdownBlock.defaultProps = {
siteConfig: {}
};
export default MarkdownBlock;

View file

@ -0,0 +1,68 @@
/* eslint-disable */
const letters =
'\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC';
const numbers =
'\u0030-\u0039\u00B2\u00B3\u00B9\u00BC-\u00BE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19';
const exceptAlphanum = new RegExp(`[^${[letters, numbers].join('')}]`, 'g');
/**
* Converts a string to a slug, that can be used in heading anchors
*
* @param {string} string
* @param {Object} [context={}] - an optional context to track used slugs and
* ensure that new slug will be unique
*
* @return {string}
*/
module.exports = (string, context = {}) => {
// var accents = "àáäâèéëêìíïîòóöôùúüûñç";
const accents =
'\u00e0\u00e1\u00e4\u00e2\u00e8' +
'\u00e9\u00eb\u00ea\u00ec\u00ed\u00ef' +
'\u00ee\u00f2\u00f3\u00f6\u00f4\u00f9' +
'\u00fa\u00fc\u00fb\u00f1\u00e7';
const without = 'aaaaeeeeiiiioooouuuunc';
let slug = string
.toString()
// Handle uppercase characters
.toLowerCase()
// Handle accentuated characters
.replace(new RegExp(`[${accents}]`, 'g'), c =>
without.charAt(accents.indexOf(c))
)
// Replace `.`, `(` and `?` with blank string like Github does
.replace(/\.|\(|\?/g, '')
// Dash special characters
.replace(exceptAlphanum, '-')
// Compress multiple dash
.replace(/-+/g, '-')
// Trim dashes
.replace(/^-|-$/g, '');
// Add trailing `-` if string contains ` ...` in the end like Github does
if (/\s[.]{1,}/.test(string)) {
slug += '-';
}
if (!context.slugStats) {
context.slugStats = {};
}
if (typeof context.slugStats[slug] === 'number') {
// search for an index, that will not clash with an existing headings
while (
typeof context.slugStats[`${slug}-${++context.slugStats[slug]}`] ===
'number'
);
slug += `-${context.slugStats[slug]}`;
}
// we are tracking both original anchors and suffixed to avoid future name
// clashing with headings with numbers e.g. `#Foo 1` may clash with the second `#Foo`
context.slugStats[slug] = 0;
return slug;
};

18
v2/lib/theme/NotFound.js Normal file
View file

@ -0,0 +1,18 @@
import React from 'react';
import Layout from '@theme/Layout';
export default class NotFound extends React.Component {
render() {
return (
<Layout>
<div>404 Page Not Found</div>
<div>
<img
alt="Not found"
src="https://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX3889253.jpg"
/>
</div>
</Layout>
);
}
}

133
v2/lib/webpack/base.js Normal file
View file

@ -0,0 +1,133 @@
const Config = require('webpack-chain');
const CSSExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const mdLoader = require.resolve('./loader/markdown');
module.exports = function createBaseConfig(props, isServer) {
const {
siteConfig,
outDir,
themePath,
docsDir,
pagesDir,
siteDir,
sourceToMetadata,
versionedDir,
translatedDir,
baseUrl
} = props;
const config = new Config();
const isProd = process.env.NODE_ENV === 'production';
config
.mode(isProd ? 'production' : 'development')
.output.path(outDir)
.filename(isProd ? '[name].[chunkhash].js' : '[name].js')
.publicPath(isProd ? baseUrl : '/');
if (!isProd) {
config.devtool('cheap-module-eval-source-map');
}
config.resolve
.set('symlinks', true)
.alias.set('@theme', themePath)
.set('@site', siteDir)
.set('@versioned_docs', versionedDir)
.set('@translated_docs', translatedDir)
.set('@docs', docsDir)
.set('@pages', pagesDir)
.set('@build', outDir)
.set('@generated', path.resolve(__dirname, '../core/generated'))
.set('@core', path.resolve(__dirname, '../core'))
.end();
function applyBabel(rule) {
rule
.use('babel')
.loader('babel-loader')
.options({
babelrc: false,
presets: ['env', 'react'],
plugins: [isServer ? 'dynamic-import-node' : 'syntax-dynamic-import']
});
}
const jsRule = config.module
.rule('js')
.test(/\.js$/)
.exclude.add(filepath => {
// Always transpile lib directory
if (filepath.startsWith(path.join(__dirname, '..'))) {
return false;
}
// Don't transpile node_modules
return /node_modules/.test(filepath);
})
.end();
applyBabel(jsRule);
const mdRule = config.module.rule('markdown').test(/\.md$/);
applyBabel(mdRule);
mdRule
.use('markdown-loader')
.loader(mdLoader)
.options({
siteConfig,
versionedDir,
translatedDir,
docsDir,
sourceToMetadata
});
const cssRule = config.module.rule('css').test(/\.css$/);
if (!isServer) {
if (isProd) {
cssRule.use('extract-css-loader').loader(CSSExtractPlugin.loader);
} else {
cssRule.use('style-loader').loader('style-loader');
}
}
cssRule
.use('css-loader')
.loader(isServer ? 'css-loader/locals' : 'css-loader')
.options({
modules: true,
importLoaders: 1,
localIdentName: `[local]_[hash:base64:8]`,
sourceMap: !isProd,
minimize: true
});
// mini-css-extract plugin
config.plugin('extract-css').use(CSSExtractPlugin, [
{
filename: isProd ? '[name].[chunkhash].css' : '[name].css',
chunkFilename: isProd ? '[id].[chunkhash].css' : '[id].css'
}
]);
if (isProd) {
config.optimization.minimizer([
new UglifyJsPlugin({
cache: true,
uglifyOptions: {
warnings: false,
compress: false,
ecma: 6,
mangle: true
},
sourceMap: true
})
]);
}
return config;
};

30
v2/lib/webpack/client.js Normal file
View file

@ -0,0 +1,30 @@
const path = require('path');
const webpackNiceLog = require('webpack-nicelog');
const {StatsWriterPlugin} = require('webpack-stats-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const createBaseConfig = require('./base');
const {applyChainWebpack} = require('./utils');
module.exports = function createClientConfig(props) {
const config = createBaseConfig(props);
config.entry('main').add(path.resolve(__dirname, '../core/clientEntry.js'));
// remove/clean build folders before building bundles
const {outDir} = props;
config
.plugin('clean')
.use(cleanWebpackPlugin, [outDir, {verbose: false, allowExternal: true}]);
// write webpack stats object so we can pickup correct client bundle path in server.
config
.plugin('stats')
.use(StatsWriterPlugin, [{filename: 'client.stats.json'}]);
// show compilation progress bar and build time
config.plugin('niceLog').use(webpackNiceLog, [{name: 'Client'}]);
// user extended webpack-chain config
applyChainWebpack(props.siteConfig.chainWebpack, config, false);
return config;
};

View file

@ -0,0 +1,78 @@
const {getOptions} = require('loader-utils');
const fm = require('front-matter');
module.exports = function(fileString) {
const options = getOptions(this);
const {
siteConfig,
versionedDir,
docsDir,
translatedDir,
sourceToMetadata
} = options;
/* Extract content of markdown (without frontmatter) */
const {body} = fm(fileString);
/* Determine the source dir. e.g: @docs, @translated_docs/ko and @versioned_docs/version-1.0.0 */
let sourceDir;
let thisSource = this.resourcePath;
if (thisSource.startsWith(translatedDir)) {
thisSource = thisSource.replace(translatedDir, '@translated_docs');
const {language, version} = sourceToMetadata[thisSource] || {};
if (language && version && version !== 'next') {
sourceDir = `@translated_docs/${language}/version-${version}`;
} else if (language && (!version || version === 'next')) {
sourceDir = `@translated_docs/${language}`;
}
} else if (thisSource.startsWith(versionedDir)) {
thisSource = thisSource.replace(versionedDir, '@versioned_docs');
const {version} = sourceToMetadata[thisSource] || {};
if (version) {
sourceDir = `@versioned_docs/version-${version}`;
}
} else if (thisSource.startsWith(docsDir)) {
sourceDir = `@docs`;
}
/* Replace internal markdown linking (except in fenced blocks) */
let content = body;
if (sourceDir) {
let fencedBlock = false;
const lines = body.split('\n').map(line => {
if (line.trim().startsWith('```')) {
fencedBlock = !fencedBlock;
}
if (fencedBlock) return line;
let modifiedLine = line;
const mdLinks = [];
const mdRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
let match = mdRegex.exec(content);
while (match !== null) {
mdLinks.push(match[1]);
match = mdRegex.exec(content);
}
mdLinks.forEach(mdLink => {
const targetSource = `${sourceDir}/${mdLink}`;
const {permalink} = sourceToMetadata[targetSource] || {};
if (permalink) {
modifiedLine = modifiedLine.replace(mdLink, permalink);
}
});
return modifiedLine;
});
content = lines.join('\n');
}
/* Return a React component */
return (
`import React from 'react';\n` +
`import Markdown from '@theme/Markdown'\n` +
`export default () => (
<Markdown siteConfig={${JSON.stringify(siteConfig)}}>
{${JSON.stringify(content)}}
</Markdown>
);`
);
};

43
v2/lib/webpack/server.js Normal file
View file

@ -0,0 +1,43 @@
const path = require('path');
const staticSiteGenerator = require('static-site-generator-webpack-plugin');
const webpackNiceLog = require('webpack-nicelog');
const createBaseConfig = require('./base');
const {applyChainWebpack} = require('./utils');
module.exports = function createServerConfig(props) {
const config = createBaseConfig(props, true);
config.entry('main').add(path.resolve(__dirname, '../core/serverEntry.js'));
config.target('node');
config.output.filename('server.bundle.js').libraryTarget('commonjs2');
// Workaround for Webpack 4 Bug (https://github.com/webpack/webpack/issues/6522)
config.output.globalObject('this');
const {siteConfig, docsMetadatas, pagesMetadatas} = props;
// static site generator webpack plugin
const docsLinks = Object.values(docsMetadatas).map(data => ({
path: `${data.permalink}`
}));
const paths = [...docsLinks, ...pagesMetadatas].map(data => data.path);
config.plugin('siteGenerator').use(staticSiteGenerator, [
{
entry: 'main',
locals: {
baseUrl: siteConfig.baseUrl
},
paths
}
]);
// show compilation progress bar and build time
config
.plugin('niceLog')
.use(webpackNiceLog, [{name: 'Server', color: 'yellow'}]);
// user extended webpack-chain config
applyChainWebpack(props.siteConfig.chainWebpack, config, true);
return config;
};

27
v2/lib/webpack/utils.js Normal file
View file

@ -0,0 +1,27 @@
const merge = require('webpack-merge');
// Modify the generated webpack config with normal webpack config
function applyConfigureWebpack(userConfig, config, isServer) {
if (typeof userConfig === 'object') {
return merge(config, userConfig);
}
if (typeof userConfig === 'function') {
const res = userConfig(config, isServer);
if (res && typeof res === 'object') {
return merge(config, res);
}
}
return config;
}
// Modify the generated webpack config with webpack-chain API
function applyChainWebpack(userChainWebpack, config, isServer) {
if (userChainWebpack) {
userChainWebpack(config, isServer);
}
}
module.exports = {
applyConfigureWebpack,
applyChainWebpack
};

94
v2/package.json Normal file
View file

@ -0,0 +1,94 @@
{
"name": "munseo",
"version": "0.0.1",
"description": "📝⚡️ Transform your document (문서) to a website",
"main": "lib/index.js",
"bin": {
"munseo": "bin/munseo.js"
},
"scripts": {
"munseo": "node bin/munseo",
"start": "node bin/munseo start website",
"build": "node bin/munseo build website",
"eject": "node bin/munseo eject website",
"prettier": "prettier --config .prettierrc --write \"lib/**/*.js\" \"bin/**/*.js\" \"test/**/*.js\"",
"lint": "eslint --cache \"lib/**/*.js\" \"bin/**/*.js\" \"test/**/*.js\"",
"test": "jest --config test/jest.config.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/endiliey/munseo.git"
},
"keywords": [
"blog",
"generator",
"react"
],
"author": "endiliey",
"license": "MIT",
"bugs": {
"url": "https://github.com/endiliey/munseo/issues"
},
"homepage": "https://github.com/endiliey/munseo#readme",
"devDependencies": {
"eslint": "^4.19.1",
"eslint-config-airbnb": "17.0.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.9.1",
"jest": "^23.4.2",
"prettier": "^1.13.7"
},
"dependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-dynamic-import-node": "^2.0.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"classnames": "^2.2.6",
"clean-webpack-plugin": "^0.1.19",
"commander": "^2.16.0",
"connect-history-api-fallback": "^1.5.0",
"css-loader": "^1.0.0",
"escape-html": "^1.0.3",
"escape-string-regexp": "^1.0.5",
"front-matter": "^2.3.0",
"fs-extra": "^7.0.0",
"globby": "^8.0.1",
"highlight.js": "^9.12.0",
"html-webpack-plugin": "^3.2.0",
"koa-connect": "^2.0.1",
"koa-mount": "^3.0.0",
"koa-range": "^0.3.0",
"koa-static": "^5.0.0",
"loader-utils": "^1.1.0",
"mini-css-extract-plugin": "^0.4.1",
"portfinder": "^1.0.13",
"prismjs": "^1.15.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-helmet": "^5.2.0",
"react-loadable": "^5.5.0",
"react-router-config": "^1.0.0-beta.4",
"react-router-dom": "^4.3.1",
"react-youtube": "^7.6.0",
"remarkable": "^1.7.1",
"semver": "^5.5.0",
"static-site-generator-webpack-plugin": "endiliey/static-site-generator-webpack-plugin#master",
"style-loader": "^0.22.1",
"uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.16.3",
"webpack-chain": "^4.8.0",
"webpack-merge": "^4.1.4",
"webpack-nicelog": "^2.2.1",
"webpack-serve": "^2.0.2",
"webpack-stats-plugin": "^0.2.1"
},
"engines": {
"node": ">=8"
}
}

View file

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>Baz</div>;

View file

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>Foo</div>;

View file

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>Foo in subfolder</div>;

View file

@ -0,0 +1,3 @@
import React from 'react';
export default () => <div>Index</div>;

View file

@ -0,0 +1,7 @@
module.exports = {
title: 'Sakura',
tagline: 'This is not an ordinary site',
organizationName: 'endiliey',
projectName: 'sakura',
baseUrl: '/sakura/'
};

View file

@ -0,0 +1,66 @@
---
id: bar
title: Bar
---
# Remarkable
> Experience real-time editing with Remarkable!
Click the `clear` link to start with a clean slate, or get the `permalink` to share or save your results.
***
# h1 Heading
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
## Horizontal Rules
___
***
***
## Typographic replacements
Enable typographer option to see result.
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
test.. test... test..... test?..... test!....
!!!!!! ???? ,,
Remarkable -- awesome
"Smartypants, double quotes"
'Smartypants, single quotes'
## Emphasis
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Deleted text~~
Superscript: 19^th^
Subscript: H~2~O
++Inserted text++
==Marked text==

View file

@ -0,0 +1,74 @@
---
id: baz
title: baz
---
## Images
Like links, Images also have a footnote style syntax
![Alt text][id]
With a reference later in the document defining the URL location:
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## Links
[link text](http://dev.nodeca.com)
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
## Footnotes
Footnote 1 link[^first].
Footnote 2 link[^second].
Inline footnote^[Text of inline footnote] definition.
Duplicated footnote reference[^second].
[^first]: Footnote **can have markup**
and multiple paragraphs.
[^second]: Footnote text.
## Definition lists
Term 1
: Definition 1
with lazy continuation.
Term 2 with *inline markup*
: Definition 2
{ some code, part of Definition 2 }
Third paragraph of definition 2.
_Compact style:_
Term 1
~ Definition 1
Term 2
~ Definition 2a
~ Definition 2b
## Abbreviations
This is HTML abbreviation example.
It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.
*[HTML]: Hyper Text Markup Language

View file

@ -0,0 +1,54 @@
---
id: hello
title: Hello, World !
---
Hi, Endilie here :)
## Relative links
Replace this
[foo](foo/bar.md)
Can't replace this
[file](file.md)
Do not replace below
```
[hello](hello.md)
```
## Blockquotes
> Blockquotes can also be nested...
>> ...by using additional greater-than signs right next to each other...
> > > ...or with spaces between arrows.
## Lists
Unordered
+ Create a list by starting a line with `+`, `-`, or `*`
+ Sub-lists are made by indenting 2 spaces:
- Marker character change forces new list start:
* Ac tristique libero volutpat at
+ Facilisis in pretium nisl aliquet
- Nulla volutpat aliquam velit
+ Very easy!
Ordered
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
1. You can use sequential numbers...
1. ...or keep all the numbers as `1.`
Start numbering with offset:
57. foo
1. bar

View file

@ -0,0 +1,7 @@
---
id: permalink
title: Permalink
permalink: :baseUrl:docsUrl/:langPart/:versionPart/endiliey/:id
---
This has a different permalink

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class World extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>World</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Hello World </div>
</Layout>
);
}
}

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class Home extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>Home</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Home ... </div>
</Layout>
);
}
}

View file

@ -0,0 +1,11 @@
{
"docs": {
"Test": [
"foo/bar",
"foo/baz"
],
"Guides": [
"hello"
]
}
}

View file

@ -0,0 +1,7 @@
module.exports = {
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/'
};

View file

@ -0,0 +1,378 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
button,
input[type="checkbox"] {
outline: none;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
label[for='toggle-all'] {
display: none;
}
.toggle-all {
position: absolute;
top: -55px;
left: -12px;
width: 60px;
height: 34px;
text-align: center;
border: none; /* Mobile Safari */
}
.toggle-all:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
.todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
.todo-list li label {
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a.selected,
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
position: relative;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
.toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,178 @@
const languages = [
{
enabled: true,
name: 'English',
tag: 'en',
},
{
enabled: false,
name: '日本語',
tag: 'ja',
},
{
enabled: false,
name: 'العربية',
tag: 'ar',
},
{
enabled: false,
name: 'Bosanski',
tag: 'bs-BA',
},
{
enabled: false,
name: 'Català',
tag: 'ca',
},
{
enabled: false,
name: 'Čeština',
tag: 'cs',
},
{
enabled: false,
name: 'Dansk',
tag: 'da',
},
{
enabled: false,
name: 'Deutsch',
tag: 'de',
},
{
enabled: false,
name: 'Ελληνικά',
tag: 'el',
},
{
enabled: false,
name: 'Español',
tag: 'es-ES',
},
{
enabled: false,
name: 'فارسی',
tag: 'fa-IR',
},
{
enabled: false,
name: 'Suomi',
tag: 'fi',
},
{
enabled: false,
name: 'Français',
tag: 'fr',
},
{
enabled: false,
name: 'עִברִית',
tag: 'he',
},
{
enabled: false,
name: 'Magyar',
tag: 'hu',
},
{
enabled: false,
name: 'Bahasa Indonesia',
tag: 'id-ID',
},
{
enabled: false,
name: 'Italiano',
tag: 'it',
},
{
enabled: false,
name: 'Afrikaans',
tag: 'af',
},
{
enabled: true,
name: '한국어',
tag: 'ko',
},
{
enabled: false,
name: 'मराठी',
tag: 'mr-IN',
},
{
enabled: false,
name: 'Nederlands',
tag: 'nl',
},
{
enabled: false,
name: 'Norsk',
tag: 'no-NO',
},
{
enabled: false,
name: 'Polskie',
tag: 'pl',
},
{
enabled: false,
name: 'Português',
tag: 'pt-PT',
},
{
enabled: false,
name: 'Português (Brasil)',
tag: 'pt-BR',
},
{
enabled: false,
name: 'Română',
tag: 'ro',
},
{
enabled: false,
name: 'Русский',
tag: 'ru',
},
{
enabled: false,
name: 'Slovenský',
tag: 'sk-SK',
},
{
enabled: false,
name: 'Српски језик (Ћирилица)',
tag: 'sr',
},
{
enabled: false,
name: 'Svenska',
tag: 'sv-SE',
},
{
enabled: false,
name: 'Türkçe',
tag: 'tr',
},
{
enabled: false,
name: 'Українська',
tag: 'uk',
},
{
enabled: false,
name: 'Tiếng Việt',
tag: 'vi',
},
{
enabled: false,
name: '简体中文',
tag: 'zh-CN',
},
{
enabled: false,
name: '繁體中文',
tag: 'zh-TW',
},
];
module.exports = languages;

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class World extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>World</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Hello World </div>
</Layout>
);
}
}

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class Home extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>Home</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Home ... </div>
</Layout>
);
}
}

View file

@ -0,0 +1,11 @@
{
"docs": {
"Test": [
"foo/bar",
"foo/baz"
],
"Guides": [
"hello"
]
}
}

View file

@ -0,0 +1,8 @@
module.exports = {
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/',
defaultLanguage: 'en'
};

View file

@ -0,0 +1,378 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
button,
input[type="checkbox"] {
outline: none;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
label[for='toggle-all'] {
display: none;
}
.toggle-all {
position: absolute;
top: -55px;
left: -12px;
width: 60px;
height: 34px;
text-align: center;
border: none; /* Mobile Safari */
}
.toggle-all:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
.todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
.todo-list li label {
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a.selected,
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
position: relative;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
.toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,66 @@
---
id: bar
title: Bar
---
# Remarkable
> Remarkable로 실시간 편집을 경험하십시오!
깨끗한 슬레이트로 시작하려면`clear` 링크를 클릭하고 결과를 공유하거나 저장하려면`permalink`를 가져옵니다.
***
# h1 제목
## h2 제목
### h3 제목
#### h4 헤딩
##### h5 제목
###### h6 제목
## 수평 규칙
___
***
***
## 활자체 대체
입력기 옵션을 사용하면 결과를 볼 수 있습니다.
(p) (P) + - (r) (t)
테스트 .. 테스트 ... 테스트 ..... 테스트? ..... 테스트! ....
!!!!!! ???? ,,
놀라운 - 굉장한
"Smartypants, 큰 따옴표"
'Smartypants, 작은 따옴표'
## 강조
** 이것은 굵은 글씨입니다 **
__ 이것은 굵은 글씨입니다 __
* 이탤릭체 텍스트 *
_ 이탤릭체 텍스트 _
~~ 삭제 된 텍스트 ~~
위 첨자 : 19 ^ th ^
아래 첨자 : H ~ 2 ~ O
++ 삽입 된 텍스트 ++
== 표시된 텍스트 ==

View file

@ -0,0 +1,74 @@
---
id: baz
title: baz
---
## 이미지
링크와 마찬가지로 이미지에도 각주 스타일 구문이 있습니다.
! [Alt text] [id]
나중에 URL 위치를 정의하는 문서에서 참조로 :
[id] : https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## 링크
[링크 텍스트] (http://dev.nodeca.com)
[제목 링크] (http://nodeca.github.io/pica/demo/ "제목 텍스트!")
자동 변환 된 링크 https://github.com/nodeca/pica (linkify를 사용하도록 설정)
## 각주
각주 1 링크 [^ 첫 번째].
각주 2 링크 [^ 초].
인라인 각주 ^ [인라인 각주의 텍스트] 정의.
중복 된 각주 참조 [^ 초].
[^ first] : 각주 **는 마크 업을 가질 수 있습니다 **
    및 여러 단락.
[^ 초] : 각주 텍스트.
## 정의 목록
1 학기
정의 1
게으른 연속.
* 인라인 마크 업과 함께 2 학기 *
: 정의 2
        {일부 코드, 정의 2의 일부}
    정의의 세 번째 단락 2.
_ 컴팩트 스타일 : _
1 학기
  ~ 정의 1
2 학기
  ~ 정의 2a
  ~ 정의 2b
## 약어
이것은 HTML 약어입니다.
그것은 "HTML"을 변환하지만 "xxxHTMLyyy"와 같이 부분적인 항목을 그대로 유지합니다.
* [HTML] : 하이퍼 텍스트 마크 업 언어

View file

@ -0,0 +1,40 @@
---
id: hello
title: Hello, World !
---
안녕하세요, 여기 엔 틸리에 :)
## Blockquotes
> Blockquotes는 또한 중첩 될 수 있습니다 ...
>> ... 서로 옆에 큰 더 큰 부호를 사용하여 ...
>>> ... 또는 화살표 사이에 공백이 있어야합니다.
## 목록
정렬되지 않은
+`+`,`-` 또는`*`를 사용하여 행을 시작하여 목록을 만듭니다.
+ 하위 목록은 2 칸을 들여서 만들어집니다 :
   - 마커 문자 변경으로 새로운 목록 시작 :
     * AC tristique libero volutpat at
     + Preisium nisl aliquet에 대한 + 시설
     - Nulla volutpat aliquam velit
+ 매우 쉽습니다!
주문 됨
1. Lorem ipsum dolor sit amet
2. 컨소시엄 adipiscing 엘리트
3. massa에서의 정수 lorem
1. 일련 번호를 사용할 수 있습니다 ...
1. ... 또는 모든 숫자를 '1'로 유지하십시오.
오프셋을 사용하여 번호 매기기 시작 :
57. foo
1. 막대기

View file

@ -0,0 +1,178 @@
const languages = [
{
enabled: true,
name: 'English',
tag: 'en',
},
{
enabled: false,
name: '日本語',
tag: 'ja',
},
{
enabled: false,
name: 'العربية',
tag: 'ar',
},
{
enabled: false,
name: 'Bosanski',
tag: 'bs-BA',
},
{
enabled: false,
name: 'Català',
tag: 'ca',
},
{
enabled: false,
name: 'Čeština',
tag: 'cs',
},
{
enabled: false,
name: 'Dansk',
tag: 'da',
},
{
enabled: false,
name: 'Deutsch',
tag: 'de',
},
{
enabled: false,
name: 'Ελληνικά',
tag: 'el',
},
{
enabled: false,
name: 'Español',
tag: 'es-ES',
},
{
enabled: false,
name: 'فارسی',
tag: 'fa-IR',
},
{
enabled: false,
name: 'Suomi',
tag: 'fi',
},
{
enabled: false,
name: 'Français',
tag: 'fr',
},
{
enabled: false,
name: 'עִברִית',
tag: 'he',
},
{
enabled: false,
name: 'Magyar',
tag: 'hu',
},
{
enabled: false,
name: 'Bahasa Indonesia',
tag: 'id-ID',
},
{
enabled: false,
name: 'Italiano',
tag: 'it',
},
{
enabled: false,
name: 'Afrikaans',
tag: 'af',
},
{
enabled: true,
name: '한국어',
tag: 'ko',
},
{
enabled: false,
name: 'मराठी',
tag: 'mr-IN',
},
{
enabled: false,
name: 'Nederlands',
tag: 'nl',
},
{
enabled: false,
name: 'Norsk',
tag: 'no-NO',
},
{
enabled: false,
name: 'Polskie',
tag: 'pl',
},
{
enabled: false,
name: 'Português',
tag: 'pt-PT',
},
{
enabled: false,
name: 'Português (Brasil)',
tag: 'pt-BR',
},
{
enabled: false,
name: 'Română',
tag: 'ro',
},
{
enabled: false,
name: 'Русский',
tag: 'ru',
},
{
enabled: false,
name: 'Slovenský',
tag: 'sk-SK',
},
{
enabled: false,
name: 'Српски језик (Ћирилица)',
tag: 'sr',
},
{
enabled: false,
name: 'Svenska',
tag: 'sv-SE',
},
{
enabled: false,
name: 'Türkçe',
tag: 'tr',
},
{
enabled: false,
name: 'Українська',
tag: 'uk',
},
{
enabled: false,
name: 'Tiếng Việt',
tag: 'vi',
},
{
enabled: false,
name: '简体中文',
tag: 'zh-CN',
},
{
enabled: false,
name: '繁體中文',
tag: 'zh-TW',
},
];
module.exports = languages;

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class World extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>World</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Hello World </div>
</Layout>
);
}
}

View file

@ -0,0 +1,17 @@
import React from 'react';
import Helmet from 'react-helmet';
import Layout from '@theme/Layout';
export default class Home extends React.Component {
render() {
return (
<Layout {...this.props}>
<Helmet>
<title>Home</title>
<link rel="stylesheet" type="text/css" href="/css/basic.css" />
</Helmet>
<div>Home ... </div>
</Layout>
);
}
}

View file

@ -0,0 +1,11 @@
{
"docs": {
"Test": [
"foo/bar",
"foo/baz"
],
"Guides": [
"hello"
]
}
}

View file

@ -0,0 +1,8 @@
module.exports = {
title: 'Hello',
tagline: 'Hello World',
organizationName: 'endiliey',
projectName: 'hello',
baseUrl: '/',
defaultLanguage: 'en'
};

View file

@ -0,0 +1,378 @@
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
button,
input[type="checkbox"] {
outline: none;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
label[for='toggle-all'] {
display: none;
}
.toggle-all {
position: absolute;
top: -55px;
left: -12px;
width: 60px;
height: 34px;
text-align: center;
border: none; /* Mobile Safari */
}
.toggle-all:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
.todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
.todo-list li label {
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a.selected,
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
position: relative;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
.toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,66 @@
---
id: bar
title: Bar
---
# Remarkable
> Remarkable로 실시간 편집을 경험하십시오!
깨끗한 슬레이트로 시작하려면`clear` 링크를 클릭하고 결과를 공유하거나 저장하려면`permalink`를 가져옵니다.
***
# h1 제목
## h2 제목
### h3 제목
#### h4 헤딩
##### h5 제목
###### h6 제목
## 수평 규칙
___
***
***
## 활자체 대체
입력기 옵션을 사용하면 결과를 볼 수 있습니다.
(p) (P) + - (r) (t)
테스트 .. 테스트 ... 테스트 ..... 테스트? ..... 테스트! ....
!!!!!! ???? ,,
놀라운 - 굉장한
"Smartypants, 큰 따옴표"
'Smartypants, 작은 따옴표'
## 강조
** 이것은 굵은 글씨입니다 **
__ 이것은 굵은 글씨입니다 __
* 이탤릭체 텍스트 *
_ 이탤릭체 텍스트 _
~~ 삭제 된 텍스트 ~~
위 첨자 : 19 ^ th ^
아래 첨자 : H ~ 2 ~ O
++ 삽입 된 텍스트 ++
== 표시된 텍스트 ==

View file

@ -0,0 +1,74 @@
---
id: baz
title: baz
---
## 이미지
링크와 마찬가지로 이미지에도 각주 스타일 구문이 있습니다.
! [Alt text] [id]
나중에 URL 위치를 정의하는 문서에서 참조로 :
[id] : https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## 링크
[링크 텍스트] (http://dev.nodeca.com)
[제목 링크] (http://nodeca.github.io/pica/demo/ "제목 텍스트!")
자동 변환 된 링크 https://github.com/nodeca/pica (linkify를 사용하도록 설정)
## 각주
각주 1 링크 [^ 첫 번째].
각주 2 링크 [^ 초].
인라인 각주 ^ [인라인 각주의 텍스트] 정의.
중복 된 각주 참조 [^ 초].
[^ first] : 각주 **는 마크 업을 가질 수 있습니다 **
    및 여러 단락.
[^ 초] : 각주 텍스트.
## 정의 목록
1 학기
정의 1
게으른 연속.
* 인라인 마크 업과 함께 2 학기 *
: 정의 2
        {일부 코드, 정의 2의 일부}
    정의의 세 번째 단락 2.
_ 컴팩트 스타일 : _
1 학기
  ~ 정의 1
2 학기
  ~ 정의 2a
  ~ 정의 2b
## 약어
이것은 HTML 약어입니다.
그것은 "HTML"을 변환하지만 "xxxHTMLyyy"와 같이 부분적인 항목을 그대로 유지합니다.
* [HTML] : 하이퍼 텍스트 마크 업 언어

View file

@ -0,0 +1,54 @@
---
id: hello
title: Hello, World !
---
안녕하세요, 여기 엔 틸리에 :)
## 상대 링크
이것 바꾸기
[foo](foo/bar.md)
이것을 대체 할 수 없습니다.
[파일] (file.md)
아래를 교체하지 마십시오.
```
[hello] (hello.md)
```
## Blockquotes
> Blockquotes는 또한 중첩 될 수 있습니다 ...
>> ... 서로 옆에 큰 더 큰 부호를 사용하여 ...
>>> ... 또는 화살표 사이에 공백이 있어야합니다.
## 목록
정렬되지 않은
+`+`,`-` 또는`*`를 사용하여 행을 시작하여 목록을 만듭니다.
+ 하위 목록은 2 칸을 들여서 만들어집니다 :
   - 마커 문자 변경으로 새로운 목록 시작 :
     * AC tristique libero volutpat at
     + Preisium nisl aliquet에 대한 + 시설
     - Nulla volutpat aliquam velit
+ 매우 쉽습니다!
주문 됨
1. Lorem ipsum dolor sit amet
2. 컨소시엄 adipiscing 엘리트
3. massa에서의 정수 lorem
1. 일련 번호를 사용할 수 있습니다 ...
1. ... 또는 모든 숫자를 '1'로 유지하십시오.
오프셋을 사용하여 번호 매기기 시작 :
57. foo
1. 막대기

View file

@ -0,0 +1,66 @@
---
id: version-1.0.0-bar
title: Bar
---
# Remarkable
> Remarkable로 실시간 편집을 경험하십시오!
깨끗한 슬레이트로 시작하려면`clear` 링크를 클릭하고 결과를 공유하거나 저장하려면`permalink`를 가져옵니다.
***
# h1 제목
## h2 제목
### h3 제목
#### h4 헤딩
##### h5 제목
###### h6 제목
## 수평 규칙
___
***
***
## 활자체 대체
입력기 옵션을 사용하면 결과를 볼 수 있습니다.
(p) (P) + - (r) (t)
테스트 .. 테스트 ... 테스트 ..... 테스트? ..... 테스트! ....
!!!!!! ???? ,,
놀라운 - 굉장한
"Smartypants, 큰 따옴표"
'Smartypants, 작은 따옴표'
## 강조
** 이것은 굵은 글씨입니다 **
__ 이것은 굵은 글씨입니다 __
* 이탤릭체 텍스트 *
_ 이탤릭체 텍스트 _
~~ 삭제 된 텍스트 ~~
위 첨자 : 19 ^ th ^
아래 첨자 : H ~ 2 ~ O
++ 삽입 된 텍스트 ++
== 표시된 텍스트 ==

View file

@ -0,0 +1,74 @@
---
id: version-1.0.0-baz
title: baz
---
## 이미지
링크와 마찬가지로 이미지에도 각주 스타일 구문이 있습니다.
! [Alt text] [id]
나중에 URL 위치를 정의하는 문서에서 참조로 :
[id] : https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## 링크
[링크 텍스트] (http://dev.nodeca.com)
[제목 링크] (http://nodeca.github.io/pica/demo/ "제목 텍스트!")
자동 변환 된 링크 https://github.com/nodeca/pica (linkify를 사용하도록 설정)
## 각주
각주 1 링크 [^ 첫 번째].
각주 2 링크 [^ 초].
인라인 각주 ^ [인라인 각주의 텍스트] 정의.
중복 된 각주 참조 [^ 초].
[^ first] : 각주 **는 마크 업을 가질 수 있습니다 **
    및 여러 단락.
[^ 초] : 각주 텍스트.
## 정의 목록
1 학기
정의 1
게으른 연속.
* 인라인 마크 업과 함께 2 학기 *
: 정의 2
        {일부 코드, 정의 2의 일부}
    정의의 세 번째 단락 2.
_ 컴팩트 스타일 : _
1 학기
  ~ 정의 1
2 학기
  ~ 정의 2a
  ~ 정의 2b
## 약어
이것은 HTML 약어입니다.
그것은 "HTML"을 변환하지만 "xxxHTMLyyy"와 같이 부분적인 항목을 그대로 유지합니다.
* [HTML] : 하이퍼 텍스트 마크 업 언어

View file

@ -0,0 +1,54 @@
---
id: version-1.0.0-hello
title: Hello, World !
---
안녕하세요, 여기 엔 틸리에 :)
## 상대 링크
이것 바꾸기
[foo](foo/bar.md)
이것을 대체 할 수 없습니다.
[파일] (file.md)
아래를 교체하지 마십시오.
```
[hello] (hello.md)
```
## Blockquotes
> Blockquotes는 또한 중첩 될 수 있습니다 ...
>> ... 서로 옆에 큰 더 큰 부호를 사용하여 ...
>>> ... 또는 화살표 사이에 공백이 있어야합니다.
## 목록
정렬되지 않은
+`+`,`-` 또는`*`를 사용하여 행을 시작하여 목록을 만듭니다.
+ 하위 목록은 2 칸을 들여서 만들어집니다 :
   - 마커 문자 변경으로 새로운 목록 시작 :
     * AC tristique libero volutpat at
     + Preisium nisl aliquet에 대한 + 시설
     - Nulla volutpat aliquam velit
+ 매우 쉽습니다!
주문 됨
1. Lorem ipsum dolor sit amet
2. 컨소시엄 adipiscing 엘리트
3. massa에서의 정수 lorem
1. 일련 번호를 사용할 수 있습니다 ...
1. ... 또는 모든 숫자를 '1'로 유지하십시오.
오프셋을 사용하여 번호 매기기 시작 :
57. foo
1. 막대기

View file

@ -0,0 +1,66 @@
---
id: version-1.0.1-bar
title: Bar
---
# Remarkable
> Remarkable로 실시간 편집을 경험하십시오!
깨끗한 슬레이트로 시작하려면`clear` 링크를 클릭하고 결과를 공유하거나 저장하려면`permalink`를 가져옵니다.
***
# h1 제목
## h2 제목
### h3 제목
#### h4 헤딩
##### h5 제목
###### h6 제목
## 수평 규칙
___
***
***
## 활자체 대체
입력기 옵션을 사용하면 결과를 볼 수 있습니다.
(p) (P) + - (r) (t)
테스트 .. 테스트 ... 테스트 ..... 테스트? ..... 테스트! ....
!!!!!! ???? ,,
놀라운 - 굉장한
"Smartypants, 큰 따옴표"
'Smartypants, 작은 따옴표'
## 강조
** 이것은 굵은 글씨입니다 **
__ 이것은 굵은 글씨입니다 __
* 이탤릭체 텍스트 *
_ 이탤릭체 텍스트 _
~~ 삭제 된 텍스트 ~~
위 첨자 : 19 ^ th ^
아래 첨자 : H ~ 2 ~ O
++ 삽입 된 텍스트 ++
== 표시된 텍스트 ==

View file

@ -0,0 +1,74 @@
---
id: version-1.0.1-baz
title: baz
---
## 이미지
링크와 마찬가지로 이미지에도 각주 스타일 구문이 있습니다.
! [Alt text] [id]
나중에 URL 위치를 정의하는 문서에서 참조로 :
[id] : https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## 링크
[링크 텍스트] (http://dev.nodeca.com)
[제목 링크] (http://nodeca.github.io/pica/demo/ "제목 텍스트!")
자동 변환 된 링크 https://github.com/nodeca/pica (linkify를 사용하도록 설정)
## 각주
각주 1 링크 [^ 첫 번째].
각주 2 링크 [^ 초].
인라인 각주 ^ [인라인 각주의 텍스트] 정의.
중복 된 각주 참조 [^ 초].
[^ first] : 각주 **는 마크 업을 가질 수 있습니다 **
    및 여러 단락.
[^ 초] : 각주 텍스트.
## 정의 목록
1 학기
정의 1
게으른 연속.
* 인라인 마크 업과 함께 2 학기 *
: 정의 2
        {일부 코드, 정의 2의 일부}
    정의의 세 번째 단락 2.
_ 컴팩트 스타일 : _
1 학기
  ~ 정의 1
2 학기
  ~ 정의 2a
  ~ 정의 2b
## 약어
이것은 HTML 약어입니다.
그것은 "HTML"을 변환하지만 "xxxHTMLyyy"와 같이 부분적인 항목을 그대로 유지합니다.
* [HTML] : 하이퍼 텍스트 마크 업 언어

View file

@ -0,0 +1,54 @@
---
id: version-1.0.1-hello
title: Hello, World !
---
안녕하세요, 여기 엔 틸리에 :)
## 상대 링크
이것 바꾸기
[foo](foo/bar.md)
이것을 대체 할 수 없습니다.
[파일] (file.md)
아래를 교체하지 마십시오.
```
[hello] (hello.md)
```
## Blockquotes
> Blockquotes는 또한 중첩 될 수 있습니다 ...
>> ... 서로 옆에 큰 더 큰 부호를 사용하여 ...
>>> ... 또는 화살표 사이에 공백이 있어야합니다.
## 목록
정렬되지 않은
+`+`,`-` 또는`*`를 사용하여 행을 시작하여 목록을 만듭니다.
+ 하위 목록은 2 칸을 들여서 만들어집니다 :
   - 마커 문자 변경으로 새로운 목록 시작 :
     * AC tristique libero volutpat at
     + Preisium nisl aliquet에 대한 + 시설
     - Nulla volutpat aliquam velit
+ 매우 쉽습니다!
주문 됨
1. Lorem ipsum dolor sit amet
2. 컨소시엄 adipiscing 엘리트
3. massa에서의 정수 lorem
1. 일련 번호를 사용할 수 있습니다 ...
1. ... 또는 모든 숫자를 '1'로 유지하십시오.
오프셋을 사용하여 번호 매기기 시작 :
57. foo
1. 막대기

View file

@ -0,0 +1,66 @@
---
id: version-1.0.0-bar
title: Bar
---
# Remarkable
> Experience real-time editing with Remarkable!
Click the `clear` link to start with a clean slate, or get the `permalink` to share or save your results.
***
# h1 Heading
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
## Horizontal Rules
___
***
***
## Typographic replacements
Enable typographer option to see result.
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
test.. test... test..... test?..... test!....
!!!!!! ???? ,,
Remarkable -- awesome
"Smartypants, double quotes"
'Smartypants, single quotes'
## Emphasis
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Deleted text~~
Superscript: 19^th^
Subscript: H~2~O
++Inserted text++
==Marked text==

View file

@ -0,0 +1,74 @@
---
id: version-1.0.0-baz
title: Baz
---
## Images
Like links, Images also have a footnote style syntax
![Alt text][id]
With a reference later in the document defining the URL location:
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
## Links
[link text](http://dev.nodeca.com)
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
## Footnotes
Footnote 1 link[^first].
Footnote 2 link[^second].
Inline footnote^[Text of inline footnote] definition.
Duplicated footnote reference[^second].
[^first]: Footnote **can have markup**
and multiple paragraphs.
[^second]: Footnote text.
## Definition lists
Term 1
: Definition 1
with lazy continuation.
Term 2 with *inline markup*
: Definition 2
{ some code, part of Definition 2 }
Third paragraph of definition 2.
_Compact style:_
Term 1
~ Definition 1
Term 2
~ Definition 2a
~ Definition 2b
## Abbreviations
This is HTML abbreviation example.
It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.
*[HTML]: Hyper Text Markup Language

Some files were not shown because too many files have changed in this diff Show more