diff --git a/bin/server.js b/bin/server.js index 65395c8..fa6344b 100755 --- a/bin/server.js +++ b/bin/server.js @@ -1,16 +1,11 @@ #!/usr/bin/env node const config = require('config'); -const co = require('co'); const app = require('app'); const log = require('log')(); -co(function*() { - - yield* app.waitBootAndListen(config.server.host, config.server.port); - +app.waitBootAndListen(config.server.host, config.server.port).then(() => { log.info("App is listening"); - }).catch(function(err) { log.error(err); process.exit(1); // fatal error, could not boot! @@ -18,14 +13,14 @@ co(function*() { // отслеживаем unhandled ошибки // https://iojs.org/api/process.html#process_event_rejectionhandled -var unhandledRejections = []; +let unhandledRejections = []; process.on('unhandledRejection', function(reason, p) { p.trackRejectionId = Math.random(); setTimeout(function() { // 100 ms to catch up and handle rejection if (p.trackRejectionId) { // if not rejectionHandled yet, report unhandledRejections.push(p); - var report = { + let report = { err: reason, trackRejectionId: p.trackRejectionId, length: unhandledRejections.length diff --git a/manifest/.gitkeep b/cache/.gitkeep similarity index 100% rename from manifest/.gitkeep rename to cache/.gitkeep diff --git a/cache/pack.versions.json b/cache/pack.versions.json new file mode 100644 index 0000000..0ca6e00 --- /dev/null +++ b/cache/pack.versions.json @@ -0,0 +1 @@ +{"footer":"/pack/footer.js?edb029e47f90da7ef027","head":"/pack/head.js?edb029e47f90da7ef027","styles":["/pack/styles.js?edb029e47f90da7ef027","/pack/styles.css?2e4f8132ebec0fb8c5aca3229f00f5ef"],"tutorial":"/pack/tutorial.js?edb029e47f90da7ef027"} \ No newline at end of file diff --git a/dev b/dev index 2a37d23..0e6a5a2 100755 --- a/dev +++ b/dev @@ -9,7 +9,7 @@ export NODE_ENV=development export ASSET_VERSIONING=query export WATCH=1 export SITE_HOST=http://javascript.local -export PORT=80 +export PORT=3000 npm --silent run gulp dev | bunyan -o short -l debug diff --git a/edit b/edit index 7248209..aebd074 100755 --- a/edit +++ b/edit @@ -7,7 +7,7 @@ BRANCH="${1:-$NODE_LANG}" export NODE_LANG=$BRANCH export NODE_ENV=production export TUTORIAL_EDIT=1 -export PORT=80 +export PORT=3000 npm --silent run -- gulp edit --root /js/javascript-tutorial-$BRANCH diff --git a/gulpfile.js b/gulpfile.js index 3b27b04..5058f73 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,6 @@ const path = require('path'); const fs = require('fs'); const assert = require('assert'); const runSequence = require('run-sequence'); -const ll = require('gulp-ll'); const config = require('config'); @@ -25,9 +24,9 @@ const jsSources = [ function lazyRequireTask(path) { - var args = [].slice.call(arguments, 1); + let args = [].slice.call(arguments, 1); return function(callback) { - var task = require(path).apply(this, args); + let task = require(path).apply(this, args); return task(callback); }; @@ -61,8 +60,6 @@ function requireModuleTasks(moduleName) { } -ll.tasks('nodemon', 'client:webpack', 'server'); - // usage: gulp db:load --from fixture/init --harmony gulp.task('db:load', lazyRequireTask('./tasks/dbLoad')); gulp.task('db:clear', lazyRequireTask('./tasks/dbClear')); @@ -70,7 +67,7 @@ gulp.task('db:clear', lazyRequireTask('./tasks/dbClear')); gulp.task("nodemon", lazyRequireTask('./tasks/nodemon', { // shared client/server code has require('template.jade) which precompiles template on run // so I have to restart server to pickup the template change - ext: "js,jade", + ext: "js,pug", nodeArgs: process.env.NODE_DEBUG ? ['--debug'] : [], script: "./bin/server.js", @@ -95,7 +92,7 @@ gulp.task("client:livereload", lazyRequireTask("./tasks/livereload", { requireModuleTasks('tutorial'); -var testSrcs = ['{handlers,modules}/**/test/**/*.js']; +let testSrcs = ['{handlers,modules}/**/test/**/*.js']; // on Travis, keys are required for E2E Selenium tests // for PRs there are no keys, so we disable E2E if (!process.env.TEST_E2E || process.env.CI && process.env.TRAVIS_SECURE_ENV_VARS=="false") { @@ -129,17 +126,6 @@ gulp.task("client:sync-resources", lazyRequireTask('./tasks/syncResources', { assets: 'public' })); -// show errors if encountered -gulp.task('client:compile-css', - lazyRequireTask('./tasks/compileCss', { - src: './styles/base.styl', - dst: './public/styles', - publicDst: process.env.STATIC_HOST + '/styles/', // from browser point of view - manifest: path.join(config.manifestRoot, 'styles.versions.json'), - assetVersioning: config.assetVersioning - }) -); - gulp.task('client:minify', lazyRequireTask('./tasks/minify')); gulp.task('client:resize-retina-images', lazyRequireTask('./tasks/resizeRetinaImages')); @@ -158,7 +144,7 @@ gulp.task('edit', ['tutorial:importWatch', "client:sync-resources", 'client:live gulp.task('dev', function(callback) { - runSequence("client:sync-resources", ['nodemon', 'client:livereload', 'client:webpack', 'watch'], callback); + runSequence("tutorial:import", "client:sync-resources", ['nodemon', 'client:livereload', 'client:webpack', 'watch'], callback); }); gulp.on('err', function(gulpErr) { diff --git a/handlers/404.js b/handlers/404.js index 4792ca4..30cc8c8 100755 --- a/handlers/404.js +++ b/handlers/404.js @@ -1,9 +1,9 @@ exports.init = function(app) { - // by default if the router didn't find anything => it yields to next middleware + // by default if the router didn't find anything => it awaits to next middleware // so I throw error here manually app.use(function* (next) { - yield* next; + await next; if (this.status == 404) { // still nothing found? let default errorHandler show 404 diff --git a/handlers/accessLogger.js b/handlers/accessLogger.js index a92a71e..830c96a 100755 --- a/handlers/accessLogger.js +++ b/handlers/accessLogger.js @@ -19,7 +19,7 @@ exports.init = function(app) { }, "--> %s %s", req.method, req.originalUrl || req.url); try { - yield next; + await next; } catch (err) { // log uncaught downstream errors log(this, start, err); diff --git a/handlers/bodyParser.js b/handlers/bodyParser.js index c536bbe..b7ee4a8 100755 --- a/handlers/bodyParser.js +++ b/handlers/bodyParser.js @@ -23,14 +23,14 @@ BodyParser.prototype.middleware = function() { if (!self.ignore.check(this.path)) { this.log.debug("bodyParser will parse"); - yield* self.parser.call(this, next); + await self.parser.call(this, next); this.log.debug("bodyParser done parse"); } else { this.log.debug("bodyParser skip"); } - yield* next; + await next; }; }; diff --git a/handlers/conditional.js b/handlers/conditional.js index 70b19f7..b96985f 100755 --- a/handlers/conditional.js +++ b/handlers/conditional.js @@ -13,7 +13,7 @@ exports.init = function(app) { // set expires to this.expires app.use(function* (next) { - yield *next; + await *next; if (!this.expires) return; diff --git a/handlers/csrfCheck.js b/handlers/csrfCheck.js index 0c880ee..81a9225 100755 --- a/handlers/csrfCheck.js +++ b/handlers/csrfCheck.js @@ -12,7 +12,7 @@ CsrfChecker.prototype.middleware = function() { return function*(next) { // skip these methods if (this.method === 'GET' || this.method === 'HEAD' || this.method === 'OPTIONS') { - return yield* next; + return await next; } var checkCsrf = true; @@ -38,7 +38,7 @@ CsrfChecker.prototype.middleware = function() { this.log.debug("csrf skip"); } - yield* next; + await next; }; }; @@ -56,7 +56,7 @@ exports.init = function(app) { try { // first, do the middleware, maybe authorize user in the process - yield* next; + await next; } finally { // then if we have a user, set XSRF token if (this.req.user) { diff --git a/handlers/dev/index.js b/handlers/dev/index.js new file mode 100755 index 0000000..cec3cee --- /dev/null +++ b/handlers/dev/index.js @@ -0,0 +1,6 @@ +var mountHandlerMiddleware = require('lib/mountHandlerMiddleware'); + +exports.init = function(app) { + app.use( mountHandlerMiddleware('/dev', __dirname) ); +}; + diff --git a/handlers/dev/router.js b/handlers/dev/router.js new file mode 100755 index 0000000..36de535 --- /dev/null +++ b/handlers/dev/router.js @@ -0,0 +1,19 @@ +var Router = require('koa-router'); + +var router = module.exports = new Router(); + +router.get('/', async function(ctx) { + ctx.body = ctx.render('index'); + +}); + +router.get('/die', async function(ctx) { + setTimeout(function() { + throw new Error("die"); + }, 10); +}); + +router.get('/test', async function(ctx) { + ctx.body = Math.round(Date.now() / 1000 / 60); +}); + diff --git a/handlers/dev/tasks/convert.js b/handlers/dev/tasks/convert.js new file mode 100755 index 0000000..0dd6d8b --- /dev/null +++ b/handlers/dev/tasks/convert.js @@ -0,0 +1,19 @@ +var co = require('co'); +var fs = require('fs'); +var path = require('path'); +var log = require('log')(); +var gutil = require('gulp-util'); +var glob = require('glob'); +let exec = require('mz/child_process').exec; +let ini = require('ini'); + +module.exports = function(options) { + + return function() { + + return async function() { + console.log("TEST"); + + }(); + }; +}; diff --git a/handlers/dev/templates/index.pug b/handlers/dev/templates/index.pug new file mode 100755 index 0000000..2cf1262 --- /dev/null +++ b/handlers/dev/templates/index.pug @@ -0,0 +1,12 @@ + +extends /layouts/main + +block append variables + - var sitetoolbar = true + - var title = "Test page" + + +block content + + +b.test + +e.hello HELLO \ No newline at end of file diff --git a/handlers/errorHandler/index.js b/handlers/errorHandler/index.js index d4e34a9..3b408db 100755 --- a/handlers/errorHandler/index.js +++ b/handlers/errorHandler/index.js @@ -7,7 +7,7 @@ var isDevelopment = process.env.NODE_ENV == 'development'; // can be called not from this MW, but from anywhere // this.templateDir can be anything -function renderError(err) { +function renderError(ctx, err) { /*jshint -W040 */ // don't pass just err, because for "stack too deep" errors it leads to logging problems @@ -16,22 +16,22 @@ function renderError(err) { stack: err.stack, errors: err.errors, // for validation errors status: err.status, - referer: this.get('referer'), - cookie: this.get('cookie') + referer: ctx.get('referer'), + cookie: ctx.get('cookie') }; if (!err.expose) { // dev error - report.requestVerbose = this.request; + report.requestVerbose = ctx.request; } - this.log.error(report); + ctx.log.error(report); // may be error if headers are already sent! - this.set('X-Content-Type-Options', 'nosniff'); + ctx.set('X-Content-Type-Options', 'nosniff'); - var preferredType = this.accepts('html', 'json'); + var preferredType = ctx.accepts('html', 'json'); if (err.name == 'ValidationError') { - this.status = 400; + ctx.status = 400; if (preferredType == 'json') { var errors = {}; @@ -40,11 +40,11 @@ function renderError(err) { errors[field] = err.errors[field].message; } - this.body = { + ctx.body = { errors: errors }; } else { - this.body = this.render(path.join(__dirname, "templates/400"), { + ctx.body = ctx.render(path.join(__dirname, "templates/400"), { useAbsoluteTemplatePath: true, error: err }); @@ -54,7 +54,7 @@ function renderError(err) { } if (isDevelopment) { - this.status = err.status || 500; + ctx.status = err.status || 500; var stack = (err.stack || '') .split('\n').slice(1) @@ -63,35 +63,35 @@ function renderError(err) { }).join(''); if (preferredType == 'json') { - this.body = { + ctx.body = { message: err.message, stack: stack }; - this.body.statusCode = err.statusCode || err.status; + ctx.body.statusCode = err.statusCode || err.status; } else { - this.type = 'text/html; charset=utf-8'; - this.body = "

" + err.message + "

"; + ctx.type = 'text/html; charset=utf-8'; + ctx.body = "

" + err.message + "

