Первое, что нам нужно для создания статического сайта — это шаблон. Для этого урока мы собираемся сделать его очень простым, всего два файла, один для страниц и один для рендеринга меню/навигационной панели. Файлы для шаблона будут представлять собой простой плоский html с небольшим количеством синтаксиса Mustache, помещенный в папку шаблона проекта. Мы будем использовать Milligram CSS, чтобы придать нашей странице немного стиля.
Ниже код для файла index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>{{title}}</title> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> <link rel="stylesheet" href="//cdn.rawgit.com/necolas/normalize.css/master/normalize.css"> <link rel="stylesheet" href="//cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css"> </head> <body> <div class='navbar'> {{> menu }} </div> <div class="row"> <div class="column column-80">{{{content}}}</div> </div> </body> <style> .navbar { margin-bottom: 10px; } .navbar ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #606c76; } .navbar li { float: left; margin-bottom: 0; } .navbar li a { display: block; color: white; text-align: center; padding: 14px 16px; text-decoration: none; } .navbar li a:hover { background-color: #ab5dda; } </style> </html>
А затем частичный _menu.html, который будет отображать заголовки страниц на панели навигации.
<ul> {{#menu}} <li><a href="{{page_link}}">{{title}}</a></li> {{/menu}} </ul>
Оба этих файла говорят сами за себя, но Mustache действительно мощный, поэтому мы предлагаем вам прочитать документацию, доступную на официальном сайте.
Генератор
Пришло время создать приложение NodeJs, которое, начиная с файлов, помещенных в папку (исходный код в нашем примере), будет собирать весь сайт. Ниже вы можете найти весь необходимый код, чтобы это произошло.
Поместите приведенный ниже код в файл index.js.
const watch = require('node-watch'); const showdown = require('showdown') const converter = new showdown.Converter() const fse = require('fs-extra') const fs = require('fs') const must = require ('mustache'); const glob = require('glob') const path =require('path') const liveServer = require("live-server"); const source_dir="./source" const output_dir="./output" const template_dir="./template" var page_menu=[] var params = { root: "output", open: true, file: "index.html", }; var generateMenu = ()=>{ page_menu=[] glob(source_dir+"/pages/**.md", (err, files)=> { files.forEach((file)=>{ const file_name = path.basename(file).replace('.md',''); const out_file_name = file_name+'.html' page_menu.push({ title:file_name, page_link:'/'+out_file_name }); }); }); } var generatePage = (file)=>{ const template = fse.readFileSync('template/index.html','UTF8'); const menu = fse.readFileSync('template/_menu.html','UTF8'); fse.readFile(file,'UTF8',(err,data)=>{ const file_name = path.basename(file).replace('.md',''); var out_file_name = file_name + '.html' var html = converter.makeHtml(data); fs.stat(file,(err,stat)=>{ var page_data = { title:file_name, publish_date: stat.atime, content:html, menu:page_menu } var rendered = must.render(template,page_data,{ menu:menu }) fse.writeFile('output/'+out_file_name,rendered); console.log("Generated %s", out_file_name) }) }); } const refresh = () =>{ fse.emptyDir(output_dir, err => { if (err) return console.error(err) glob(source_dir+"/pages/**.md", (er, files)=> { files.forEach((file)=>{ generatePage(file) }); }) console.log('success!') }); } generateMenu() refresh() watch(source_dir, { recursive: true }, function(evt, name) { generateMenu() refresh() }); liveServer.start(params);
Как вы можете видеть, каждый раз, когда файл изменяется в исходном каталоге, вызываются функции generateMenu и Refresh. Функция generateMenu перечисляет все файлы в папке и для каждого из них вставляет объект am в массив page_menu. Функция обновления делает почти то же самое, но для каждого файла уценки в папке он будет отображаться в статический html-файл с использованием функции рендеринга усов. Массив page_menu передается в качестве параметра этой функции, поэтому механизм шаблонов может отображать меню (панель навигации).
Вывод
Это очень простой генератор статических сайтов, но он основан на принципах, на которых основаны другие проекты. К этому базовому примеру можно добавить много вещей, например, интерпретатор главной страницы, чтобы назначить заголовки и другие функции для страницы. Другой тип источника, например сообщения или функция заказа. Предел - ваше воображение.
Полный код этого руководства можно найти на нашей странице Github.
Если вам понравилась эта работа, пожалуйста, не забудьте поделиться ею :)