diff --git a/gulpfile.ts b/gulpfile.ts index df355e33e..a9ccbbdb5 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -59,9 +59,15 @@ gulp.task('build:ts', () => { .pipe(gulp.dest('./built/')); }); -gulp.task('build:copy', () => +gulp.task('build:copy:views', () => + gulp.src('./src/server/web/views/**/*').pipe(gulp.dest('./built/server/web/views')) +); + +gulp.task('build:copy', ['build:copy:views'], () => gulp.src([ './build/Release/crypto_key.node', + './src/const.json', + './src/server/web/views/**/*', './src/**/assets/**/*', '!./src/client/app/**/assets/**/*' ]).pipe(gulp.dest('./built/')) diff --git a/package.json b/package.json index 73369b26f..d4776a778 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@types/koa-multer": "1.0.0", "@types/koa-router": "7.0.28", "@types/koa-send": "4.1.1", + "@types/koa-views": "^2.0.3", "@types/koa__cors": "2.2.2", "@types/kue": "0.11.8", "@types/license-checker": "15.0.0", @@ -146,6 +147,7 @@ "koa-router": "7.4.0", "koa-send": "4.1.3", "koa-slow": "2.1.0", + "koa-views": "^6.1.4", "kue": "0.11.6", "license-checker": "18.0.0", "loader-utils": "1.1.0", diff --git a/src/client/app/base.pug b/src/client/app/base.pug index 32a95a6c9..c182fd6f6 100644 --- a/src/client/app/base.pug +++ b/src/client/app/base.pug @@ -1,3 +1,5 @@ +block vars + doctype html != '\n\n' @@ -9,9 +11,17 @@ html meta(name='application-name' content='Misskey') meta(name='theme-color' content=themeColor) meta(name='referrer' content='origin') + meta(property='og:site_name' content='Misskey') link(rel='manifest' href='/manifest.json') - title Misskey + title + block title + | Misskey + + block desc + meta(name='description' content='A SNS') + + block meta style include ./../../../built/client/assets/init.css diff --git a/src/renderers/get-note-summary.ts b/src/renderers/get-note-summary.ts index dfc05ebfd..0844c0b18 100644 --- a/src/renderers/get-note-summary.ts +++ b/src/renderers/get-note-summary.ts @@ -1,6 +1,6 @@ /** * 投稿を表す文字列を取得します。 - * @param {*} note 投稿 + * @param {*} note (packされた)投稿 */ const summarize = (note: any): string => { if (note.isHidden) { diff --git a/src/server/web/index.ts b/src/server/web/index.ts index 13751835b..7d4f76665 100644 --- a/src/server/web/index.ts +++ b/src/server/web/index.ts @@ -7,14 +7,32 @@ import * as Koa from 'koa'; import * as Router from 'koa-router'; import * as send from 'koa-send'; import * as favicon from 'koa-favicon'; +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 config from '../../config'; +import Note, { pack as packNote } from '../../models/note'; +import getNoteSummary from '../../renderers/get-note-summary'; +const consts = require('../../const.json'); const client = `${__dirname}/../../client/`; // Init app const app = new Koa(); +// Init renderer +app.use(views(__dirname + '/views', { + extension: 'pug', + options: { + config, + themeColor: consts.themeColor, + facss: fa.dom.css() + } +})); + // Serve favicon app.use(favicon(`${client}/assets/favicon.ico`)); @@ -67,6 +85,38 @@ router.use('/docs', docs.routes()); // URL preview endpoint router.get('/url', require('./url-preview')); +//#region for crawlers +// User +router.get('/@:user', async ctx => { + const { username, host } = parseAcct(ctx.params.user); + const user = await User.findOne({ + usernameLower: username.toLowerCase(), + host + }); + + if (user != null) { + await ctx.render('user', { user }); + } else { + ctx.status = 404; + } +}); + +// Note +router.get('/notes/:note', async ctx => { + const note = await Note.findOne({ _id: ctx.params.note }); + + if (note != null) { + const _note = await packNote(note); + await ctx.render('note', { + note: _note, + summary: getNoteSummary(_note) + }); + } else { + ctx.status = 404; + } +}); +//#endregion + // Render base html for all requests router.get('*', async ctx => { await send(ctx, `app/base.html`, { diff --git a/src/server/web/views/note.pug b/src/server/web/views/note.pug new file mode 100644 index 000000000..3107c0329 --- /dev/null +++ b/src/server/web/views/note.pug @@ -0,0 +1,20 @@ +extends ../../../../src/client/app/base + +block vars + - const user = note.user; + - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; + - const url = `${config.url}/notes/${note.id}`; + - const img = user.avatarId ? `${config.drive_url}/${user.avatarId}` : null; + +block title + = `${title} | Misskey` + +block desc + meta(name='description' content= summary) + +block meta + meta(name='twitter:card' content='summary') + meta(property='og:title' content= title) + meta(property='og:description' content= summary) + meta(property='og:url' content= url) + meta(property='og:image' content= img) diff --git a/src/server/web/views/user.pug b/src/server/web/views/user.pug new file mode 100644 index 000000000..cdfacb32b --- /dev/null +++ b/src/server/web/views/user.pug @@ -0,0 +1,19 @@ +extends ../../../../src/client/app/base + +block vars + - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; + - const url = config.url + '/@' + (user.host ? `${user.username}@${user.host}` : user.username); + - const img = user.avatarId ? `${config.drive_url}/${user.avatarId}` : null; + +block title + = `${title} | Misskey` + +block desc + meta(name='description' content= user.description) + +block meta + meta(name='twitter:card' content='summary') + meta(property='og:title' content= title) + meta(property='og:description' content= user.description) + meta(property='og:url' content= url) + meta(property='og:image' content= img)