"; } return; } - this.status = err.expose ? err.status : 500; + ctx.status = err.expose ? err.status : 500; if (preferredType == 'json') { - this.body = { + ctx.body = { message: err.message, statusCode: err.status || err.statusCode }; if (err.description) { - this.body.description = err.description; + ctx.body.description = err.description; } } else { - var templateName = ~[500, 401, 404, 403].indexOf(this.status) ? this.status : 500; - this.body = this.render(`${__dirname}/templates/${templateName}`, { + var templateName = ~[500, 401, 404, 403].indexOf(ctx.status) ? ctx.status : 500; + ctx.body = ctx.render(`${__dirname}/templates/${templateName}`, { useAbsoluteTemplatePath: true, error: err, - requestId: this.requestId + requestId: ctx.requestId }); } @@ -100,45 +100,27 @@ function renderError(err) { exports.init = function(app) { - app.use(function*(next) { - this.renderError = renderError; + app.use(async function(ctx, next) { + ctx.renderError = renderError; try { - yield* next; + await next; } catch (err) { - if (typeof err == 'string') { // fx error + if (typeof err !== 'object') { // 'fx error' from money or mb another module err = new Error(err); } - // this middleware is not like others, it is not endpoint + // ctx middleware is not like others, it is not endpoint // so wrapHmvcMiddleware is of little use try { - this.renderError(err); + ctx.renderError(err); } catch(renderErr) { // could not render, maybe template not found or something - this.status = 500; - this.body = "Server render error"; - this.log.error(renderErr); // make it last to ensure that status/body are set + ctx.status = 500; + ctx.body = "Server render error"; + ctx.log.error(renderErr); // make it last to ensure that status/body are set } } }); - // this middleware handles error BEFORE ^^^ - // rewrite mongoose wrong mongoose parameter -> 400 (not 500) - app.use(function* rewriteCastError(next) { - - try { - yield next; - } catch (err) { - if (err.name == 'CastError') { - // malformed or absent mongoose params - if (process.env.NODE_ENV == 'production') { // do not rewrite in dev/test env - this.throw(400); - } - } - - throw err; - } - - }); }; diff --git a/handlers/errorHandler/templates/400.jade b/handlers/errorHandler/templates/400.pug similarity index 100% rename from handlers/errorHandler/templates/400.jade rename to handlers/errorHandler/templates/400.pug diff --git a/handlers/errorHandler/templates/401.jade b/handlers/errorHandler/templates/401.pug similarity index 100% rename from handlers/errorHandler/templates/401.jade rename to handlers/errorHandler/templates/401.pug diff --git a/handlers/errorHandler/templates/403.jade b/handlers/errorHandler/templates/403.pug similarity index 100% rename from handlers/errorHandler/templates/403.jade rename to handlers/errorHandler/templates/403.pug diff --git a/handlers/errorHandler/templates/404.jade b/handlers/errorHandler/templates/404.pug similarity index 100% rename from handlers/errorHandler/templates/404.jade rename to handlers/errorHandler/templates/404.pug diff --git a/handlers/errorHandler/templates/500.jade b/handlers/errorHandler/templates/500.pug similarity index 100% rename from handlers/errorHandler/templates/500.jade rename to handlers/errorHandler/templates/500.pug diff --git a/handlers/multipartParser.js b/handlers/multipartParser.js index ab8e363..c3eb230 100755 --- a/handlers/multipartParser.js +++ b/handlers/multipartParser.js @@ -61,21 +61,21 @@ MultipartParser.prototype.middleware = function() { // skip these methods var contentType = this.get('content-type') || ''; if (!~['DELETE', 'POST', 'PUT', 'PATCH'].indexOf(this.method) || !contentType.startsWith('multipart/form-data')) { - return yield* next; + return await next; } if (!self.ignore.check(this.path)) { this.log.debug("multipart will parse"); // this may throw an error w/ status 400 or 415 or... - this.request.body = yield self.parse(this.req); + this.request.body = await self.parse(this.req); this.log.debug("multipart done parse"); } else { this.log.debug("multipart skip"); } - yield* next; + await next; }; }; diff --git a/handlers/nocache.js b/handlers/nocache.js index 27d562b..0cd13fa 100755 --- a/handlers/nocache.js +++ b/handlers/nocache.js @@ -6,7 +6,7 @@ exports.init = function(app) { this.set('Cache-Control', 'no-cache, no-store, must-revalidate'); }; - yield* next; + await next; }); }; diff --git a/handlers/nodeExample/controller/node.js b/handlers/nodeExample/controller/node.js index c049a36..5fba5f5 100755 --- a/handlers/nodeExample/controller/node.js +++ b/handlers/nodeExample/controller/node.js @@ -19,40 +19,40 @@ function clean(pathOrPiece) { } -exports.all = function*() { +exports.all = async function(ctx) { // bad path: http://javascript.local/task/capslock-warning-field/solution - if (this.params.serverPath === undefined) { - this.throw(404); + if (ctx.params.serverPath === undefined) { + ctx.throw(404); } // for /article/ajax-xmlhttprequest/xhr/test: xhr/test - var serverPath = clean(this.params.serverPath); - var slug = clean(this.params.slug); - var view = clean(this.params.view); - var taskOrArticle = this.url.match(/\w+/)[0]; + var serverPath = clean(ctx.params.serverPath); + var slug = clean(ctx.params.slug); + var view = clean(ctx.params.view); + var taskOrArticle = ctx.url.match(/\w+/)[0]; var modulePath = path.join(config.publicRoot, taskOrArticle, slug, view, 'server.js'); - this.log.debug("trying modulePath", modulePath); + ctx.log.debug("trying modulePath", modulePath); - if (yield fs.exists(modulePath)) { + if (await fs.exists(modulePath)) { var server = require(modulePath); - this.req.url = "/" + serverPath; + ctx.req.url = "/" + serverPath; - var originalUrl = this.request.originalUrl; + var originalUrl = ctx.request.originalUrl; if (~originalUrl.indexOf('?')) { - this.req.url += originalUrl.slice(originalUrl.indexOf('?')); + ctx.req.url += originalUrl.slice(originalUrl.indexOf('?')); } - this.res.statusCode = 200; // reset default koa 404 assignment - this.log.debug("passing control to modulePath server, url=", this.req.url); - this.respond = false; - server.accept(this.req, this.res); + ctx.res.statusCode = 200; // reset default koa 404 assignment + ctx.log.debug("passing control to modulePath server, url=", ctx.req.url); + ctx.respond = false; + server.accept(ctx.req, ctx.res); } else { - this.throw(404); + ctx.throw(404); } }; diff --git a/handlers/render.js b/handlers/render.js index c139ebd..65632eb 100755 --- a/handlers/render.js +++ b/handlers/render.js @@ -6,7 +6,7 @@ const path = require('path'); const config = require('config'); const fs = require('fs'); const log = require('log')(); -const jade = require('lib/serverJade'); +const pug = require('lib/serverPug'); const assert = require('assert'); const t = require('i18n'); @@ -87,11 +87,11 @@ function addStandardHelpers(locals, ctx) { }; locals.t = t; - locals.bem = require('bemJade')(); + //locals.bem = require('bemPug')(); locals.pack = function(name, ext) { var versions = JSON.parse( - fs.readFileSync(path.join(config.manifestRoot, 'pack.versions.json'), {encoding: 'utf-8'}) + fs.readFileSync(path.join(config.cacheRoot, 'webpback.versions.json'), {encoding: 'utf-8'}) ); var versionName = versions[name]; // e.g style = [ style.js, style.js.map, style.css, style.css.map ] @@ -129,7 +129,7 @@ exports.init = function(app) { var renderFileCache = {}; - this.locals = Object.assign({}, config.jade); + this.locals = Object.assign({}, config.pug); /** * Render template @@ -170,7 +170,7 @@ exports.init = function(app) { var templatePathResolved = resolvePath(templatePath, loc); this.log.debug("render file " + templatePathResolved); - return jade.renderFile(templatePathResolved, loc); + return pug.renderFile(templatePathResolved, loc); }; function resolvePath(templatePath, options) { @@ -183,8 +183,8 @@ exports.init = function(app) { // first we try template.en.jade // if fails then template.jade var templatePathWithLangAndExt = templatePath + '.' + config.lang; - if (!/\.jade$/.test(templatePathWithLangAndExt)) { - templatePathWithLangAndExt += '.jade'; + if (!/\.pug/.test(templatePathWithLangAndExt)) { + templatePathWithLangAndExt += '.pug'; } @@ -202,7 +202,7 @@ exports.init = function(app) { } if (!fs.existsSync(templatePathResolved)) { - templatePathResolved = templatePathResolved.replace(`.${config.lang}.jade`, '.jade'); + templatePathResolved = templatePathResolved.replace(`.${config.lang}.pug`, '.pug'); } renderFileCache[cacheKey] = templatePathResolved; @@ -210,7 +210,7 @@ exports.init = function(app) { return templatePathResolved; } - yield* next; + await next; }); }; diff --git a/handlers/requestId.js b/handlers/requestId.js index 6804fba..ad6fdb5 100755 --- a/handlers/requestId.js +++ b/handlers/requestId.js @@ -6,6 +6,6 @@ exports.init = function(app) { app.use(function*(next) { /* jshint -W106 */ this.requestId = this.get('X-Request-Id') || uuid(); - yield next; + await next; }); }; diff --git a/handlers/requestLog.js b/handlers/requestLog.js index 9b92902..65d78ff 100755 --- a/handlers/requestLog.js +++ b/handlers/requestLog.js @@ -7,7 +7,7 @@ exports.init = function(app) { requestId: this.requestId }); - yield* next; + await next; }); }; diff --git a/handlers/tutorial/controller/article.js b/handlers/tutorial/controller/article.js index 02f3fec..3ba272a 100755 --- a/handlers/tutorial/controller/article.js +++ b/handlers/tutorial/controller/article.js @@ -1,5 +1,6 @@ 'use strict'; +const TutorialTree = require('../models/tutorialTree'); const Article = require('../models/article'); const Task = require('../models/task'); const ArticleRenderer = require('../renderer/articleRenderer'); @@ -7,20 +8,22 @@ const TaskRenderer = require('../renderer/taskRenderer'); const _ = require('lodash'); const makeAnchor = require('textUtil/makeAnchor'); const t = require('i18n'); +const localStorage = require('localStorage'); -exports.get = function *get(next) { - - var renderedArticle = yield* CacheEntry.getOrGenerate({ - key: 'tutorial:article:' + this.params.slug, - tags: ['article'] - }, renderArticle.bind(this, this.params.slug), process.env.TUTORIAL_EDIT); +exports.get = async function get(ctx, next) { + + let renderedArticle = await localStorage.getOrGenerate( + 'tutorial:article:' + ctx.params.slug, + () => renderArticle(ctx, ctx.params.slug), + process.env.TUTORIAL_EDIT + ); if (!renderedArticle) { - yield* next; + await next; return; } - var locals = renderedArticle; + let locals = renderedArticle; locals.sitetoolbar = true; @@ -31,7 +34,7 @@ exports.get = function *get(next) { locals.comments = true; } - var sections = []; + let sections = []; if (renderedArticle.isFolder) { sections.push({ @@ -46,7 +49,7 @@ exports.get = function *get(next) { links: [renderedArticle.breadcrumbs[renderedArticle.breadcrumbs.length-1]] }); - var headerLinks = renderedArticle.headers + let headerLinks = renderedArticle.headers .filter(function(header) { // [level, titleHtml, anchor] return header.level == 2; @@ -68,7 +71,7 @@ exports.get = function *get(next) { if (!renderedArticle.isFolder) { - var section2 = { + let section2 = { class: '_separator_before', links: [] }; @@ -106,21 +109,21 @@ exports.get = function *get(next) { // next // path // siblings -function* renderArticle(slug) { +async function renderArticle(ctx, slug) { - const article = yield Article.findOne({ slug: slug }); + const tree = TutorialTree.instance(); + const article = tree.bySlug(slug); if (!article) { return null; } - this.log.debug("article", article._id); - - - var renderer = new ArticleRenderer(); + ctx.log.debug("article", article._id); + + let renderer = new ArticleRenderer(); - var rendered = yield* renderer.renderWithCache(article); + let rendered = await renderer.render(article); - this.log.debug("rendered"); + ctx.log.debug("rendered"); rendered.isFolder = article.isFolder; rendered.modified = article.modified; @@ -130,62 +133,61 @@ function* renderArticle(slug) { rendered.githubLink = article.githubLink; rendered.canonicalPath = article.getUrl(); - const tree = yield* Article.findTree(); - const articleInTree = tree.byId(article._id); - - yield* renderProgress(); - yield* renderPrevNext(); - yield* renderBreadCrumb(); - yield* renderSiblings(); - yield* renderChildren(); - yield* renderTasks(); + await renderProgress(); + await renderPrevNext(); + await renderBreadCrumb(); + await renderSiblings(); + await renderChildren(); + await renderTasks(); // strip / and /tutorial rendered.level = rendered.breadcrumbs.length - 2; // starts at 0 - if (articleInTree.isFolder) { + if (article.isFolder) { // levelMax is 2 for deep courses or 1 for plain courses - rendered.levelMax = articleInTree.children[0].isFolder ? rendered.level + 2 : rendered.level + 1; + rendered.levelMax = tree.bySlug(children[0]).isFolder ? rendered.level + 2 : rendered.level + 1; } - function* renderPrevNext() { + async function renderPrevNext() { - var prev = tree.byId(articleInTree.prev); + let prev = tree.getPrev(article.slug); if (prev) { + prev = tree.bySlug(prev); rendered.prev = { - url: Article.getUrlBySlug(prev.slug), + url: prev.getUrl(), title: prev.title }; } - var next = tree.byId(articleInTree.next); + let next = tree.getNext(article.slug); if (next) { + next = tree.bySlug(next); rendered.next = { - url: Article.getUrlBySlug(next.slug), + url: next.getUrl(), title: next.title }; } } - function* renderProgress() { - var parent = articleInTree.parent; - var bookRoot = articleInTree; - while (parent) { - bookRoot = tree.byId(parent); - parent = bookRoot.parent; + + + async function renderProgress() { + let parent = article; + while (parent.parent) { + parent = tree.bySlug(parent.parent); } // now bookroot is 1st level tree item, book root, let's count items in it //console.log(bookRoot); - var bookLeafCount = 0; - var bookChildNumber; - function countChildren(tree) { - if (tree == articleInTree) { + let bookLeafCount = 0; + let bookChildNumber; + function countChildren(article) { + if (tree === article) { bookChildNumber = bookLeafCount + 1; } @@ -207,58 +209,55 @@ function* renderArticle(slug) { //console.log(bookLeafCount, bookChildNumber); } - function* renderBreadCrumb() { - var path = []; - var parent = articleInTree.parent; + async function renderBreadCrumb() { + let path = []; + let parent = article.parent; while (parent) { - var a = tree.byId(parent); + let a = tree.bySlug(parent); path.push({ title: a.title, - url: Article.getUrlBySlug(a.slug) + url: a.getUrl() }); parent = a.parent; } path.push({ - title: 'Учебник', + title: t('site.tutorial'), url: '/' }); - /* - path.push({ - title: 'JavaScript.ru', - url: 'http://javascript.ru' - }); - */ path = path.reverse(); rendered.breadcrumbs = path; } - function* renderSiblings() { - var siblings = tree.siblings(articleInTree._id); - rendered.siblings = siblings.map(function(sibling) { + async function renderSiblings() { + let siblings = tree.getSiblings(article.slug); + rendered.siblings = siblings.map(slug => { + let sibling = tree.bySlug(slug); return { title: sibling.title, - url: Article.getUrlBySlug(sibling.slug) + url: sibling.getUrl() }; }); } - function* renderChildren() { - if (!articleInTree.isFolder) return; - var children = articleInTree.children || []; - rendered.children = children.map(function(child) { - var renderedChild = { + async function renderChildren() { + if (!article.isFolder) return; + let children = article.children || []; + rendered.children = children.map(slug => { + let child = tree.bySlug(slug); + let renderedChild = { title: child.title, - url: Article.getUrlBySlug(child.slug), + url: child.getUrl(), weight: child.weight }; if (child.isFolder) { - renderedChild.children = (child.children || []).map(function(subChild) { + renderedChild.children = (child.children || []).map((slug) => { + let subChild = tree.bySlug(slug); return { title: subChild.title, - url: Article.getUrlBySlug(subChild.slug), - weight: child.weight + url: subChild.getUrl(), + weight: subChild.weight }; }); } @@ -267,20 +266,18 @@ function* renderArticle(slug) { }); } - function *renderTasks() { - var tasks = yield Task.find({ - parent: article._id - }).sort({weight: 1}); + async function renderTasks() { + let tasks = article.children.map(slug => { + return tree.bySlug(slug); + }); const taskRenderer = new TaskRenderer(); - rendered.tasks = []; - for (var i = 0; i < tasks.length; i++) { - var task = tasks[i]; + for (let task of tasks) { - var taskRendered = yield* taskRenderer.renderWithCache(task); + let taskRendered = await taskRenderer.render(task); rendered.tasks.push({ url: task.getUrl(), title: task.title, diff --git a/handlers/tutorial/controller/frontpage.js b/handlers/tutorial/controller/frontpage.js index c6db8da..bd38675 100755 --- a/handlers/tutorial/controller/frontpage.js +++ b/handlers/tutorial/controller/frontpage.js @@ -12,7 +12,7 @@ exports.get = function *get(next) { this.locals.title = "Современный учебник JavaScript"; - var tutorial = yield CacheEntry.getOrGenerate({ + var tutorial = await CacheEntry.getOrGenerate({ key: 'tutorial:frontpage', tags: ['article'] }, renderTutorial); @@ -38,14 +38,14 @@ exports.get = function *get(next) { // path // siblings function* renderTutorial() { - const tree = yield* Article.findTree(); + const tree = await Article.findTree(); - var treeRendered = yield* renderTree(tree); + var treeRendered = await renderTree(tree); // render top-level content for (var i = 0; i < treeRendered.length; i++) { var child = treeRendered[i]; - yield* populateContent(child); + await populateContent(child); } @@ -67,7 +67,7 @@ function* renderTree(tree) { }; if (child.isFolder) { - childRendered.children = yield* renderTree(child); + childRendered.children = await renderTree(child); } children.push(childRendered); @@ -78,11 +78,11 @@ function* renderTree(tree) { function* populateContent(articleObj) { - var article = yield Article.findById(articleObj.id); + var article = await Article.findById(articleObj.id); var renderer = new ArticleRenderer(); - var rendered = yield* renderer.renderWithCache(article); + var rendered = await renderer.renderWithCache(article); articleObj.content = rendered.content; } diff --git a/handlers/tutorial/controller/map.js b/handlers/tutorial/controller/map.js index 2308c0c..b49c68a 100755 --- a/handlers/tutorial/controller/map.js +++ b/handlers/tutorial/controller/map.js @@ -8,8 +8,6 @@ const TaskRenderer = require('../renderer/taskRenderer'); const _ = require('lodash'); const makeAnchor = require('textUtil/makeAnchor'); -const localStorage = require('localStorage'); - const t = require('i18n'); const LANG = require('config').lang; @@ -20,16 +18,17 @@ exports.get = function* get() { const tutorialTree = TutorialTree.instance(); - var template = this.get('X-Requested-With') ? '_map' : 'map'; + const template = this.get('X-Requested-With') ? '_map' : 'map'; + console.log(tutorialTree.tree); this.body = this.render(template, { bySlug: tutorialTree.bySlug.bind(tutorialTree), roots: [ - treeRendered[0], - treeRendered[1], + tutorialTree.tree[0], + tutorialTree.tree[1], { title: t('site.additional_articles'), - children: treeRendered.slice(2) + children: tutorialTree.tree.slice(2) } ] }); diff --git a/handlers/tutorial/controller/task.js b/handlers/tutorial/controller/task.js index 7d998ae..3e277c8 100755 --- a/handlers/tutorial/controller/task.js +++ b/handlers/tutorial/controller/task.js @@ -6,18 +6,18 @@ const TaskRenderer = require('../renderer/taskRenderer'); exports.get = function *get(next) { - const task = yield Task.findOne({ + const task = await Task.findOne({ slug: this.params.slug }).populate('parent'); if (!task) { - yield* next; + await next; return; } const renderer = new TaskRenderer(); - const rendered = yield* renderer.renderWithCache(task); + const rendered = await renderer.renderWithCache(task); this.locals.githubLink = task.githubLink; @@ -26,7 +26,7 @@ exports.get = function *get(next) { var parentId = task.parent._id; while (true) { - let parent = yield Article.findById(parentId, {slug: 1, title: 1, parent: 1}); + let parent = await Article.findById(parentId, {slug: 1, title: 1, parent: 1}); if (!parent) break; breadcrumbs.push({ url: parent.getUrl(), diff --git a/handlers/tutorial/lib/resolveTutorialLinks.js b/handlers/tutorial/lib/resolveTutorialLinks.js index 764e27e..da21278 100755 --- a/handlers/tutorial/lib/resolveTutorialLinks.js +++ b/handlers/tutorial/lib/resolveTutorialLinks.js @@ -45,11 +45,11 @@ module.exports = function* (tokens) { token.children[i + 2].type == 'link_close'; if (pathname.startsWith('task/')) { - let task = yield Task.findOne({slug: pathname.slice('task/'.length)}, 'slug title'); + let task = await Task.findOne({slug: pathname.slice('task/'.length)}, 'slug title'); if (task) replaceLink(token.children, i, task.title, task.getUrl(), urlParsed); else replaceLinkWithError(token.children, i, t('tutorial.task.task_not_found', {path: pathname})); } else { - let article = yield Article.findOne({slug: pathname}, 'slug title'); + let article = await Article.findOne({slug: pathname}, 'slug title'); if (article) replaceLink(token.children, i, article.title, article.getUrl(), urlParsed); else replaceLinkWithError(token.children, i, t('tutorial.article.article_not_found', {path: pathname})); } diff --git a/handlers/tutorial/lib/tutorialParser.js b/handlers/tutorial/lib/tutorialParser.js index e51030b..37c4d8e 100755 --- a/handlers/tutorial/lib/tutorialParser.js +++ b/handlers/tutorial/lib/tutorialParser.js @@ -12,8 +12,8 @@ const ServerParser = require('markit').ServerParser; module.exports = class TutorialParser extends ServerParser { *parse(text) { - const tokens = yield* super.parse(text); - yield* resolveTutorialLinks(tokens, this.md.options); + const tokens = await super.parse(text); + await resolveTutorialLinks(tokens, this.md.options); return tokens; } diff --git a/handlers/tutorial/models/tutorialTree.js b/handlers/tutorial/models/tutorialTree.js index 65805e0..b66b73a 100755 --- a/handlers/tutorial/models/tutorialTree.js +++ b/handlers/tutorial/models/tutorialTree.js @@ -13,6 +13,29 @@ module.exports = class TutorialTree { return this.bySlugMap[slug]; } + getSiblings(slug) { + let entry = this.bySlug(slug); + return entry.parent ? this.bySlug(entry.parent).children : this.tree; + } + + getPrev(slug) { + let entry = this.bySlug(slug); + let parentChildren = entry.parent ? this.bySlug(entry.parent).children : this.tree; + let idx = parentChildren.indexOf(slug); + assert(idx >= 0); + + return idx == 0 ? null : parentChildren[idx - 1]; + } + + getNext(slug) { + let entry = this.bySlug(slug); + let parentChildren = entry.parent ? this.bySlug(entry.parent).children : this.tree; + let idx = parentChildren.indexOf(slug); + assert(idx >= 0); + + return idx == (parentChildren.length-1) ? null : parentChildren[idx + 1]; + } + addToSlugMap(entry) { this.bySlugMap[entry.slug] = entry; } diff --git a/handlers/tutorial/renderer/articleRenderer.js b/handlers/tutorial/renderer/articleRenderer.js index c0d5229..34fbd48 100755 --- a/handlers/tutorial/renderer/articleRenderer.js +++ b/handlers/tutorial/renderer/articleRenderer.js @@ -16,202 +16,167 @@ const TutorialParser = require('../lib/tutorialParser'); /** * Can render many articles, joining metadata - * @constructor */ -function ArticleRenderer() { - this.libs = []; - this.headCss = []; - this.headJs = []; - this.headHtml = []; - - // shared across all renderings - // shared headingsMap to prevent same ids - this.env = {}; - - Object.defineProperties(this, { - headers:{ - get() { - throw new Error("Deprecated get headers"); - } - }, - content:{ - get() { - throw new Error("Deprecated get content"); - } - } - }); -} +module.exports = class ArticleRenderer { + constructor() { + this.libs = []; + this.headCss = []; + this.headJs = []; + this.headHtml = []; + + // shared across all renderings + // shared headingsMap to prevent same ids + this.env = {}; + + } // gets content from metadata.libs & metadata.head -ArticleRenderer.prototype.getHead = function() { - return [].concat( - this._libsToJsCss( - this._unmapLibsNames(this.libs) - ).css, - this._libsToJsCss( - this._unmapLibsNames(this.libs) - ).js, - this.headCss.length && ``, - this.headJs.length && ``, - this.headHtml.join('\n')) - .filter(Boolean).join('\n'); -}; + getHead() { + return [].concat( + this._libsToJsCss( + this._unmapLibsNames(this.libs) + ).css, + this._libsToJsCss( + this._unmapLibsNames(this.libs) + ).js, + this.headCss.length && ``, + this.headJs.length && ``, + this.headHtml.join('\n')) + .filter(Boolean).join('\n'); + } // Все библиотеки должны быть уникальны // Если один ресурс требует JQUERY и другой тоже, то нужно загрузить только один раз JQUERY // Именно форматтер окончательно форматирует библиотеки, т.к. он знает про эти мапппинги // // Кроме того, парсер может распарсить много документов для сбора метаданных -ArticleRenderer.prototype._unmapLibsNames = function(libs) { - var libsUnmapped = []; - - // заменить все-все короткие имена - // предполагается, что короткое имя при раскрытии не содержит другого короткого имени (легко заимплементить) - - libs.forEach(function(lib) { - switch (lib) { - case 'lodash': - libsUnmapped.push("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"); - break; - - case 'd3': - libsUnmapped.push("https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"); - break; + _unmapLibsNames(libs) { + var libsUnmapped = []; - case 'domtree': - libsUnmapped.push("domtree.css", "domtree.js"); - break; - - default: - libsUnmapped.push(lib); - } - }); - - return libsUnmapped; -}; + // заменить все-все короткие имена + // предполагается, что короткое имя при раскрытии не содержит другого короткого имени (легко заимплементить) + libs.forEach(function (lib) { + switch (lib) { + case 'lodash': + libsUnmapped.push("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"); + break; -ArticleRenderer.prototype._libsToJsCss = function(libs) { - var js = []; - var css = []; + case 'd3': + libsUnmapped.push("https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"); + break; - _.uniq(libs).forEach(function(lib) { - if (!~lib.indexOf('://')) { - lib = '//' + config.domain.static + '/libs/' + lib; - } - - if (lib.slice(-3) == '.js') { - js.push(''); - } else if (lib.slice(-4) == '.css') { - css.push(""); - } else { - js.push(""); - } - }); + case 'domtree': + libsUnmapped.push("domtree.css", "domtree.js"); + break; - return { - js: js, - css: css - }; -}; - -/** - * Render, gather metadata to the renderer object - * @param article - * @param options - * options.headerLevelShift shifts all headers (to render in ebook as a subchapter0 - * @returns {{content: *, headers: *, head: *}} - */ -ArticleRenderer.prototype.render = function* (article, options) { - - options = Object.assign({ - resourceWebRoot: article.getResourceWebRoot(), - env: this.env - }, options || {}); + default: + libsUnmapped.push(lib); + } + }); - if (options.linkHeaderTag === undefined) options.linkHeaderTag = true; + return libsUnmapped; + } - let parser = new TutorialParser(options); - const tokens = yield* parser.parse(article.content); + _libsToJsCss(libs) { + var js = []; + var css = []; - let headers = []; + _.uniq(libs).forEach(function (lib) { + if (!~lib.indexOf('://')) { + lib = '//' + config.domain.static + '/libs/' + lib; + } - for (let idx = 0; idx < tokens.length; idx++) { - let token = tokens[idx]; - if (token.type == 'heading_open') { - let i = idx + 1; - while (tokens[i].type != 'heading_close') i++; + if (lib.slice(-3) == '.js') { + js.push(''); + } else if (lib.slice(-4) == '.css') { + css.push(""); + } else { + js.push(""); + } + }); - let headingTokens = tokens.slice(idx + 1, i); + return { + js: js, + css: css + }; + } - headers.push({ - level: +token.tag.slice(1), - anchor: token.anchor, - title: parser.render(headingTokens) - }); + /** + * Render, gather metadata to the renderer object + * @param article + * @param options + * options.headerLevelShift shifts all headers (to render in ebook as a subchapter0 + * @returns {{content: *, headers: *, head: *}} + */ + async render(article, options) { - idx = i; - } + options = Object.assign({ + resourceWebRoot: article.getResourceWebRoot(), + env: this.env + }, options || {}); - } + if (options.linkHeaderTag === undefined) options.linkHeaderTag = true; - let content = parser.render(tokens); + let parser = new TutorialParser(options); - for (var i = 0; i < article.libs.length; i++) { - this.libs.push(article.libs[i]); - } + const tokens = await parser.parse(article.content); - if (article.headCss) { - this.headCss.push(article.headCss); - } - if (article.headJs) { - this.headJs.push(article.headJs); - } - if (article.headHtml) { - this.headHtml.push(article.headHtml); - } + let headers = []; + for (let idx = 0; idx < tokens.length; idx++) { + let token = tokens[idx]; + if (token.type == 'heading_open') { + let i = idx + 1; + while (tokens[i].type != 'heading_close') i++; - return { - content: content, - headers: headers, - head: this.getHead() - }; -}; + let headingTokens = tokens.slice(idx + 1, i); -/** - * Render with cache - * @param article - * @param options Add refreshCache: true not to use the cached value - * @returns {*} - */ -ArticleRenderer.prototype.renderWithCache = function*(article, options) { - options = options || {}; + headers.push({ + level: +token.tag.slice(1), + anchor: token.anchor, + title: parser.render(headingTokens) + }); - var useCache = !options.refreshCache && !process.env.TUTORIAL_EDIT; + idx = i; + } - if (article.rendered && useCache) return article.rendered; + } - var rendered = yield* this.render(article); + let content = parser.render(tokens); - article.rendered = rendered; + for (var i = 0; i < article.libs.length; i++) { + this.libs.push(article.libs[i]); + } - yield article.persist(); + if (article.headCss) { + this.headCss.push(article.headCss); + } + if (article.headJs) { + this.headJs.push(article.headJs); + } + if (article.headHtml) { + this.headHtml.push(article.headHtml); + } - return rendered; -}; + return { + content: content, + headers: headers, + head: this.getHead() + }; + } +} +/* ArticleRenderer.regenerateCaches = function*() { - var articles = yield Article.find({}); + var articles = await Article.find({}); for (var i = 0; i < articles.length; i++) { var article = articles[i]; log.debug("regenerate article", article._id); - yield* (new ArticleRenderer()).renderWithCache(article, {refreshCache: true}); + await (new ArticleRenderer()).renderWithCache(article, {refreshCache: true}); } -}; - +};*/ -module.exports = ArticleRenderer; diff --git a/handlers/tutorial/renderer/taskRenderer.js b/handlers/tutorial/renderer/taskRenderer.js index 7f90dde..b26d404 100755 --- a/handlers/tutorial/renderer/taskRenderer.js +++ b/handlers/tutorial/renderer/taskRenderer.js @@ -26,18 +26,18 @@ TaskRenderer.prototype.renderContent = function* (task, options) { resourceWebRoot: task.getResourceWebRoot() }, options)); - const tokens = yield* parser.parse(task.content); + const tokens = await parser.parse(task.content); let content = parser.render(tokens); - content = yield* this.addContentPlunkLink(task, content); + content = await this.addContentPlunkLink(task, content); return content; }; TaskRenderer.prototype.addContentPlunkLink = function*(task, content) { - var sourcePlunk = yield Plunk.findOne({webPath: task.getResourceWebRoot() + '/source'}); + var sourcePlunk = await Plunk.findOne({webPath: task.getResourceWebRoot() + '/source'}); if (sourcePlunk) { @@ -57,8 +57,8 @@ TaskRenderer.prototype.addContentPlunkLink = function*(task, content) { TaskRenderer.prototype.render = function*(task, options) { - this.content = yield* this.renderContent(task, options); - this.solution = yield* this.renderSolution(task, options); + this.content = await this.renderContent(task, options); + this.solution = await this.renderSolution(task, options); return { content: this.content, @@ -73,11 +73,11 @@ TaskRenderer.prototype.renderWithCache = function*(task, options) { if (task.rendered && useCache) return task.rendered; - var rendered = yield* this.render(task, options); + var rendered = await this.render(task, options); task.rendered = rendered; - yield task.persist(); + await task.persist(); return rendered; }; @@ -89,7 +89,7 @@ TaskRenderer.prototype.renderSolution = function* (task, options) { resourceWebRoot: task.getResourceWebRoot() }, options)); - const tokens = yield* parser.parse(task.solution); + const tokens = await parser.parse(task.solution); const solutionParts = []; @@ -98,7 +98,7 @@ TaskRenderer.prototype.renderSolution = function* (task, options) { // no parts, single solution if (tokens.length == 0 || tokens[0].type != 'heading_open') { let solution = parser.render(tokens); - solution = yield* this.addSolutionPlunkLink(task, solution); + solution = await this.addSolutionPlunkLink(task, solution); return solution; } @@ -132,14 +132,14 @@ TaskRenderer.prototype.renderSolution = function* (task, options) { } var solutionPartLast = solutionParts[solutionParts.length - 1]; - solutionParts[solutionParts.length - 1].content = yield* this.addSolutionPlunkLink(task, solutionPartLast.content); + solutionParts[solutionParts.length - 1].content = await this.addSolutionPlunkLink(task, solutionPartLast.content); return solutionParts; }; TaskRenderer.prototype.addSolutionPlunkLink = function*(task, solution) { - var solutionPlunk = yield Plunk.findOne({webPath: task.getResourceWebRoot() + '/solution'}); + var solutionPlunk = await Plunk.findOne({webPath: task.getResourceWebRoot() + '/solution'}); if (solutionPlunk) { var files = solutionPlunk.files.toObject(); @@ -158,12 +158,12 @@ TaskRenderer.prototype.addSolutionPlunkLink = function*(task, solution) { TaskRenderer.regenerateCaches = function*() { - var tasks = yield Task.find({}); + var tasks = await Task.find({}); for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; log.debug("regenerate task", task._id); - yield* (new TaskRenderer()).renderWithCache(task, {refreshCache: true}); + await (new TaskRenderer()).renderWithCache(task, {refreshCache: true}); } }; diff --git a/handlers/tutorial/tasks/cacheRegenerate.js b/handlers/tutorial/tasks/cacheRegenerate.js index 7d10b88..95ea012 100755 --- a/handlers/tutorial/tasks/cacheRegenerate.js +++ b/handlers/tutorial/tasks/cacheRegenerate.js @@ -10,8 +10,8 @@ module.exports = function() { return function() { return co(function*() { - yield* ArticleRenderer.regenerateCaches(); - yield* TaskRenderer.regenerateCaches(); + await ArticleRenderer.regenerateCaches(); + await TaskRenderer.regenerateCaches(); }); }; diff --git a/handlers/tutorial/tasks/edit.js b/handlers/tutorial/tasks/edit.js index a3c6f20..e74115f 100755 --- a/handlers/tutorial/tasks/edit.js +++ b/handlers/tutorial/tasks/edit.js @@ -24,7 +24,7 @@ module.exports = function(options) { var urlPath = url.parse(args.url).pathname.split('/').filter(Boolean); if (urlPath.length == 1) { - var article = yield Article.findOne({slug: urlPath[0]}); + var article = await Article.findOne({slug: urlPath[0]}); if (!article) { console.log("Not found!"); return; @@ -48,7 +48,7 @@ module.exports = function(options) { } if (urlPath[0] == 'task') { - var task = yield Task.findOne({slug: urlPath[1]}); + var task = await Task.findOne({slug: urlPath[1]}); if (!task) { return; } diff --git a/handlers/tutorial/tasks/figuresImport.js b/handlers/tutorial/tasks/figuresImport.js index 6097015..30f671a 100755 --- a/handlers/tutorial/tasks/figuresImport.js +++ b/handlers/tutorial/tasks/figuresImport.js @@ -29,7 +29,7 @@ module.exports = function(options) { return co(function* () { - yield* importer.syncFigures(); + await importer.syncFigures(); log.info("Figures imported"); }); diff --git a/handlers/tutorial/tasks/import.js b/handlers/tutorial/tasks/import.js index b5cbb1c..19d633b 100755 --- a/handlers/tutorial/tasks/import.js +++ b/handlers/tutorial/tasks/import.js @@ -41,8 +41,9 @@ module.exports = function(options) { await importer.sync(path.join(root, subRoot)); } - // yield* importer.generateCaches(); + // await importer.generateCaches(); + // console.log("SLUGMAP", tree.bySlugMap); log.info("DONE"); }(); diff --git a/handlers/tutorial/tasks/importWatch.js b/handlers/tutorial/tasks/importWatch.js index 82855de..3aa71d3 100755 --- a/handlers/tutorial/tasks/importWatch.js +++ b/handlers/tutorial/tasks/importWatch.js @@ -97,7 +97,7 @@ function watchTutorial(root) { folder = path.dirname(filePath); } - yield* importer.sync(folder); + await importer.sync(folder); }).catch(function(err) { log.error(err); @@ -121,7 +121,7 @@ function watchFigures(root) { co(function* () { - yield* importer.syncFigures(); + await importer.syncFigures(); }).catch(function(err) { throw err; diff --git a/handlers/tutorial/tasks/killContent.js b/handlers/tutorial/tasks/killContent.js index ae8d49a..d131315 100755 --- a/handlers/tutorial/tasks/killContent.js +++ b/handlers/tutorial/tasks/killContent.js @@ -12,11 +12,11 @@ module.exports = function() { return co(function*() { - yield* killArticles(); - yield* killTasks(); + await killArticles(); + await killTasks(); - yield* renderTasks(); - yield* renderArticles(); + await renderTasks(); + await renderArticles(); console.log("DONE"); }); }; @@ -25,14 +25,14 @@ module.exports = function() { function* killArticles() { - var articles = yield Article.find({}); + var articles = await Article.find({}); for (var i = 0; i < articles.length; i++) { var article = articles[i]; article.content = '# ' + article.title + '\n\n## Article ' + article.weight + '\n\nText'; - yield article.persist(); + await article.persist(); } @@ -40,16 +40,16 @@ function* killArticles() { function* renderArticles() { - var articles = yield Article.find({}); + var articles = await Article.find({}); for (var i = 0; i < articles.length; i++) { var article = articles[i]; var renderer = new ArticleRenderer(); - yield* renderer.renderWithCache(article, {refreshCache: true}); + await renderer.renderWithCache(article, {refreshCache: true}); - yield article.persist(); + await article.persist(); } @@ -58,16 +58,16 @@ function* renderArticles() { function* renderTasks() { - var tasks = yield Task.find({}); + var tasks = await Task.find({}); for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; var renderer = new TaskRenderer(); - yield* renderer.renderWithCache(task, {refreshCache: true}); + await renderer.renderWithCache(task, {refreshCache: true}); - yield task.persist(); + await task.persist(); } @@ -75,7 +75,7 @@ function* renderTasks() { function* killTasks() { - var tasks = yield Task.find({}); + var tasks = await Task.find({}); for (var i = 0; i < tasks.length; i++) { var task = tasks[i]; @@ -83,7 +83,7 @@ function* killTasks() { task.content = '# ' + task.title + '\n\nTask content ' + task.weight; task.solution = 'Task solution ' + task.weight; - yield task.persist(); + await task.persist(); } } \ No newline at end of file diff --git a/handlers/tutorial/templates/_map.jade b/handlers/tutorial/templates/_map.pug similarity index 91% rename from handlers/tutorial/templates/_map.jade rename to handlers/tutorial/templates/_map.pug index da26960..44580e8 100755 --- a/handlers/tutorial/templates/_map.jade +++ b/handlers/tutorial/templates/_map.pug @@ -1,4 +1,6 @@ -include /bem +include /bem/index + +- console.log(roots) +b.tutorial-map +e.filter @@ -13,7 +15,9 @@ include /bem = t('tutorial.map.show_tasks') +b.tutorial-map-list - each topic in roots + each slug in roots + - let topic = bySlug(slug) + - console.log(slug, topic) +e.item +e('h2').title= topic.title +b('ul').tutorial-map-list-two diff --git a/handlers/tutorial/templates/_task_content.jade b/handlers/tutorial/templates/_task_content.pug similarity index 100% rename from handlers/tutorial/templates/_task_content.jade rename to handlers/tutorial/templates/_task_content.pug diff --git a/handlers/tutorial/templates/article.jade b/handlers/tutorial/templates/article.pug similarity index 100% rename from handlers/tutorial/templates/article.jade rename to handlers/tutorial/templates/article.pug diff --git a/handlers/tutorial/templates/folder.jade b/handlers/tutorial/templates/folder.pug similarity index 100% rename from handlers/tutorial/templates/folder.jade rename to handlers/tutorial/templates/folder.pug diff --git a/handlers/tutorial/templates/frontpage.jade b/handlers/tutorial/templates/frontpage.pug similarity index 100% rename from handlers/tutorial/templates/frontpage.jade rename to handlers/tutorial/templates/frontpage.pug diff --git a/handlers/tutorial/templates/map.jade b/handlers/tutorial/templates/map.pug similarity index 100% rename from handlers/tutorial/templates/map.jade rename to handlers/tutorial/templates/map.pug diff --git a/handlers/tutorial/templates/sidebar.jade b/handlers/tutorial/templates/sidebar.pug similarity index 100% rename from handlers/tutorial/templates/sidebar.jade rename to handlers/tutorial/templates/sidebar.pug diff --git a/handlers/tutorial/templates/task.jade b/handlers/tutorial/templates/task.pug similarity index 100% rename from handlers/tutorial/templates/task.jade rename to handlers/tutorial/templates/task.pug diff --git a/handlers/tutorial/test/model/article.js b/handlers/tutorial/test/model/article.js index 3b978c1..354d494 100755 --- a/handlers/tutorial/test/model/article.js +++ b/handlers/tutorial/test/model/article.js @@ -11,7 +11,7 @@ var Article = require('../../models/article'); describe('Article', function() { before(function* () { - yield* dataUtil.loadModels(path.join(__dirname, '../fixture/article'), {reset: true}); + await dataUtil.loadModels(path.join(__dirname, '../fixture/article'), {reset: true}); }); @@ -27,17 +27,17 @@ describe('Article', function() { weight: 0 }); - yield article.persist(); + await article.persist(); assert(article.modified >= date); - yield article.destroy(); + await article.destroy(); }); describe('findTree', function() { it("returns nested structure { children: [ ... ] }", function* () { - var tree = yield Article.findTree(); + var tree = await Article.findTree(); tree.children.length.should.be.eql(2); tree.children[0].children.length.should.be.eql(2); tree.children[1].children.length.should.be.eql(2); diff --git a/handlers/tutorial/test/renderer/articleRenderer.js b/handlers/tutorial/test/renderer/articleRenderer.js index 8214e42..f3fbf7a 100755 --- a/handlers/tutorial/test/renderer/articleRenderer.js +++ b/handlers/tutorial/test/renderer/articleRenderer.js @@ -6,7 +6,7 @@ const Article = require('../../models/article'); describe("ArticleRenderer", function() { beforeEach(function* () { - yield Article.destroy(); + await Article.destroy(); }); it("appends -2, -3... to header with same title", function* () { @@ -19,7 +19,7 @@ describe("ArticleRenderer", function() { }); const renderer = new ArticleRenderer(); - const result = yield renderer.render(article); + const result = await renderer.render(article); result.content.replace(/\n/g, '').should.be.eql( '

