#! ./public #! ./app/ #! ./blocks/ #! ./application/ // корневой блок #! application.html #! application.scss #! application.js #! application.spec.js #! ./vendors/ #! ./feast/ #! ./pilotjs/ #! boot.js // файл запуска проект #! sitemap.js // карта сайта #! index.html // точка входа #! index.js // простенький сервер
"use strict"; #! const feast = require("feast"); #!+ const app = feast.createSimpleApp({ #! name: "Ответы@Mail.Ru" #!- }); #! // Всё, вот и весь сервер ;]
Тут ничего интересного
#! import Pilot from "pilotjs"; #! import sitemap from "./sitemap"; #! import UIApplication from "./blocks/application/application"; #! const router = Pilot.create(sitemap); #!+ export default function (el, data) { #!+ const getViewAttrs = () => ({ #! name: data.name, #! router: router, #! route: router.route, #! request: router.request #!- }); #! const view = new UIApplication(getViewAttrs()); #! router.view = view; #! router.on("route", () => view.set(getViewAttrs())); #! view.renderTo(el); #! // ...History API... #! return router.nav(location.toString().split("#!").pop()).then(() => router); #!- };
export default { "#index": { url: "/" } }
#! import feast from "feast"; #! const api = (path, opts) => feast.resource(`/api/v2/${path}`, opts); #!+ export default { #!+ leaders: { #! users: api("usrrating", {body: "rating"}), #! questions: api("leadqst", {body: "qst"}) #!- }, #! question: api("question", {id: "qid"}), #! questions: api("questlist", {body: "qst"}) #!- };
#! import api from "./api"; #! import {mock as user} from "./blocks/user-card/user-card.spec"; #! import {default as categories, index as categoriesIndex} from "./categories"; #!+ export default { #! model: {/* модели доступные всем маршрутам */}, #!+ "#index": { #! url: {/* описание маски */}, #! model: {/* доп. модели */} #!- }, #!+ "#ask": { ... } "#top": { ... } #!- "#question": { ... } #!- };
export default { model: { #! categories: () => categories, #! currentUser: () => currentUser, #!+ leaders: { #! match: ["#index", "#question"], // список машрутов #! fetch: () => #!+ Promise.all([ #! api.leaders.users.find({n: 8}), #! api.leaders.questions.find({n: 5}) #!- ]) #!+ .then(results => ({ users: results[0], questions: results[1] #!- })) #!- } } }
"#index": { url: { #! pattern: "/:category?", #!+ params: { #!+ category: { #! validate: (value) => !!categoriesIndex[value] #!- } #!- } }, model: { #! questions: (req) => #! api.questions.find({n: 20, cat: req.params.category}), #! category: (req) => #! ({root: categoriesIndex[req.params.category]}) } }
"#ask": { url: "/ask" }, "#top": { url: "/top", model: { top: () => api.leaders.users.find({n: 20}) } }
url: "/question/:id", model: { #! question: (req) => #! api.question.findOne(req.params.id), #! category: (req, waitFor) => #! waitFor("question").then(q => #!+ ({ active: q.cid, root: categoriesIndex[categoriesIndex[q.cid].parent] #!- })) }
router.getUrl("#index", {category: "auto"}); // → "/auto" router.getUrl("#index", {category: 305}); // → "/auto" router.nav(router.getUrl("#index", {category: "auto"})); router.go("#index", {category: 305});
"#index": { url: { pattern: "/:category?", params: { category: { validate: (value) => !!categoriesIndex[value], #! encode: (value) => categoriesIndex[value].urlmame } } } }
url: { pattern: "path/:toName", params: { toName: { validate: (value) => ..., decode: (value) => ..., encode: (value) => ..., } }, query: { // аналогично } }
<div> #! <b:headline key="hl" .../> #! <b:portal-menu key="pm" .../> #!+ <b:layout key="grid"> #!+ <fn:match name="left" args="layoutAttrs"> ... #!- </fn:match> #!+ <fn:match name="center" args="layoutAttrs"> ... #!- </fn:match> #!- </b:layout> </div>
<fn:match name="left" args="layoutAttrs"> #!+ <fn:if test="**attrs.route.model**.category.root"> <b:categories-nav key="nav" active="{attrs.route.model.category.active}" model="{attrs.route.model.category.root}" /> #!- </fn:if> #!+ <fn:if test="attrs.route.model.leaders.questions"> <b:leaders key="q" type="question" models="{attrs.route.model.leaders.questions}" /> #!-</fn:if> #!+ <fn:if test="attrs.route.model.leaders.users"> <b:leaders key="cat" type="category" models="{attrs.route.model.leaders.users}" /> #!-</fn:if> #!+ <fn:if test="**attrs.route.is('#ask')**"> <b:user-card key="cu" model="{attrs.route.model.currentUser}" /> #!- </fn:if> </fn:match>
<fn:match name="center" args="layoutAttrs"> <div class="page"> <fn:choose> #!+ <fn:when test="attrs.route.is('#index')"> #! <b:form key="fa" mode="fast-ask"/> #! <h1 class="page-index--h1 bordered">Вопросы участников</h1> #! <b:questions key="qlist" items="{attrs.route.model.questions}"/> #!- </fn:when> #!+ <fn:when test="attrs.route.is('#ask')"> <b:form key="ask" mode="ask" type="question"/> #!- </fn:when> #!+ <fn:when test="attrs.route.is('#question')"> <b:question key="q" model="{attrs.route.model.question}"/> #!- </fn:when> #!+ <fn:when test="attrs.route.is('#top')"> <b:leaders key="top" type="project" models="{attrs.route.model.top}"/> #!- </fn:when> </fn:choose> </div> </fn:match>
<!-- Bad --> <div class="item {attrs.selected ? 'selected' : ''}"> <span>text</span> </div> #!+ <!-- Good --> <div class="item"> <fn:add-class **name="selected"** **test="attrs.selected"**/> <span>text</span> #!- </div>