#! ./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>