'.format(i, line));
1220 | }
1221 | continue;
1222 | }
1223 |
1224 | if (!isblock && lines[i] && isprevblock) {
1225 | builder.push('
');
1226 | isprevblock = false;
1227 | }
1228 |
1229 | if (three === '```') {
1230 |
1231 | if (iscode) {
1232 | if (opt.code !== false)
1233 | builder[builder.length - 1] += '
';
1234 | iscode = false;
1235 | continue;
1236 | }
1237 |
1238 | closeul();
1239 | iscode = true;
1240 | if (opt.code !== false)
1241 | tmp = '
'.format(lines[i].substring(3));
1242 | continue;
1243 | }
1244 |
1245 | if (iscode) {
1246 | if (opt.code !== false)
1247 | builder.push(tmp + lines[i]);
1248 | if (tmp)
1249 | tmp = '';
1250 | continue;
1251 | }
1252 |
1253 | var line = lines[i];
1254 |
1255 | if (opt.br !== false)
1256 | line = line.replace(/<br(\s\/)?>/g, '
');
1257 |
1258 | if (line.length > 10 && opt.urlify !== false && opt.links !== false)
1259 | line = markdown_urlify(line);
1260 |
1261 | if (opt.custom)
1262 | line = opt.custom(line);
1263 |
1264 | if (line.length > 2 && line !== '***' && line !== '---') {
1265 | if (opt.formatting !== false)
1266 | line = formatline(line);
1267 | if (opt.images !== false)
1268 | line = imagescope(line);
1269 | if (opt.links !== false) {
1270 | linkscope(line, 0, function(text, inline) {
1271 | if (inline)
1272 | line = line.replace(text, markdown_links2);
1273 | else if (opt.images !== false)
1274 | line = line.replace(text, markdown_imagelinks);
1275 | else
1276 | line = line.replace(text, formatlinks);
1277 | });
1278 | }
1279 | if (opt.keywords !== false)
1280 | line = line.replace(keywords, markdown_keywords);
1281 |
1282 | if (opt.icons !== false)
1283 | line = line.replace(regicons, markdown_icon);
1284 | }
1285 |
1286 | if (!line) {
1287 | if (table) {
1288 | table = null;
1289 | if (opt.tables !== false)
1290 | builder.push('');
1291 | }
1292 | }
1293 |
1294 | if (line === '' && lines[i - 1] === '') {
1295 | closeul();
1296 | if (opt.emptynewline !== false)
1297 | builder.push('
');
1298 | continue;
1299 | }
1300 |
1301 | if (line[0] === '|') {
1302 | closeul();
1303 |
1304 | if (!table) {
1305 | var next = lines[i + 1];
1306 | if (next[0] === '|') {
1307 | if (next.indexOf('--') === -1) {
1308 | if (opt.tables !== false)
1309 | builder.push('');
1310 | table = [];
1311 | ishead = 2;
1312 | } else {
1313 | table = [];
1314 | var columns = next.substring(1, next.length - 1).split('|');
1315 | for (var j = 0; j < columns.length; j++) {
1316 | var column = columns[j].trim();
1317 | var align = 'left';
1318 | if (column.charAt(column.length - 1) === ':')
1319 | align = column[0] === ':' ? 'center' : 'right';
1320 | table.push(align);
1321 | }
1322 | if (opt.tables !== false)
1323 | builder.push('');
1324 | ishead = 1;
1325 | i++;
1326 | }
1327 | } else
1328 | continue;
1329 | }
1330 |
1331 | if (opt.tables !== false) {
1332 | if (ishead === 1)
1333 | builder.push(markdown_table(line, table, true) + '');
1334 | else if (ishead === 2)
1335 | builder.push('' + markdown_table(line, table));
1336 | else
1337 | builder.push(markdown_table(line, table));
1338 | }
1339 |
1340 | ishead = 0;
1341 | continue;
1342 | }
1343 |
1344 | if (line.charAt(0) === '#') {
1345 |
1346 | closeul();
1347 |
1348 | if (line.substring(0, 2) === '# ') {
1349 | tmp = line.substring(2).trim();
1350 | if (opt.headlines !== false) {
1351 | if (opt.html)
1352 | tmp = opt.html(tmp, '#');
1353 | builder.push(headline.format('h1', i, tmp, markdown_id(tmp)));
1354 | }
1355 | continue;
1356 | }
1357 |
1358 | if (line.substring(0, 3) === '## ') {
1359 | tmp = line.substring(3).trim();
1360 | if (opt.headlines !== false) {
1361 | if (opt.html)
1362 | tmp = opt.html(tmp, '##');
1363 | builder.push(headline.format('h2', i, tmp, markdown_id(tmp)));
1364 | }
1365 | continue;
1366 | }
1367 |
1368 | if (line.substring(0, 4) === '### ') {
1369 | tmp = line.substring(4).trim();
1370 | if (opt.headlines !== false) {
1371 | if (opt.html)
1372 | tmp = opt.html(tmp, '###');
1373 | builder.push(headline.format('h3', i, tmp, markdown_id(tmp)));
1374 | }
1375 | continue;
1376 | }
1377 |
1378 | if (line.substring(0, 5) === '#### ') {
1379 | tmp = line.substring(5).trim();
1380 | if (opt.headlines !== false) {
1381 | if (opt.html)
1382 | tmp = opt.html(tmp, '####');
1383 | builder.push(headline.format('h4', i, tmp, markdown_id(tmp)));
1384 | }
1385 | continue;
1386 | }
1387 |
1388 | if (line.substring(0, 6) === '##### ') {
1389 | tmp = line.substring(6).trim();
1390 | if (opt.headlines !== false) {
1391 | if (opt.html)
1392 | tmp = opt.html(tmp, '#####');
1393 | builder.push(headline.format('h5', i, tmp, markdown_id(tmp)));
1394 | }
1395 | continue;
1396 | }
1397 | }
1398 |
1399 | tmp = line.substring(0, 3);
1400 |
1401 | if (tmp === '---' || tmp === '***') {
1402 | if (opt.hr !== false)
1403 | builder.push('
');
1404 | continue;
1405 | }
1406 |
1407 | // footnotes
1408 | if ((/^#\d+:(\s)+/).test(line)) {
1409 | if (opt.footnotes !== false) {
1410 | tmp = line.indexOf(':');
1411 | builder.push('{0}: {1}
'.format(line.substring(1, tmp).trim(), line.substring(tmp + 1).trim()));
1412 | }
1413 | continue;
1414 | }
1415 |
1416 | if (line.substring(0, 5) === '> ') {
1417 | if (opt.blockquotes !== false) {
1418 | line = line.substring(5).trim();
1419 | if (opt.html)
1420 | line = opt.html(line, 'blockquote');
1421 | builder.push('' + line + '
');
1422 | }
1423 | continue;
1424 | }
1425 |
1426 | if (line.substring(0, 5) === '< ') {
1427 | if (opt.sections !== false) {
1428 | line = line.substring(5).trim();
1429 | if (opt.html)
1430 | line = opt.html(line, 'section');
1431 | builder.push('');
1432 | }
1433 | continue;
1434 | }
1435 |
1436 | var tmpline = line.trim();
1437 |
1438 | if (opt.ul !== false && ordered.test(tmpline)) {
1439 |
1440 | var size = line.match(orderedsize);
1441 | if (size)
1442 | size = size[0].length;
1443 | else
1444 | size = 0;
1445 |
1446 | var ultype = tmpline.charAt(0) === '-' ? 'ul' : 'ol';
1447 | var tmpstr = (ultype === 'ol' ? tmpline.substring(tmpline.indexOf('.') + 1) : tmpline.substring(2));
1448 | var istask = false;
1449 |
1450 | var tt = tmpstr.trim().substring(0, 3);
1451 | istask = tt === '[ ]' || tt === '[x]';
1452 |
1453 | var tmpval = tmpstr.trim();
1454 |
1455 | if (opt.html)
1456 | tmpval = opt.html(tmpval, 'li');
1457 |
1458 | builder.push('\0' + (ultype === 'ol' ? ('o' + ((/\d+\./).test(tmpline) ? '1' : 'a')) : 'ul') + size + ''.format(i, istask ? ' markdown-task' : '') + tmpval.replace(/\[x\]/g, '').replace(/\[\s\]/g, '') + '');
1459 |
1460 | } else {
1461 | closeul();
1462 | if (line) {
1463 | line = line.trim();
1464 | if (opt.html)
1465 | line = opt.html(line, opt.linetag);
1466 | }
1467 | line && builder.push((opt.linetag ? ('<' + opt.linetag + ' class="markdown-line" data-line="' + i + '">') : '') + line.trim() + (opt.linetag ? ('' + opt.linetag + '>') : ''));
1468 | }
1469 | }
1470 |
1471 | closeul();
1472 |
1473 | table && opt.tables !== false && builder.push('
');
1474 | iscode && opt.code !== false && builder.push('');
1475 |
1476 | builder = parseul(builder);
1477 |
1478 | if (!opt.noredraw && typeof(window) === 'object')
1479 | setTimeout(FUNC.markdownredraw, 1, null, opt);
1480 | return (opt.wrap ? ('') : '') + builder.join('\n').replace(/\t/g, ' ') + (opt.wrap ? '
' : '');
1481 | };
1482 |
1483 | })();
1484 |
1485 | });
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
3 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # BlogEngine template
2 |
3 | - [Documentation](https://docs.totaljs.com)
4 | - [Join Total.js Telegram](https://t.me/totaljs)
5 | - [Support](https://www.totaljs.com/support/)
6 |
7 | First you need to obtain a token from: . Then download the source-code or `bundle` only (recommendation).
8 |
9 | - open terminal / command-line
10 | - open app directory
11 | - install latest version of Total.js from NPM `$ npm install total4`
12 | - modify `/config` file
13 | - run `$ node index.js`
14 | - open browser `http://127.0.0.1:8000`
15 |
16 | __Requirements__:
17 |
18 | - Total.js `+v4`
19 |
20 | ## Extend template via components
21 |
22 | The template supports extending body or panel via Total.js components. Each component must have defined group called `blogengine`.
23 |
24 | __Parts__:
25 |
26 | - `body-top`
27 | - `body-bottom`
28 | - `panel-top`
29 | - `panel-bottom`
30 |
31 | [license-image]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat
32 | [license-url]: license.txt
33 |
--------------------------------------------------------------------------------
/resources/default.resource:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/totaljs/blogengine/644065c43bcb13d522bc8c254556b38ae8bb3767/resources/default.resource
--------------------------------------------------------------------------------
/views/detail.html:
--------------------------------------------------------------------------------
1 | @{meta(model.name + ' - ' + CONF.name, model.summary, model.tags)}
2 |
3 | @{section ogtags}
4 |
5 |
6 |
7 |
8 |
9 |
10 | @{end}
11 |
12 | @{if model.picture.indexOf('empty') == -1}
13 |
14 | @{fi}
15 |
16 |
17 | @{!model.body}
18 | @{if model.similar && model.similar.length}
19 |
20 |
@(Other posts)
21 |
26 |
27 | @{fi}
28 |
29 |
30 |
31 | @{section panel}
32 |
33 |
34 |
@(Published)
35 |
@{model.dtpublished.format('@(dd MMM. yyyy)')}
36 |
37 |
38 | @{if model.category}
39 |
40 |
@(Category)
41 |
@{model.category}
42 |
43 | @{fi}
44 |
45 |
46 |
@(Count views)
47 |
@{model.countviews}x
48 |
49 | @{if model.readingtime}
50 |
51 |
@(Reading time)
52 |
@{model.readingtime} @(min.)
53 |
54 | @{fi}
55 | @{if model.tags.length}
56 |
61 | @{fi}
62 |
63 | @{end}
64 |
65 |
--------------------------------------------------------------------------------
/views/index.html:
--------------------------------------------------------------------------------
1 | @{if url === '/'}
2 | @{meta(CONF.name, CONF.description)}
3 | @{fi}
4 |
5 | @{if url !== '/'}
6 | @{title}
7 | @{fi}
8 |
9 | @{if query.tag}
10 | @(Posts by tag:) "@{query.tag}"
11 | @{fi}
12 |
13 | @{if url === '/' && model.tiles}
14 |
15 | @{foreach m in model.tiles.items}
16 |
17 |
18 |

19 |
@{m.name}
20 |
@{m.dtpublished.format('@(dd MMM. yyyy)')}
21 |
22 |
23 | @{end}
24 |
25 |
28 | @{fi}
29 |
30 | @{if !model.items.length}
31 |
32 |
33 |
34 |
35 |
@(Database doesn't contain any posts.)
36 |
37 |
38 |
39 | @{fi}
40 |
41 |
42 | @{foreach m in model.items}
43 |
44 |
45 |

46 |
@{if m.userid !== m.ownerid}@{m.ownername} @(for) @{fi}@{m.username}
47 |
@{if m.age < 3}@(NEW)@{fi}@{m.name}. @{m.summary}
48 |
@{m.dtpublished.format('@(dd MMM. yyyy)')}@{if m.readingtime}, @{m.readingtime} @(min. read)@{fi}
49 |
50 |
51 | @{end}
52 |
53 |
54 | @{if model.pages > 1}
55 |
60 | @{fi}
--------------------------------------------------------------------------------
/views/layout.html:
--------------------------------------------------------------------------------
1 | @{layout('')}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | @{section('ogtags')}
19 | @{import('meta', 'head', 'default.css', 'default.js + ui.js', 'favicon.ico')}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
51 |
52 |
53 |
54 |
55 |
56 |

57 |
@{MAIN.account.name}
58 |
@{if CONF.description}@{CONF.description}@{else}@{MAIN.account.signature}@{fi}
59 |
60 |
61 |
62 |
63 |
64 |
72 |
73 |
74 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | @{part('body-top')}
95 | @{body}
96 | @{part('body-bottom')}
97 |
98 |
99 |
100 |
101 |
102 |

103 |
@{MAIN.account.name}
104 |
@{if CONF.description}@{CONF.description}@{else}@{MAIN.account.signature}@{fi}
105 |
106 |
107 | @{if CONF.facebook}
108 |
109 | @{fi}
110 | @{if CONF.twitter}
111 |
112 | @{fi}
113 | @{if CONF.github}
114 |
115 | @{fi}
116 | @{if CONF.linkedin}
117 |
118 | @{fi}
119 | @{if CONF.youtube}
120 |
121 | @{fi}
122 | @{if CONF.instagram}
123 |
124 | @{fi}
125 |
126 | @{part('panel-top')}
127 |
128 |
129 |
134 |
135 | @{section('panel')}
136 | @{part('panel-bottom')}
137 |
138 |
139 |
140 |
141 |
142 |
143 |
147 |
148 | @{components('blogengine')}
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/views/tiles.html:
--------------------------------------------------------------------------------
1 | @{meta('@(Tiles: from )' + CONF.name, CONF.description)}
2 |
3 | @{if !model.items.length}
4 |
5 |
6 |
7 |
8 |
@(Database doesn't contain any tiles.)
9 |
10 |
11 |
12 | @{fi}
13 |
14 |
15 | @{foreach m in model.items}
16 |
17 |
18 |

19 |
@{m.name}
20 |
@{m.dtpublished.format('@(dd MMM. yyyy)')}
21 |
22 |
23 | @{end}
24 |
25 |
26 | @{if model.pages > 1}
27 |
32 | @{fi}
--------------------------------------------------------------------------------