summaryrefslogtreecommitdiff
path: root/src/server/web
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2018-08-01 08:34:22 +0900
committerGitHub <noreply@github.com>2018-08-01 08:34:22 +0900
commit77faf7a84cc28d9a24803940730e59706edd4ec8 (patch)
treea3a366deedc99a98bcfe7358eb48aff0ff5fe71c /src/server/web
parentNew translations ja.yml (English) (diff)
parentMerge pull request #2033 from syuilo/greenkeeper/qrcode-1.2.2 (diff)
downloadmisskey-77faf7a84cc28d9a24803940730e59706edd4ec8.tar.gz
misskey-77faf7a84cc28d9a24803940730e59706edd4ec8.tar.bz2
misskey-77faf7a84cc28d9a24803940730e59706edd4ec8.zip
Merge branch 'master' into l10n_master
Diffstat (limited to 'src/server/web')
-rw-r--r--src/server/web/docs.ts223
-rw-r--r--src/server/web/index.ts6
2 files changed, 221 insertions, 8 deletions
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index e65cc87b12..81e5ace3e8 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -2,26 +2,239 @@
* Docs
*/
+import * as fs from 'fs';
+import * as path from 'path';
+import * as showdown from 'showdown';
+import 'showdown-highlightjs-extension';
import ms = require('ms');
import * as Router from 'koa-router';
import * as send from 'koa-send';
+import { Context, ObjectContext } from 'cafy';
+import * as glob from 'glob';
+import * as yaml from 'js-yaml';
+import config from '../../config';
+import I18n from '../../misc/i18n';
+import { licenseHtml } from '../../misc/license';
+const constants = require('../../const.json');
+import endpoints from '../api/endpoints';
-const docs = `${__dirname}/../../client/docs/`;
+async function genVars(lang: string): Promise<{ [key: string]: any }> {
+ const vars = {} as { [key: string]: any };
+
+ vars['lang'] = lang;
+
+ const cwd = path.resolve(__dirname + '/../../../') + '/';
+
+ vars['endpoints'] = endpoints;
+
+ const entities = glob.sync('src/docs/api/entities/**/*.yaml', { cwd });
+ vars['entities'] = entities.map(x => {
+ const _x = yaml.safeLoad(fs.readFileSync(cwd + x, 'utf-8')) as any;
+ return _x.name;
+ });
+
+ const docs = glob.sync(`src/docs/**/*.${lang}.md`, { cwd });
+ vars['docs'] = {};
+ docs.forEach(x => {
+ const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/);
+ if (vars['docs'][name] == null) {
+ vars['docs'][name] = {
+ name,
+ title: {}
+ };
+ }
+ vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)[1];
+ });
+
+ vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
+
+ vars['config'] = config;
+
+ vars['copyright'] = constants.copyright;
+
+ vars['license'] = licenseHtml;
+
+ const i18n = new I18n(lang);
+ vars['i18n'] = (key: string) => i18n.get(null, key);
+
+ return vars;
+}
+
+// WIP type
+const parseParamDefinition = (key: string, param: Context) => {
+ return Object.assign({
+ name: key,
+ type: param.getType()
+ }, param.data);
+};
+
+const parsePropDefinition = (key: string, prop: any) => {
+ const id = prop.type.match(/^id\((.+?)\)|^id/);
+ const entity = prop.type.match(/^entity\((.+?)\)/);
+ const isObject = /^object/.test(prop.type);
+ const isDate = /^date/.test(prop.type);
+ const isArray = /\[\]$/.test(prop.type);
+ if (id) {
+ prop.kind = 'id';
+ prop.type = 'string';
+ prop.entity = id[1];
+ if (isArray) {
+ prop.type += '[]';
+ }
+ }
+ if (entity) {
+ prop.kind = 'entity';
+ prop.type = 'object';
+ prop.entity = entity[1];
+ if (isArray) {
+ prop.type += '[]';
+ }
+ }
+ if (isObject) {
+ prop.kind = 'object';
+ if (prop.props) {
+ prop.hasDef = true;
+ }
+ }
+ if (isDate) {
+ prop.kind = 'date';
+ prop.type = 'string';
+ if (isArray) {
+ prop.type += '[]';
+ }
+ }
+
+ if (prop.optional) {
+ prop.type += '?';
+ }
+
+ prop.name = key;
+
+ return prop;
+};
+
+const sortParams = (params: Array<{ name: string }>) => {
+ return params;
+};
+
+// WIP type
+const extractParamDefRef = (params: Context[]) => {
+ let defs: any[] = [];
+
+ params.forEach(param => {
+ if (param.data && param.data.ref) {
+ const props = (param as ObjectContext<any>).props;
+ defs.push({
+ name: param.data.ref,
+ params: sortParams(Object.keys(props).map(k => parseParamDefinition(k, props[k])))
+ });
+
+ const childDefs = extractParamDefRef(Object.keys(props).map(k => props[k]));
+
+ defs = defs.concat(childDefs);
+ }
+ });
+
+ return sortParams(defs);
+};
+
+const extractPropDefRef = (props: any[]) => {
+ let defs: any[] = [];
+
+ Object.entries(props).forEach(([k, v]) => {
+ if (v.props) {
+ defs.push({
+ name: k,
+ props: sortParams(Object.entries(v.props).map(([k, v]) => parsePropDefinition(k, v)))
+ });
+
+ const childDefs = extractPropDefRef(v.props);
+
+ defs = defs.concat(childDefs);
+ }
+ });
+
+ return sortParams(defs);
+};
const router = new Router();
router.get('/assets/*', async ctx => {
await send(ctx, ctx.params[0], {
- root: docs + '/assets/',
+ root: `${__dirname}/../../docs/assets/`,
maxage: ms('7 days'),
immutable: true
});
});
-router.get('*', async ctx => {
- await send(ctx, `${ctx.params[0]}.html`, {
- root: docs
+router.get('/*/api/endpoints/*', async ctx => {
+ const lang = ctx.params[0];
+ const name = ctx.params[1];
+ const ep = endpoints.find(e => e.name === name);
+
+ const vars = {
+ id: `api/endpoints/${name}`,
+ title: name,
+ endpoint: ep.meta,
+ endpointUrl: {
+ host: config.api_url,
+ path: name
+ },
+ // @ts-ignore
+ params: ep.meta.params ? sortParams(Object.entries(ep.meta.params).map(([k, v]) => parseParamDefinition(k, v))) : null,
+ paramDefs: ep.meta.params ? extractParamDefRef(Object.values(ep.meta.params)) : null,
+ res: ep.meta.res,
+ resProps: ep.meta.res && ep.meta.res.props ? sortParams(Object.entries(ep.meta.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null,
+ resDefs: null as any, //extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v)))
+ src: `https://github.com/syuilo/misskey/tree/master/src/server/api/endpoints/${name}.ts`
+ };
+
+ await ctx.render('../../../../src/docs/api/endpoints/view', Object.assign(await genVars(lang), vars));
+});
+
+router.get('/*/api/entities/*', async ctx => {
+ const lang = ctx.params[0];
+ const entity = ctx.params[1];
+
+ const x = yaml.safeLoad(fs.readFileSync(path.resolve(__dirname + '/../../../src/docs/api/entities/' + entity + '.yaml'), 'utf-8')) as any;
+
+ await ctx.render('../../../../src/docs/api/entities/view', Object.assign(await genVars(lang), {
+ id: `api/entities/${entity}`,
+ name: x.name,
+ desc: x.desc,
+ props: sortParams(Object.entries(x.props).map(([k, v]) => parsePropDefinition(k, v))),
+ propDefs: extractPropDefRef(x.props)
+ }));
+});
+
+router.get('/*/*', async ctx => {
+ const lang = ctx.params[0];
+ const doc = ctx.params[1];
+
+ showdown.extension('urlExtension', () => ({
+ type: 'output',
+ regex: /%URL%/g,
+ replace: config.url
+ }));
+
+ showdown.extension('apiUrlExtension', () => ({
+ type: 'output',
+ regex: /%API_URL%/g,
+ replace: config.api_url
+ }));
+
+ const conv = new showdown.Converter({
+ tables: true,
+ extensions: ['urlExtension', 'apiUrlExtension', 'highlightjs']
});
+ const md = fs.readFileSync(`${__dirname}/../../../src/docs/${doc}.${lang}.md`, 'utf8');
+
+ await ctx.render('../../../../src/docs/article', Object.assign({
+ id: doc,
+ html: conv.makeHtml(md),
+ title: md.match(/^# (.+?)\r?\n/)[1],
+ src: `https://github.com/syuilo/misskey/tree/master/src/docs/${doc}.${lang}.md`
+ }, await genVars(lang)));
});
export default router;
diff --git a/src/server/web/index.ts b/src/server/web/index.ts
index 4400fc1024..7291f8a0a5 100644
--- a/src/server/web/index.ts
+++ b/src/server/web/index.ts
@@ -11,11 +11,11 @@ import * as views from 'koa-views';
import docs from './docs';
import User from '../../models/user';
-import parseAcct from '../../acct/parse';
-import { fa } from '../../build/fa';
+import parseAcct from '../../misc/acct/parse';
+import { fa } from '../../misc/fa';
import config from '../../config';
import Note, { pack as packNote } from '../../models/note';
-import getNoteSummary from '../../renderers/get-note-summary';
+import getNoteSummary from '../../misc/get-note-summary';
const consts = require('../../const.json');
const client = `${__dirname}/../../client/`;