Title

Title

' ); diff --git a/handlers/tutorial/test/renderer/taskRenderer.js b/handlers/tutorial/test/renderer/taskRenderer.js index 667fc83..020869c 100755 --- a/handlers/tutorial/test/renderer/taskRenderer.js +++ b/handlers/tutorial/test/renderer/taskRenderer.js @@ -8,7 +8,7 @@ const Task = require('../../models/task'); describe("TaskRenderer", function() { beforeEach(function* () { - yield Task.destroy(); + await Task.destroy(); }); it("renderContent", function* () { @@ -23,7 +23,7 @@ describe("TaskRenderer", function() { const renderer = new TaskRenderer(); - const result = yield renderer.renderContent(task, {}); + const result = await renderer.renderContent(task, {}); result.replace(/\n/g, '').should.be.eql('

Content

'); }); @@ -40,7 +40,7 @@ describe("TaskRenderer", function() { }); const renderer = new TaskRenderer(); - const result = yield renderer.renderSolution(task, {}); + const result = await renderer.renderSolution(task, {}); result.should.be.eql([{title: 'Part 1', content: '

Content 1

\n'}, {title: 'Part 2', content: '

Content 2

\n'}]); diff --git a/locales/site/en.yml b/locales/site/en.yml index c9d45f2..3bb6461 100755 --- a/locales/site/en.yml +++ b/locales/site/en.yml @@ -14,6 +14,7 @@ share: Share donate: Donate read_before_commenting: read before commenting… +tutorial: Tutorial tutorial_map: Tutorial map additional_articles: Additional articles comment: diff --git a/locales/site/ru.yml b/locales/site/ru.yml index 32de4df..2be104f 100755 --- a/locales/site/ru.yml +++ b/locales/site/ru.yml @@ -15,6 +15,7 @@ share: Поделиться donate: Поддержать read_before_commenting: перед тем как писать… +tutorial: Учебник tutorial_map: Карта учебника additional_articles: Дополнительно comment: diff --git a/modules/bemJade.js b/modules/-bemPug.js similarity index 96% rename from modules/bemJade.js rename to modules/-bemPug.js index 1e75401..31770d4 100755 --- a/modules/bemJade.js +++ b/modules/-bemPug.js @@ -1,8 +1,6 @@ // Adapted from bemto.jade, copyright(c) 2012 Roman Komarov -/* jshint -W106 */ - -var jade = require('jade/lib/runtime'); +var pug = require('pug-runtime'); module.exports = function(settings) { settings = settings || {}; @@ -116,7 +114,7 @@ module.exports = function(settings) { } } - buf.push('<' + newTag + jade.attrs(jade.merge([attributes]), true) + ">"); + buf.push('<' + newTag + pug.attrs(pug.merge([attributes]), true) + ">"); if (block) block(); diff --git a/modules/application.js b/modules/application.js index c1812f8..e579098 100755 --- a/modules/application.js +++ b/modules/application.js @@ -30,12 +30,12 @@ class Application extends KoaApplication { // mongoose buffers queries, // so for TEST/DEV there's no reason to wait // for PROD, there is a reason: to check if DB is ok before taking a request - *waitBoot() { + async waitBoot() { for (var path in this.handlers) { var handler = this.handlers[path]; if (!handler.boot) continue; - yield* handler.boot(); + await handler.boot(); } } @@ -47,28 +47,28 @@ class Application extends KoaApplication { // app.listen can also be called from tests directly (and synchronously), without waitBoot (many times w/ random port) // it's ok for tests, db requests are buffered, no need to waitBoot - *waitBootAndListen(host, port) { - yield* this.waitBoot(); + async waitBootAndListen(host, port) { + await this.waitBoot(); - yield (callback) => { - this.server = this.listen(port, host, callback); - }; + await new Promise((resolve) => { + this.server = this.listen(port, host, resolve); + }); this.log.info('Server is listening %s:%d', host, port); } - *close() { + async close() { this.log.info("Closing app server..."); - yield function(callback) { - this.server.close(callback); - }.bind(this); + await new Promise(resolve => { + this.server.close(resolve); + }); this.log.info("App connections are closed"); for (var path in this.handlers) { var handler = this.handlers[path]; if (!handler.close) continue; - yield* handler.close(); + await handler.close(); } this.log.info("App stopped"); @@ -92,7 +92,7 @@ class Application extends KoaApplication { this.use(function *(next) { log.trace("-> setup " + path); var d = new Date(); - yield* next; + await next; log.trace("<- setup " + path, new Date() - d); }); } diff --git a/modules/client/clientRender.js b/modules/client/clientRender.js index a881428..21df15e 100755 --- a/modules/client/clientRender.js +++ b/modules/client/clientRender.js @@ -1,4 +1,4 @@ -const bem = require('bemJade')(); +const bem = require('bemPug')(); const thumb = require('client/image').thumb; const LANG = require('config').lang; diff --git a/modules/client/notification/notification-popup.jade b/modules/client/notification/notification-popup.pug similarity index 87% rename from modules/client/notification/notification-popup.jade rename to modules/client/notification/notification-popup.pug index 50af53d..9aa10aa 100755 --- a/modules/client/notification/notification-popup.jade +++ b/modules/client/notification/notification-popup.pug @@ -1,4 +1,4 @@ -include /bem +include /bem/index +b(class="notification notification_popup notification_" + type) +e.content= html diff --git a/modules/config/handlers.js b/modules/config/handlers.js index 5d297d9..fef402e 100755 --- a/modules/config/handlers.js +++ b/modules/config/handlers.js @@ -39,6 +39,7 @@ var handlers = [ 'conditional', + process.env.NODE_ENV=='development' && 'dev', 'tutorial' ]; diff --git a/modules/config/index.js b/modules/config/index.js index 6e04432..5995b7b 100755 --- a/modules/config/index.js +++ b/modules/config/index.js @@ -1,9 +1,9 @@ // make sure Promise is wrapped early, // to assign mongoose.Promise = global.Promise the wrapped variant any time later -var path = require('path'); -var fs = require('fs'); -var env = process.env; -var yaml = require('js-yaml'); +let path = require('path'); +let fs = require('fs'); +let env = process.env; +let yaml = require('js-yaml'); // NODE_ENV = development || test || production env.NODE_ENV = env.NODE_ENV || 'development'; @@ -11,9 +11,9 @@ env.NODE_ENV = env.NODE_ENV || 'development'; //if (!env.SITE_HOST) throw new Error("env.SITE_HOST is not set"); //if (!env.STATIC_HOST) throw new Error("env.STATIC_HOST is not set"); -var secret = require('./secret'); +let secret = require('./secret'); -var lang = env.NODE_LANG || 'en'; +let lang = env.NODE_LANG || 'en'; require('util').inspect.defaultOptions.depth = 3; @@ -23,7 +23,7 @@ if (env.DEV_TRACE) { require('clarify'); } -var config = module.exports = { +let config = module.exports = { // production domain, for tutorial imports, descriptions, etc // for the places where in-dev we must use a real domain domain: { @@ -50,7 +50,7 @@ var config = module.exports = { assetVersioning: env.ASSET_VERSIONING == 'file' ? 'file' : env.ASSET_VERSIONING == 'query' ? 'query' : null, - jade: { + pug: { basedir: path.join(process.cwd(), 'templates'), cache: env.NODE_ENV != 'development' }, @@ -59,15 +59,12 @@ var config = module.exports = { // public files, served by nginx publicRoot: path.join(process.cwd(), 'public'), // private files, for expiring links, not directly accessible - downloadRoot: path.join(process.cwd(), 'download'), - archiveRoot: path.join(process.cwd(), 'archive'), + tutorialRoot: path.join(process.cwd(), '..', 'javascript-tutorial-' + lang), tmpRoot: path.join(process.cwd(), 'tmp'), localesRoot: path.join(process.cwd(), 'locales'), // js/css build versions - manifestRoot: path.join(process.cwd(), 'manifest'), - migrationsRoot: path.join(process.cwd(), 'migrations'), - tutorialGithubBaseUrl: 'https://github.com/iliakan/javascript-tutorial-' + lang + '/tree/master/' + - '', + cacheRoot: path.join(process.cwd(), 'cache'), + tutorialGithubBaseUrl: 'https://github.com/iliakan/javascript-tutorial-' + lang + '/tree/master', handlers: require('./handlers') }; diff --git a/modules/config/webpack.js b/modules/config/webpack.js index 429fda0..8030d48 100755 --- a/modules/config/webpack.js +++ b/modules/config/webpack.js @@ -83,8 +83,8 @@ module.exports = function(config) { use: ['json-loader', 'yaml-loader'] }, { - test: /\.jade$/, - use: 'jade-loader?root=' + config.projectRoot + '/templates' + test: /\.pug$/, + use: 'pug-loader?root=' + config.projectRoot + '/templates' }, { test: /\.js$/, @@ -204,7 +204,7 @@ module.exports = function(config) { name: 'head', filename: extHash('head', 'js') }), - new WriteVersionsPlugin(path.join(config.manifestRoot, 'pack.versions.json')), + new WriteVersionsPlugin(path.join(config.cacheRoot, 'webpack.versions.json')), new ExtractTextPlugin(extHash('[name]', 'css', '[contenthash]'), {allChunks: true}), diff --git a/modules/lib/lazyRouterMiddleware.js b/modules/lib/lazyRouterMiddleware.js index 34fb57b..23ea2ef 100755 --- a/modules/lib/lazyRouterMiddleware.js +++ b/modules/lib/lazyRouterMiddleware.js @@ -7,8 +7,8 @@ module.exports = function(routerModulePath) { var middleware = module.parent.require(routerModulePath).middleware(); - return function*(next) { - yield* middleware.call(this, next); + return async function(ctx, next) { + await middleware(ctx, next); }; }; diff --git a/modules/lib/mountHandlerMiddleware.js b/modules/lib/mountHandlerMiddleware.js index 3d903a7..eb7d0ee 100755 --- a/modules/lib/mountHandlerMiddleware.js +++ b/modules/lib/mountHandlerMiddleware.js @@ -1,5 +1,5 @@ -var path = require('path'); -var mount = require('koa-mount'); +let path = require('path'); +let mount = require('koa-mount'); // wrap('modulePath') @@ -10,33 +10,27 @@ var mount = require('koa-mount'); module.exports = function(prefix, moduleDir) { // actually includes router when the middleware is accessed (mount prefix matches) - var lazyRouterMiddleware = require('lib/lazyRouterMiddleware')(path.join(moduleDir, 'router')); + let lazyRouterMiddleware = require('lib/lazyRouterMiddleware')(path.join(moduleDir, 'router')); - function* wrapMiddleware(next) { - var self = this; - - var templateDir = path.join(moduleDir, 'templates'); + async function wrapMiddleware(ctx, next) { + let templateDir = path.join(moduleDir, 'templates'); // before entering middeware - function apply() { - self.templateDir = templateDir; - } + let apply = () => self.templateDir = templateDir; // before leaving middleware - function undo() { - delete self.templateDir; - } + let undo = () => delete self.templateDir; apply(); try { - yield* lazyRouterMiddleware.call(this, function* () { - // when middleware does yield next, undo changes + await lazyRouterMiddleware(ctx, async function() { + // when middleware does await next, undo changes undo(); try { - yield* next; + await next; } finally { - // ...then apply back, when control goes back after yield next + // ...then apply back, when control goes back after await next apply(); } }()); diff --git a/modules/lib/readline.js b/modules/lib/readline.js deleted file mode 100755 index 339b5d6..0000000 --- a/modules/lib/readline.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * DISCLAIMER: Had to implement custom input reading, - * - * because both node-read and node-prompt had bugs on Windows-8.1 - * E.g. every input letter was double-printed - * (and I really need starred * input for passwords) - * - */ -var readline = require('readline'); - - -/** - * @param options object { message: what to ask?, hidden: true for passwords } - * @param callback function Calls callback(null, result), no errors no matter what - */ -function readLine(options, callback) { - - var rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); - - setup(); - rl.question(options.message, function(result) { - tearDown(); - callback(null, result); - }); - - function onReadable() { - if (!options.hidden) return; - hideInput(); - } - - function hideInput() { - if (!rl.line) return; // happens on \n when the input is finished - process.stdout.write("\033[2K\033[200D" + options.message + new Array(rl.line.length+1).join("*")); - } - - - function setup() { - process.stdin.on("readable", onReadable); - } - - function tearDown() { - process.stdin.removeListener("readable", onReadable); - rl.close(); - } - -} - -module.exports = readLine; diff --git a/modules/lib/serverJade/filterMarkit.js b/modules/lib/serverPug/filterMarkit.js similarity index 82% rename from modules/lib/serverJade/filterMarkit.js rename to modules/lib/serverPug/filterMarkit.js index e0320ff..e2cce59 100755 --- a/modules/lib/serverJade/filterMarkit.js +++ b/modules/lib/serverPug/filterMarkit.js @@ -1,6 +1,6 @@ 'use strict'; -let filters = require('jade').filters; +let filters = require('pug').filters; let BasicParser = require('markit').BasicParser; diff --git a/modules/lib/serverJade/filterUglify.js b/modules/lib/serverPug/filterUglify.js similarity index 79% rename from modules/lib/serverJade/filterUglify.js rename to modules/lib/serverPug/filterUglify.js index fdc8393..a55ec53 100755 --- a/modules/lib/serverJade/filterUglify.js +++ b/modules/lib/serverPug/filterUglify.js @@ -1,4 +1,4 @@ -var filters = require('jade').filters; +var filters = require('pug').filters; var UglifyJS = require("uglify-js"); diff --git a/modules/lib/serverJade/index.js b/modules/lib/serverPug/index.js similarity index 72% rename from modules/lib/serverJade/index.js rename to modules/lib/serverPug/index.js index 3742834..e335a1f 100755 --- a/modules/lib/serverJade/index.js +++ b/modules/lib/serverPug/index.js @@ -1,17 +1,17 @@ const fs = require('fs'); const path = require('path'); const config = require('config'); -const jade = require('jade'); +const pug = require('pug'); /** * extension for require('file.jade'), * works in libs that are shared between client & server */ -require.extensions['.jade'] = function(module, filename) { +require.extensions['.pug'] = function(module, filename) { - var compiled = jade.compile( + var compiled = pug.compile( fs.readFileSync(filename, 'utf-8'), - Object.assign({}, config.jade, { + Object.assign({}, config.pug, { pretty: false, compileDebug: false, filename: filename @@ -20,7 +20,7 @@ require.extensions['.jade'] = function(module, filename) { module.exports = function(locals) { locals = locals || {}; - locals.bem = require('bemJade')(); + locals.bem = require('bemPug')(); return compiled(locals); }; @@ -33,4 +33,4 @@ require('./filterMarkit'); require('./filterUglify'); -module.exports = jade; +module.exports = pug; diff --git a/modules/lib/verboseLogger.js b/modules/lib/verboseLogger.js index 7ea4880..dbea3b7 100755 --- a/modules/lib/verboseLogger.js +++ b/modules/lib/verboseLogger.js @@ -1,22 +1,23 @@ const PathListCheck = require('pathListCheck'); -function VerboseLogger() { - this.logPaths = new PathListCheck(); -} - +module.exports = class VerboseLogger { + constructor() { + this.logPaths = new PathListCheck(); + } -VerboseLogger.prototype.middleware = function() { - var self = this; + middleware() { + var self = this; - return function*(next) { + return async function (ctx, next) { - if (self.logPaths.check(this.path)) { - this.log.info({requestVerbose: this.request}); - } + if (self.logPaths.check(ctxx.path)) { + ctx.log.info({requestVerbose: ctx.request}); + } - yield* next; - }; + await next; + }; + } }; /* @@ -33,4 +34,3 @@ VerboseLogger.prototype.log = function(context) { }; */ -module.exports = VerboseLogger; diff --git a/modules/localStorage.js b/modules/localStorage.js index e67ddfa..fecd2e3 100644 --- a/modules/localStorage.js +++ b/modules/localStorage.js @@ -1 +1,26 @@ -module.exports = new Map(); \ No newline at end of file +module.exports = class LocalStorage { + constructor() { + this.storage = Object.create(null); + } + + set(key, value) { + this.storage[key] = value; + } + + get(key) { + return this.storage[key]; + } + + has(key) { + return (key in this.storage); + } + + async getOrGenerate(key, func, skipCache) { + if (skipCache) return await func(); + + if (!this.has(key)) { + this.set(key, await func()); + } + return this.get(key); + } +}; \ No newline at end of file diff --git a/modules/markit/loadImgSizeAsync.js b/modules/markit/loadImgSizeAsync.js index 2b87015..15c9224 100755 --- a/modules/markit/loadImgSizeAsync.js +++ b/modules/markit/loadImgSizeAsync.js @@ -28,7 +28,7 @@ module.exports = function* (tokens, options) { if (token.type == 'figure') { - yield* processImageOrFigure(token); + await processImageOrFigure(token); continue; } @@ -39,7 +39,7 @@ module.exports = function* (tokens, options) { //
gives figure inside inline token if (inlineToken.type != 'image' && inlineToken.type != 'figure') continue; - yield* processImageOrFigure(inlineToken); + await processImageOrFigure(inlineToken); } } @@ -49,7 +49,7 @@ module.exports = function* (tokens, options) { if (token.attrIndex('height') != -1 || token.attrIndex('width') != -1) return; try { - yield* doProcessImageOrFigure(token); + await doProcessImageOrFigure(token); } catch (error) { if (error instanceof SrcError) { // replace image with error text @@ -86,7 +86,7 @@ module.exports = function* (tokens, options) { let stat; try { - stat = yield fs.stat(sourcePath); + stat = await fs.stat(sourcePath); } catch (e) { throw new SrcError(t('markit.error.image_not_found', {src})); } @@ -97,7 +97,7 @@ module.exports = function* (tokens, options) { if (/\.svg$/i.test(sourcePath)) { try { - let size = yield function(callback) { + let size = await function(callback) { // GraphicsMagick fails with `gm identify my.svg` gm(sourcePath).options({imageMagick: true}).identify('{"width":%w,"height":%h}', callback); }; @@ -112,7 +112,7 @@ module.exports = function* (tokens, options) { try { - return yield function(callback) { + return await function(callback) { imageSize(sourcePath, callback); }; @@ -129,7 +129,7 @@ module.exports = function* (tokens, options) { let src = tokenUtils.attrGet(token, 'src'); if (!src) return; - let imageInfo = yield* getImageInfo(src); + let imageInfo = await getImageInfo(src); tokenUtils.attrReplace(token, 'width', imageInfo.width); tokenUtils.attrReplace(token, 'height', imageInfo.height); diff --git a/modules/markit/loadSrcAsync.js b/modules/markit/loadSrcAsync.js index efe9d5d..e0dc03a 100755 --- a/modules/markit/loadSrcAsync.js +++ b/modules/markit/loadSrcAsync.js @@ -51,7 +51,7 @@ module.exports = function* (tokens, options) { let src = path.join(options.resourceWebRoot, token.blockTagAttrs.src); - let plunk = yield Plunk.findOne({webPath: src}); + let plunk = await Plunk.findOne({webPath: src}); if (!plunk) { throw new SrcError(t('markit.error.no_such_plunk', {src})); @@ -66,7 +66,7 @@ module.exports = function* (tokens, options) { let src = path.join(options.resourceWebRoot, href.slice('sandbox:'.length)); - let plunk = yield Plunk.findOne({webPath: src}); + let plunk = await Plunk.findOne({webPath: src}); if (!plunk) { throw new SrcError(t('markit.error.no_such_plunk', {src: href})); @@ -77,7 +77,7 @@ module.exports = function* (tokens, options) { function* blocktag_iframe(token) { if (token.blockTagAttrs.edit || token.blockTagAttrs.zip) { - yield* src2plunk(token); + await src2plunk(token); } } @@ -93,7 +93,7 @@ module.exports = function* (tokens, options) { let content; try { - content = yield fs.readFile(sourcePath, 'utf-8'); + content = await fs.readFile(sourcePath, 'utf-8'); } catch (e) { throw new SrcError( t('markit.error.read_file', {src: token.blockTagAttrs.src}) + @@ -111,7 +111,7 @@ module.exports = function* (tokens, options) { let process = methods[token.type]; if (process) { try { - yield* process(token); + await process(token); } catch (err) { if (err instanceof SrcError) { token.type = isInline ? 'markdown_error_inline' : 'markdown_error_block'; @@ -123,7 +123,7 @@ module.exports = function* (tokens, options) { } if (token.children) { - yield* walk(token.children, true); + await walk(token.children, true); } } @@ -131,7 +131,7 @@ module.exports = function* (tokens, options) { } - yield* walk(tokens); + await walk(tokens); }; diff --git a/modules/markit/locales/codeTabs/en.yml b/modules/markit/locales/codeTabs/en.yml new file mode 100755 index 0000000..103b49a --- /dev/null +++ b/modules/markit/locales/codeTabs/en.yml @@ -0,0 +1,4 @@ + +result: Result +open_in_window: open in a new window +edit_in_sandbox: edit in the sandbox diff --git a/modules/markit/locales/codeTabs/ru.yml b/modules/markit/locales/codeTabs/ru.yml new file mode 100755 index 0000000..f4070f9 --- /dev/null +++ b/modules/markit/locales/codeTabs/ru.yml @@ -0,0 +1,4 @@ + +result: Результат +open_in_window: открыть в отдельном окне +edit_in_sandbox: редактировать в песочнице diff --git a/modules/markit/plugins/blockTags/codetabs.js b/modules/markit/plugins/blockTags/codetabs.js index cd4c5da..e664981 100755 --- a/modules/markit/plugins/blockTags/codetabs.js +++ b/modules/markit/plugins/blockTags/codetabs.js @@ -6,10 +6,10 @@ assert(typeof IS_CLIENT === 'undefined'); const path = require('path'); const getPrismLanguage = require('../../getPrismLanguage'); -const jade = require('lib/serverJade'); -const bem = require('bemJade'); -const codeTabsTemplate = require('../../templates/codeTabs.jade'); +require('lib/serverPug'); + +const codeTabsTemplate = require('../../templates/codeTabs.pug'); module.exports = function(md) { diff --git a/modules/markit/serverParser.js b/modules/markit/serverParser.js index 44e1f5d..b61a781 100755 --- a/modules/markit/serverParser.js +++ b/modules/markit/serverParser.js @@ -82,8 +82,8 @@ module.exports = class ServerParser { *parse(text) { const tokens = this.md.parse(text, this.env); - yield* loadSrcAsync(tokens, this.md.options); - yield* loadImgSizeAsync(tokens, this.md.options); + await loadSrcAsync(tokens, this.md.options); + await loadImgSizeAsync(tokens, this.md.options); return tokens; } diff --git a/modules/markit/templates/codeTabs.jade b/modules/markit/templates/codeTabs.pug similarity index 67% rename from modules/markit/templates/codeTabs.jade rename to modules/markit/templates/codeTabs.pug index 5375c81..6c5226b 100755 --- a/modules/markit/templates/codeTabs.jade +++ b/modules/markit/templates/codeTabs.pug @@ -1,22 +1,22 @@ -include /bem +include /bem/index +b.code-tabs._result_on +e.tools +e.scroll-wrap - +e('button').scroll-button._left(title="←" data-code-tabs-left) + +e('button').scroll-button._left(title="←", data-code-tabs-left) +e.switches-wrap +e.switches(data-code-tabs-switches) +e.switches-items - +e.switch._current Результат + +e.switch._current= t('markit.codeTabs.result') each tab in tabs +e.switch #{tab.title} +e.scroll-wrap +e('button').scroll-button._right(title="→" data-code-tabs-right) +e.buttons if external - +e('a').button._external(target="_blank", title="открыть в отдельном окне", href=external.href) + +e('a').button._external(target="_blank", title=t('markit.codeTabs.open_in_window'), href=external.href) if edit - +e('a').button._edit(target="_blank", title="редактировать в песочнице", href=edit.href) + +e('a').button._edit(target="_blank", title=t("markit.codeTabs.edit_in_sandbox"), href=edit.href) if zip +e('a').button._download(target="_blank", href=zip.href) diff --git a/modules/markit/test/server.js b/modules/markit/test/server.js index f72a622..d8568f9 100755 --- a/modules/markit/test/server.js +++ b/modules/markit/test/server.js @@ -38,7 +38,7 @@ function* render(text) { env }); - const tokens = yield* parser.parse(text); + const tokens = await parser.parse(text); let result = parser.render(tokens); //console.log(env); @@ -50,13 +50,13 @@ function* render(text) { describe('MarkIt', function() { before(function* () { - yield* dataUtil.loadModels(path.join(__dirname, './fixture/tutorial'), {reset: true}); + await dataUtil.loadModels(path.join(__dirname, './fixture/tutorial'), {reset: true}); }); describe('code', function() { it(`[js src="1.js" height=300]`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.should.be.html(`
@@ -69,7 +69,7 @@ describe('MarkIt', function() { it('```\ncode\n```', function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.should.be.html(`
@@ -81,7 +81,7 @@ describe('MarkIt', function() { it('```js\na = 5\n```\n', function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.should.be.html(`
@@ -96,7 +96,7 @@ describe('MarkIt', function() { it(`[iframe src="/path"]`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.should.be.html(`
@@ -108,43 +108,43 @@ describe('MarkIt', function() { /* it(``, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.eql('

Task 1

'); }); it(``, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.eql('

Article 1.2

'); }); */ it(`notfigure ![desc|height=100 width=200](/url)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.eql('

notfigure desc

'); }); it(`notfigure ![desc](blank.png)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.eql('

notfigure desc

'); }); it(`notfigure ![desc](not-exists.png)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.match(/^

notfigure .*?<\/p>$/); }); it(`notfigure ![desc](error.png)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.match(/^

notfigure .*?<\/p>$/); }); it(`notfigure ![desc](1.js)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.match(/^

notfigure .*?<\/p>$/); }); it(`![figure|height=100 width=200](/url)`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.html(`

@@ -152,12 +152,12 @@ describe('MarkIt', function() { }); it(`## Header [#anchor]`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.html('

Header

'); }); it(`## My header`, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.html('

My header

'); }); @@ -166,7 +166,7 @@ describe('MarkIt', function() { - Простые вещи делаются просто. - Поддерживается всеми распространёнными браузерами и включён по умолчанию. \`\`\``, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.html(`
@@ -185,7 +185,7 @@ describe('MarkIt', function() { + one - two \`\`\``, function*() { - let result = yield* render(this.test.title); + let result = await render(this.test.title); result.trim().should.be.html(`
diff --git a/modules/mdeditor/client/render.js b/modules/mdeditor/client/render.js index 25ff7f0..d5fe43e 100755 --- a/modules/mdeditor/client/render.js +++ b/modules/mdeditor/client/render.js @@ -6,7 +6,7 @@ const LANG = require('config').lang; t.requirePhrase('mdeditor', require('../locales/' + LANG + '.yml')); -const template = require('../templates/editor.jade'); +const template = require('../templates/editor.pug'); const clientRender = require('client/clientRender'); module.exports = function(options) { diff --git a/package.json b/package.json index af439e6..42bc180 100755 --- a/package.json +++ b/package.json @@ -13,19 +13,19 @@ "precommit": "NODE_ENV=development node `which gulp` pre-commit", "//": "node-xmpp-client installs for linux only", "dependencies": { + "autoprefixer": "*", "babel-core": "^6", "babel-loader": "^7", "babel-plugin-transform-flow-strip-types": "*", "babel-plugin-transform-runtime": "*", "babel-preset-env": "*", "babelfish": "^1.1.2", + "bemto.pug": "github:kizu/bemto", "bunyan": "*", "css-loader": "*", "extract-text-webpack-plugin": "^3", "file-loader": "*", "fs-extra": "*", - "autoprefixer": "*", - "postcss-loader": "*", "gm": "*", "gulp": "^3", "gulp-livereload": "*", @@ -34,16 +34,14 @@ "gulp-nodemon": "*", "gulp-util": "*", "image-size": "*", - "jade": "*", - "jade-loader": "*", "js-yaml": "*", - "koa": "^1", - "koa-bodyparser": "^2", - "koa-conditional-get": "^1", - "koa-etag": "^2", - "koa-mount": "^1", - "koa-router": "^5", - "koa-static": "^2", + "koa": "^2", + "koa-bodyparser": "^4", + "koa-conditional-get": "^2", + "koa-etag": "^3", + "koa-mount": "^3", + "koa-router": "^7", + "koa-static": "^5", "lodash": "*", "markdown-it": "*", "markdown-it-container": "*", @@ -56,16 +54,20 @@ "node-uuid": "*", "node-zip": "*", "path-to-regexp": "*", + "postcss-loader": "*", "prismjs": "^1", + "pug": "^2.0.3", + "pug-loader": "^2.4.0", + "pug-runtime": "^2.0.4", "request": "*", "request-promise": "*", "run-sequence": "*", "rupture": "*", "style-loader": "^0", "stylus-loader": "^3", - "webpack": "^3", "uglify-js": "^3", - "uglifyjs-webpack-plugin": "^1" + "uglifyjs-webpack-plugin": "^1", + "webpack": "^3" }, "engineStrict": true, "repository": { diff --git a/tasks/cloudflareClean.js b/tasks/cloudflareClean.js index f9d4bba..7160efe 100755 --- a/tasks/cloudflareClean.js +++ b/tasks/cloudflareClean.js @@ -8,7 +8,7 @@ const log = require('log')(); function* cleanDomain(domain) { - var params = { + let params = { a: "fpurge_ts", tkn: config.cloudflare.apiKey, email: config.cloudflare.email, @@ -16,7 +16,7 @@ function* cleanDomain(domain) { v: 1 }; - return yield request.post({ + return await request.post({ url: config.cloudflare.url, form: params, json: true @@ -26,18 +26,18 @@ function* cleanDomain(domain) { module.exports = function(options) { - var domains = options.domains; + let domains = options.domains; return function() { return co(function*() { - for (var i = 0; i < domains.length; i++) { - var domain = domains[i]; + for (let i = 0; i < domains.length; i++) { + let domain = domains[i]; log.info("Cloudfare clean", domain); - var result = yield cleanDomain(domain); + let result = await cleanDomain(domain); if (result.body.result != 'success') { log.error(result.body); //log.error(result.request); diff --git a/tasks/compileCss.js b/tasks/compileCss.js deleted file mode 100755 index e58464b..0000000 --- a/tasks/compileCss.js +++ /dev/null @@ -1,77 +0,0 @@ -const gulp = require('gulp'); - -const gp = require('gulp-load-plugins')(); - -const sourcemaps = require('gulp-sourcemaps'); -const fs = require('fs'); -const crypto = require('crypto'); -const es = require('event-stream'); -const path = require('path'); -const del = require('del'); - -module.exports = function(options) { - - function getAssetVersion(file) { - if (process.env.NODE_ENV == 'development') { - return fs.statSync(file).mtime.getTime().toString().replace(/0+$/, '').slice(-8); - } else { - var buf = fs.readFileSync(file); - return crypto.createHash('md5').update(buf).digest('hex').substring(0, 8); - } - } - - return function() { - - var nib = require('nib')(); - var asset = require('lib/stylusAsset')({ - getVersion: getAssetVersion, - assetVersioning : options.assetVersioning - }); - - del.sync(options.dst + '/*'); - - var versions = {}; - return gulp.src(options.src) - // without plumber if stylus emits PluginError, it will disappear at the next step - // plumber propagates it down the chain - .pipe(gp.plumber({errorHandler: gp.notify.onError("<%= error.message %>")})) - .pipe(sourcemaps.init()) - .pipe(gp.stylus({ - use: [nib, asset], - linenos: true, - sourcemap: { - inline: true - } - })) - .pipe(gp.autoprefixer("last 1 version")) - - .pipe(sourcemaps.write()) - // dies on node 0.11.15 with full npm reinstall - //.pipe(gp.if(process.env.NODE_ENV == 'production', gp.minifyCss())) - .pipe(es.map(function(file, cb) { - var version = crypto.createHash('md5').update(file.contents).digest('hex').substring(0, 8); - var name = path.basename(file.path).slice(0, -4); - - if (options.assetVersioning == 'file') { - file.path = file.path.replace(/\.css$/, '.' + version + '.css'); - versions[name] = options.publicDst + path.basename(file.path); - } else if (options.assetVersioning == 'query') { - versions[name] = options.publicDst + path.basename(file.path) + '?' + version; - } else { - versions[name] = options.publicDst + path.basename(file.path); - } - - //console.log(versions); - cb(null, file); - })) - .pipe(gulp.dest(options.dst)) - .on('end', function() { - //console.log(options.manifest, versions); - fs.writeFileSync(options.manifest, JSON.stringify(versions)); - }); - - }; - - -}; - diff --git a/tasks/livereload.js b/tasks/livereload.js index b07c60d..cb0b59f 100755 --- a/tasks/livereload.js +++ b/tasks/livereload.js @@ -1,8 +1,8 @@ -var livereload = require('gulp-livereload'); -var gulp = require('gulp'); -var gutil = require('gulp-util'); -var throttle = require('lodash/throttle'); -var chokidar = require('chokidar'); +let livereload = require('gulp-livereload'); +let gulp = require('gulp'); +let gutil = require('gulp-util'); +let throttle = require('lodash/throttle'); +let chokidar = require('chokidar'); // options.watch must NOT be www/**, because that breaks (why?!?) supervisor reloading // www/**/*.* is fine diff --git a/tasks/resizeRetinaImages.js b/tasks/resizeRetinaImages.js index 92be5ce..17a4eb1 100755 --- a/tasks/resizeRetinaImages.js +++ b/tasks/resizeRetinaImages.js @@ -29,7 +29,7 @@ module.exports = function(options) { .pipe(gp.debug()) .pipe(es.map(function(file, cb) { - var normalResolutionPath = file.path.replace(/@2x(?=\.[^.]+$)/, ''); + let normalResolutionPath = file.path.replace(/@2x(?=\.[^.]+$)/, ''); gutil.log(file.path + ' -> ' + normalResolutionPath); gm(file.path).resize("50%").write(normalResolutionPath, cb); })); diff --git a/tasks/server.js b/tasks/server.js index 381bf77..22765bf 100755 --- a/tasks/server.js +++ b/tasks/server.js @@ -1,6 +1,6 @@ -var co = require('co'); -var app = require('app'); -var config = require('config'); +let co = require('co'); +let app = require('app'); +let config = require('config'); module.exports = function() { return function(callback) { diff --git a/tasks/spawnWebpack.js b/tasks/spawnWebpack.js index 285dd51..f9ebc95 100755 --- a/tasks/spawnWebpack.js +++ b/tasks/spawnWebpack.js @@ -1,5 +1,5 @@ // spawn webpack in a separate process to improve overall build speed -var spawn = require('child_process').spawn; +let spawn = require('child_process').spawn; module.exports = function() { diff --git a/tasks/syncResources.js b/tasks/syncResources.js index 1086b53..9292a62 100755 --- a/tasks/syncResources.js +++ b/tasks/syncResources.js @@ -7,22 +7,22 @@ module.exports = function(resources) { return function(callback) { - for (var src in resources) { - var dst = resources[src]; + for (let src in resources) { + let dst = resources[src]; - var files = glob.sync(src + '/**'); - for (var i = 0; i < files.length; i++) { - var srcPath = files[i]; + let files = glob.sync(src + '/**'); + for (let i = 0; i < files.length; i++) { + let srcPath = files[i]; - var dstPath = srcPath.replace(src, dst); - var srcStat = fs.statSync(srcPath); + let dstPath = srcPath.replace(src, dst); + let srcStat = fs.statSync(srcPath); if (srcStat.isDirectory()) { fse.ensureDirSync(dstPath); continue; } - var dstMtime = 0; + let dstMtime = 0; try { dstMtime = fs.statSync(dstPath).mtime; } catch(e) {} diff --git a/tasks/watch.js b/tasks/watch.js index 485f609..799d0a9 100755 --- a/tasks/watch.js +++ b/tasks/watch.js @@ -2,23 +2,23 @@ * Autorun tasks *sequentially* on watch events */ -var gulp = require('gulp'); -var minimatch = require("minimatch"); -var chokidar = require('chokidar'); -var fs = require('fs'); -var runSequence = require('run-sequence'); -var glob = require('glob'); -var path = require('path'); +let gulp = require('gulp'); +let minimatch = require("minimatch"); +let chokidar = require('chokidar'); +let fs = require('fs'); +let runSequence = require('run-sequence'); +let glob = require('glob'); +let path = require('path'); -var taskQueue = []; -var taskRunning = ''; +let taskQueue = []; +let taskRunning = ''; -var DEBUG = false; +let DEBUG = false; function log() { if (!DEBUG) return; - var args = [].slice.call(arguments); + let args = [].slice.call(arguments); args.unshift(Date.now() % 1e6); console.log.apply(console, args); @@ -54,18 +54,18 @@ function runNext() { function onModify(filePath) { if (~filePath.indexOf('___jb_')) return; // ignore JetBrains Webstorm tmp files - var relFilePath = filePath.slice(this.root.length + 1); + let relFilePath = filePath.slice(this.root.length + 1); if (DEBUG) console.log("->", relFilePath); function watch(mapping) { // mapping.watch mapping.ignore mapping.task - var patternsWatch = Array.isArray(mapping.watch) ? mapping.watch : [mapping.watch]; - var patternsIgnore = !mapping.ignore ? [] : + let patternsWatch = Array.isArray(mapping.watch) ? mapping.watch : [mapping.watch]; + let patternsIgnore = !mapping.ignore ? [] : Array.isArray(mapping.ignore) ? mapping.ignore : [mapping.ignore]; // matches any watch => found=true - var found = false, i, pattern; + let found = false, i, pattern; for (i = 0; i < patternsWatch.length; i++) { pattern = patternsWatch[i]; if (minimatch(relFilePath, pattern)) { @@ -99,11 +99,11 @@ function onModify(filePath) { module.exports = function(options) { return function(callback) { - var dirs = options.dirs.map(function(dir) { + let dirs = options.dirs.map(function(dir) { return path.join(options.root, dir); }); - var watcher = chokidar.watch(dirs, {ignoreInitial: true}); + let watcher = chokidar.watch(dirs, {ignoreInitial: true}); watcher.root = options.root; watcher.taskMapping = options.taskMapping; diff --git a/tasks/webpack.js b/tasks/webpack.js index bfee922..59439d8 100755 --- a/tasks/webpack.js +++ b/tasks/webpack.js @@ -1,18 +1,18 @@ -var webpack = require('webpack'); -var gp = require('gulp-load-plugins')(); -var notifier = require('node-notifier'); +let webpack = require('webpack'); +let gp = require('gulp-load-plugins')(); +let notifier = require('node-notifier'); module.exports = function() { return function(callback) { - var config = require('config').webpack; + let config = require('config').webpack; webpack(config, function(err, stats) { if (!err) { // errors in files do not stop webpack watch // instead, they are gathered, so I get the first one here (if no other) - var jsonStats = stats.toJson(); + let jsonStats = stats.toJson(); err = jsonStats.errors[0]; } diff --git a/templates/bem.jade b/templates/-bem.pug old mode 100755 new mode 100644 similarity index 100% rename from templates/bem.jade rename to templates/-bem.pug diff --git a/templates/bem b/templates/bem new file mode 120000 index 0000000..d8f451d --- /dev/null +++ b/templates/bem @@ -0,0 +1 @@ +../node_modules/bemto.pug/lib \ No newline at end of file diff --git a/templates/blocks/article-tablet-foot.jade b/templates/blocks/article-tablet-foot.pug similarity index 100% rename from templates/blocks/article-tablet-foot.jade rename to templates/blocks/article-tablet-foot.pug diff --git a/templates/blocks/banner-bottom.jade b/templates/blocks/banner-bottom.pug similarity index 100% rename from templates/blocks/banner-bottom.jade rename to templates/blocks/banner-bottom.pug diff --git a/templates/blocks/breadcrumbs.jade b/templates/blocks/breadcrumbs.pug similarity index 100% rename from templates/blocks/breadcrumbs.jade rename to templates/blocks/breadcrumbs.pug diff --git a/templates/blocks/button/index.jade b/templates/blocks/button/index.pug similarity index 100% rename from templates/blocks/button/index.jade rename to templates/blocks/button/index.pug diff --git a/templates/blocks/buy-book.jade b/templates/blocks/buy-book.pug similarity index 100% rename from templates/blocks/buy-book.jade rename to templates/blocks/buy-book.pug diff --git a/templates/blocks/columns/index.jade b/templates/blocks/columns/index.pug similarity index 100% rename from templates/blocks/columns/index.jade rename to templates/blocks/columns/index.pug diff --git a/templates/blocks/comments.jade b/templates/blocks/comments.pug similarity index 100% rename from templates/blocks/comments.jade rename to templates/blocks/comments.pug diff --git a/templates/blocks/ga.jade b/templates/blocks/ga.pug similarity index 100% rename from templates/blocks/ga.jade rename to templates/blocks/ga.pug diff --git a/templates/blocks/guest.jade b/templates/blocks/guest.pug similarity index 100% rename from templates/blocks/guest.jade rename to templates/blocks/guest.pug diff --git a/templates/blocks/head.jade b/templates/blocks/head.pug similarity index 100% rename from templates/blocks/head.jade rename to templates/blocks/head.pug diff --git a/templates/blocks/input-select/index.jade b/templates/blocks/input-select/index.pug similarity index 100% rename from templates/blocks/input-select/index.jade rename to templates/blocks/input-select/index.pug diff --git a/templates/blocks/label/index.jade b/templates/blocks/label/index.pug similarity index 100% rename from templates/blocks/label/index.jade rename to templates/blocks/label/index.pug diff --git a/templates/blocks/map-with-title.jade b/templates/blocks/map-with-title.pug similarity index 100% rename from templates/blocks/map-with-title.jade rename to templates/blocks/map-with-title.pug diff --git a/templates/blocks/map.jade b/templates/blocks/map.pug similarity index 100% rename from templates/blocks/map.jade rename to templates/blocks/map.pug diff --git a/templates/blocks/mdeditor.jade b/templates/blocks/mdeditor.pug similarity index 98% rename from templates/blocks/mdeditor.jade rename to templates/blocks/mdeditor.pug index 736be59..1886991 100755 --- a/templates/blocks/mdeditor.jade +++ b/templates/blocks/mdeditor.pug @@ -1,4 +1,4 @@ -include /bem +include /bem/index mixin mdeditor(data) diff --git a/templates/blocks/page-footer.jade b/templates/blocks/page-footer.pug similarity index 100% rename from templates/blocks/page-footer.jade rename to templates/blocks/page-footer.pug diff --git a/templates/blocks/pie/index.jade b/templates/blocks/pie/index.pug similarity index 100% rename from templates/blocks/pie/index.jade rename to templates/blocks/pie/index.pug diff --git a/templates/blocks/section/index.jade b/templates/blocks/section/index.pug similarity index 100% rename from templates/blocks/section/index.jade rename to templates/blocks/section/index.pug diff --git a/templates/blocks/sidebar.jade b/templates/blocks/sidebar.pug similarity index 100% rename from templates/blocks/sidebar.jade rename to templates/blocks/sidebar.pug diff --git a/templates/blocks/sitetoolbar-light.jade b/templates/blocks/sitetoolbar-light.pug similarity index 100% rename from templates/blocks/sitetoolbar-light.jade rename to templates/blocks/sitetoolbar-light.pug diff --git a/templates/blocks/sitetoolbar.jade b/templates/blocks/sitetoolbar.pug similarity index 100% rename from templates/blocks/sitetoolbar.jade rename to templates/blocks/sitetoolbar.pug diff --git a/templates/blocks/social-icons.jade b/templates/blocks/social-icons.pug similarity index 100% rename from templates/blocks/social-icons.jade rename to templates/blocks/social-icons.pug diff --git a/templates/blocks/text-input/index.jade b/templates/blocks/text-input/index.pug similarity index 100% rename from templates/blocks/text-input/index.jade rename to templates/blocks/text-input/index.pug diff --git a/templates/blocks/textarea-input/index.jade b/templates/blocks/textarea-input/index.pug similarity index 100% rename from templates/blocks/textarea-input/index.jade rename to templates/blocks/textarea-input/index.pug diff --git a/templates/blocks/tutorial/bottom-navigation.jade b/templates/blocks/tutorial/bottom-navigation.pug similarity index 100% rename from templates/blocks/tutorial/bottom-navigation.jade rename to templates/blocks/tutorial/bottom-navigation.pug diff --git a/templates/blocks/tutorial/top-navigation.jade b/templates/blocks/tutorial/top-navigation.pug similarity index 100% rename from templates/blocks/tutorial/top-navigation.jade rename to templates/blocks/tutorial/top-navigation.pug diff --git a/templates/blocks/user.jade b/templates/blocks/user.pug similarity index 100% rename from templates/blocks/user.jade rename to templates/blocks/user.pug diff --git a/templates/layouts/base.jade b/templates/layouts/base.pug similarity index 78% rename from templates/layouts/base.jade rename to templates/layouts/base.pug index ab02c0a..854a6f1 100755 --- a/templates/layouts/base.jade +++ b/templates/layouts/base.pug @@ -1,6 +1,6 @@ //- bare layout with bem doctype html -include ../bem +include /bem/index html(lang=lang) block html diff --git a/templates/layouts/body.jade b/templates/layouts/body.pug similarity index 100% rename from templates/layouts/body.jade rename to templates/layouts/body.pug diff --git a/templates/layouts/html.jade b/templates/layouts/html.pug similarity index 100% rename from templates/layouts/html.jade rename to templates/layouts/html.pug diff --git a/templates/layouts/main.jade b/templates/layouts/main.pug similarity index 100% rename from templates/layouts/main.jade rename to templates/layouts/main.pug diff --git a/templates/notification.jade b/templates/notification.pug similarity index 100% rename from templates/notification.jade rename to templates/notification.pug