@terrymooreii/sia 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +33 -0
- package/.prettierignore +3 -0
- package/.prettierrc +8 -0
- package/lib/build.js +20 -0
- package/lib/helpers.js +37 -0
- package/lib/index.js +22 -0
- package/lib/init.js +8 -0
- package/lib/markdown.js +33 -0
- package/lib/new.js +46 -0
- package/lib/parse.js +94 -0
- package/lib/readconfig.js +16 -0
- package/lib/rss.js +63 -0
- package/package.json +26 -0
- package/readme.md +100 -0
- package/templates/siarc-template.js +53 -0
- package/templates/src/_partials/_footer.njk +1 -0
- package/templates/src/_partials/_head.njk +35 -0
- package/templates/src/_partials/_header.njk +1 -0
- package/templates/src/_partials/_layout.njk +12 -0
- package/templates/src/_partials/_nav.njk +12 -0
- package/templates/src/_partials/page.njk +5 -0
- package/templates/src/_partials/post.njk +13 -0
- package/templates/src/_partials/posts.njk +19 -0
- package/templates/src/assets/android-chrome-192x192.png +0 -0
- package/templates/src/assets/android-chrome-512x512.png +0 -0
- package/templates/src/assets/apple-touch-icon.png +0 -0
- package/templates/src/assets/favicon-16x16.png +0 -0
- package/templates/src/assets/favicon-32x32.png +0 -0
- package/templates/src/assets/favicon.ico +0 -0
- package/templates/src/assets/site.webmanifest +19 -0
- package/templates/src/content/index.md +7 -0
- package/templates/src/css/markdown.css +1210 -0
- package/templates/src/css/theme.css +120 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Build and GH-Page Deploy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v3
|
|
18
|
+
with:
|
|
19
|
+
persist-credentials: false
|
|
20
|
+
|
|
21
|
+
- name: Install
|
|
22
|
+
run: npm install
|
|
23
|
+
|
|
24
|
+
- name: Build
|
|
25
|
+
run: |
|
|
26
|
+
npm run build
|
|
27
|
+
|
|
28
|
+
- name: Deploy to GH Page
|
|
29
|
+
uses: JamesIves/github-pages-deploy-action@4.1.1
|
|
30
|
+
with:
|
|
31
|
+
branch: gh-pages
|
|
32
|
+
folder: public
|
|
33
|
+
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/lib/build.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import config from './readconfig.js'
|
|
2
|
+
import { parseContent, generateBlogListPage } from './parse.js'
|
|
3
|
+
import { mkdir, cpdir } from './helpers.js'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { generateRSS } from './rss.js'
|
|
6
|
+
const { app } = config
|
|
7
|
+
|
|
8
|
+
export const build = () => {
|
|
9
|
+
mkdir(path.join(app.public))
|
|
10
|
+
|
|
11
|
+
const posts = parseContent()
|
|
12
|
+
generateBlogListPage(posts)
|
|
13
|
+
generateRSS(posts, app.feed.count)
|
|
14
|
+
|
|
15
|
+
cpdir(path.join(app.src, app.css), path.join(app.public, app.css))
|
|
16
|
+
cpdir(path.join(app.src, app.js), path.join(app.public, app.js))
|
|
17
|
+
cpdir(path.join(app.src, app.images), path.join(app.public, app.images))
|
|
18
|
+
cpdir(path.join(app.src, app.assets), path.join(app.public, app.assets))
|
|
19
|
+
console.log('Build success')
|
|
20
|
+
}
|
package/lib/helpers.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
|
|
3
|
+
export const formatDate = (postDate) => {
|
|
4
|
+
const d = new Date(postDate)
|
|
5
|
+
const date = d.toLocaleDateString('en-us', {
|
|
6
|
+
year: 'numeric',
|
|
7
|
+
month: 'long',
|
|
8
|
+
day: 'numeric',
|
|
9
|
+
})
|
|
10
|
+
const time = d.toLocaleTimeString()
|
|
11
|
+
return {
|
|
12
|
+
datetime: `${date} ${time}`,
|
|
13
|
+
date,
|
|
14
|
+
year: d.getFullYear(),
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const mkdir = (path) => {
|
|
19
|
+
if (!fs.existsSync(path)) {
|
|
20
|
+
fs.mkdirSync(path)
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const cpdir = (src, dest) => {
|
|
27
|
+
if (fs.existsSync(src)) {
|
|
28
|
+
mkdir(dest)
|
|
29
|
+
fs.cpSync(src, dest, { recursive: true })
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const writefile = (file, content, options = { flags: 'w+' }) => {
|
|
36
|
+
fs.writeFileSync(file, content, options)
|
|
37
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { build } from './build.js'
|
|
4
|
+
import { create } from './new.js'
|
|
5
|
+
import { init } from './init.js'
|
|
6
|
+
|
|
7
|
+
const [, , cmd, type, folder] = process.argv
|
|
8
|
+
|
|
9
|
+
switch (cmd) {
|
|
10
|
+
case init:
|
|
11
|
+
init()
|
|
12
|
+
break
|
|
13
|
+
case 'build':
|
|
14
|
+
build()
|
|
15
|
+
break
|
|
16
|
+
case 'new':
|
|
17
|
+
create(type, folder)
|
|
18
|
+
break
|
|
19
|
+
default:
|
|
20
|
+
console.log('Missing command')
|
|
21
|
+
break
|
|
22
|
+
}
|
package/lib/init.js
ADDED
package/lib/markdown.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import config from './readconfig.js'
|
|
2
|
+
import markdownit from 'markdown-it'
|
|
3
|
+
import hljs from 'highlight.js'
|
|
4
|
+
|
|
5
|
+
import javascript from 'highlight.js/lib/languages/javascript'
|
|
6
|
+
import bash from 'highlight.js/lib/languages/bash'
|
|
7
|
+
hljs.registerLanguage('javascript', javascript)
|
|
8
|
+
hljs.registerLanguage('bash', bash)
|
|
9
|
+
|
|
10
|
+
const md = markdownit({
|
|
11
|
+
html: true,
|
|
12
|
+
linkify: true,
|
|
13
|
+
typographer: true,
|
|
14
|
+
breaks: true,
|
|
15
|
+
highlight: function (str, lang) {
|
|
16
|
+
if (config?.app?.markdown?.highlightjs && lang && hljs.getLanguage(lang)) {
|
|
17
|
+
try {
|
|
18
|
+
return hljs.highlight(str, { language: lang }).value
|
|
19
|
+
} catch (__) {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return ''
|
|
23
|
+
},
|
|
24
|
+
...config?.app?.markdown?.markdownitOptions,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
if (config?.app?.markdown?.plugins) {
|
|
28
|
+
config.app.markdown.plugins.forEach((plugin) => {
|
|
29
|
+
md.use(plugin)
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default md
|
package/lib/new.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import config from './readconfig.js'
|
|
4
|
+
import { mkdir } from './helpers.js'
|
|
5
|
+
import slugify from 'slugify'
|
|
6
|
+
|
|
7
|
+
const { app } = config
|
|
8
|
+
|
|
9
|
+
export const create = (type, folder) => {
|
|
10
|
+
if (!type || !folder) {
|
|
11
|
+
console.log('Must specify a type and folder')
|
|
12
|
+
process.exit(1)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const slugified = slugify(folder, {
|
|
16
|
+
replacement: '-',
|
|
17
|
+
lower: true,
|
|
18
|
+
strict: true,
|
|
19
|
+
locale: 'en',
|
|
20
|
+
trim: true,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
if (!['page', 'post'].includes(type)) {
|
|
24
|
+
console.log('Invalid type. post or page')
|
|
25
|
+
process.exit(1)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const date = new Date()
|
|
29
|
+
const createdAt = date.toISOString()
|
|
30
|
+
|
|
31
|
+
const template = `---
|
|
32
|
+
created_at: ${createdAt}
|
|
33
|
+
title: ${slugified}
|
|
34
|
+
description:
|
|
35
|
+
image:
|
|
36
|
+
template: ${type}
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
Add ${type} content here
|
|
40
|
+
|
|
41
|
+
`
|
|
42
|
+
|
|
43
|
+
const root = path.join(app.src, app.content, slugified)
|
|
44
|
+
mkdir(root)
|
|
45
|
+
fs.writeFileSync(path.join(root, `index.md`), template)
|
|
46
|
+
}
|
package/lib/parse.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import config from './readconfig.js'
|
|
2
|
+
import matter from 'gray-matter'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import nunjucks from 'nunjucks'
|
|
6
|
+
import md from './markdown.js'
|
|
7
|
+
|
|
8
|
+
import { formatDate, mkdir, writefile } from './helpers.js'
|
|
9
|
+
|
|
10
|
+
const { app, site } = config
|
|
11
|
+
|
|
12
|
+
nunjucks.configure(path.join(app.src, app.partials), {
|
|
13
|
+
autoescape: false,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const render = (srcFolder, publicFolder, file) => {
|
|
17
|
+
const parsed = matter.read(path.join(srcFolder, file))
|
|
18
|
+
const { data: page, content } = parsed
|
|
19
|
+
const fileName = path.parse(file).name
|
|
20
|
+
const fileNameHtml = `${fileName}.html`
|
|
21
|
+
|
|
22
|
+
if (!page.template) return
|
|
23
|
+
|
|
24
|
+
page.date = formatDate(page.created_at)
|
|
25
|
+
|
|
26
|
+
// technically slug is the permalink or uri
|
|
27
|
+
// this removes the public folder path to reveal the slug path
|
|
28
|
+
page.slug = path.join(publicFolder).replace(app.public, '')
|
|
29
|
+
// index pages will render automatically in folder but if the file
|
|
30
|
+
// name is not then make sure it included in the permalink
|
|
31
|
+
if (fileNameHtml !== 'index.html') {
|
|
32
|
+
page.slug = path.join(page.slug, fileNameHtml)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const html = md.render(content)
|
|
36
|
+
const rendered = nunjucks.render(`${page.template}${app.template_ext}`, {
|
|
37
|
+
content: html,
|
|
38
|
+
page,
|
|
39
|
+
site,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
writefile(path.join(publicFolder, fileNameHtml), rendered)
|
|
43
|
+
|
|
44
|
+
// collect all the page attibutes for blog posts
|
|
45
|
+
if (page.template === 'post') {
|
|
46
|
+
return { ...page }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const getAllFiles = (srcPath, posts) => {
|
|
51
|
+
// take the source path and generate the public path equivalent
|
|
52
|
+
const publicPath = srcPath.replace(path.join(app.src, app.content), app.public)
|
|
53
|
+
|
|
54
|
+
mkdir(publicPath)
|
|
55
|
+
|
|
56
|
+
const files = fs.readdirSync(srcPath)
|
|
57
|
+
|
|
58
|
+
files.forEach((file) => {
|
|
59
|
+
const filePath = path.join(srcPath, file)
|
|
60
|
+
|
|
61
|
+
if (fs.statSync(filePath).isDirectory()) {
|
|
62
|
+
// recursively look at files
|
|
63
|
+
getAllFiles(filePath, posts)
|
|
64
|
+
} else {
|
|
65
|
+
// Process markdown files and render the nunjucks template
|
|
66
|
+
if (path.extname(file) === '.md') {
|
|
67
|
+
const post = render(srcPath, publicPath, file)
|
|
68
|
+
if (post) {
|
|
69
|
+
posts.push(post)
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
// file is not a markdown file so just copy it to its public folder
|
|
73
|
+
fs.copyFileSync(path.join(srcPath, file), path.join(publicPath, file))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
return posts
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const parseContent = () => {
|
|
81
|
+
return getAllFiles(path.join(app.src, app.content), [], '/').filter((o) => o != null) // make sure there are no undefined items
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const generateBlogListPage = (posts) => {
|
|
85
|
+
const rendered = nunjucks.render(app.posts_template, {
|
|
86
|
+
posts,
|
|
87
|
+
site,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const blogListDirectory = path.join(app.public, app.blog_list)
|
|
91
|
+
|
|
92
|
+
mkdir(blogListDirectory)
|
|
93
|
+
writefile(path.join(blogListDirectory, 'index.html'), rendered)
|
|
94
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { findUp } from 'find-up'
|
|
2
|
+
|
|
3
|
+
async function getConfig() {
|
|
4
|
+
try {
|
|
5
|
+
const siarc = await findUp('siarc.js')
|
|
6
|
+
const { default: config } = await import(siarc)
|
|
7
|
+
return config
|
|
8
|
+
} catch (err) {
|
|
9
|
+
console.log('Unable to find and load the siarc.js file.')
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const config = await getConfig()
|
|
13
|
+
export default config ?? {
|
|
14
|
+
app: {},
|
|
15
|
+
site: {},
|
|
16
|
+
}
|
package/lib/rss.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { Feed } from 'feed'
|
|
4
|
+
import config from './readconfig.js'
|
|
5
|
+
const { app, site } = config
|
|
6
|
+
|
|
7
|
+
const feed = new Feed({
|
|
8
|
+
title: site.blog_title,
|
|
9
|
+
description: site.blog_description,
|
|
10
|
+
id: site.blog_url,
|
|
11
|
+
link: site.blog_url,
|
|
12
|
+
language: 'en', // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
|
|
13
|
+
image: site.blog_image,
|
|
14
|
+
favicon: `${site.blog_url}/assets/favicon.ico`,
|
|
15
|
+
copyright: `All rights reserved ${new Date().getFullYear()}, ${site.author}`,
|
|
16
|
+
feedLinks: {
|
|
17
|
+
json: `${site.blog_url}/feed.json`,
|
|
18
|
+
atom: `${site.blog_url}/atom.xml`,
|
|
19
|
+
},
|
|
20
|
+
author: {
|
|
21
|
+
name: site.author,
|
|
22
|
+
email: site.email_address,
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const writeFeed = (name, content) => {
|
|
27
|
+
fs.writeFileSync(path.join(app.public, name), content, {
|
|
28
|
+
flag: 'w+',
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const generateRSS = (posts, count = 10) => {
|
|
33
|
+
posts.splice(0, count).forEach((post) => {
|
|
34
|
+
feed.addItem({
|
|
35
|
+
title: post.title,
|
|
36
|
+
id: `${site.blog_url}${post.slug}`,
|
|
37
|
+
link: `${site.blog_url}${post.slug}`,
|
|
38
|
+
description: post.description,
|
|
39
|
+
content: post.content,
|
|
40
|
+
author: [
|
|
41
|
+
{
|
|
42
|
+
name: site.author,
|
|
43
|
+
email: site.email_address,
|
|
44
|
+
link: site.blog_url,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
date: post.created_at,
|
|
48
|
+
image: `${site.blog_url}/${post.image}`,
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
if (app.feed.rss2) {
|
|
53
|
+
writeFeed('rss.xml', feed.rss2())
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (app.feed.atom1) {
|
|
57
|
+
writeFeed('atom.xml', feed.atom1())
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (app.feed.json1) {
|
|
61
|
+
writeFeed('feed.json', feed.json1())
|
|
62
|
+
}
|
|
63
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@terrymooreii/sia",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"lint": "npx prettier . --write"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"bin": {
|
|
13
|
+
"sia": "./lib/index.js"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"feed": "^4.2.2",
|
|
17
|
+
"find-up": "^7.0.0",
|
|
18
|
+
"forever": "^4.0.3",
|
|
19
|
+
"gray-matter": "^4.0.3",
|
|
20
|
+
"highlight.js": "^11.9.0",
|
|
21
|
+
"markdown-it": "^14.0.0",
|
|
22
|
+
"nunjucks": "^3.2.4",
|
|
23
|
+
"prettier": "3.2.1",
|
|
24
|
+
"slugify": "^1.6.6"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Sia Micro blog
|
|
2
|
+
|
|
3
|
+
Sia is static site generator
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install --save-dev @terrymooreii/sia
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
After installation run the following command in a new node repo
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
sia init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This will install the nunjucks template files, some base css and a shell `index.html`
|
|
18
|
+
|
|
19
|
+
It also add the `siarc.js` config file to the root of your project.
|
|
20
|
+
|
|
21
|
+
The `siarc.js` file contains two sections. One for configuing your site information. The second is to configure the app's folders, numjucks template, and markdown configutation.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Adding pages and posts
|
|
25
|
+
|
|
26
|
+
The easist way to add a new page or a post to your site is to run the following command
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
sia new post new-post-name
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This will create a new folder in the `content` folder called `new-post-name` and add a shell `index.html`
|
|
33
|
+
|
|
34
|
+
You can do the same thing to create a new page
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
sia new post new-post-name
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The difference between pages and posts is that during the build process sia keeps tack of all posts and generate a post list page at the url `/blog`
|
|
41
|
+
|
|
42
|
+
New pages and post will have config area at the top that tell sia how to handle the page and post. All properties expect the image is required. The image is used to generate the page's `og:image`. If its not present we will use the `blogs_image`.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
template: post
|
|
48
|
+
title: Page title
|
|
49
|
+
created_at: 2024-01-12 16:00:00-5:00
|
|
50
|
+
description: Testing out some markdown
|
|
51
|
+
---
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `template` is the nunjucks template located in `src/_partials`
|
|
55
|
+
- `title` is the post title and used in the blog posts list page
|
|
56
|
+
- `create_at` is the date of the post
|
|
57
|
+
- `description` a short description of the post
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## Build
|
|
61
|
+
|
|
62
|
+
To build the site run
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
sia build
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This will parse all markdown files and then numjucks.
|
|
69
|
+
The default output folder is `/public`
|
|
70
|
+
|
|
71
|
+
The build command will also copy all `assets`, `js` and `css` to the `/public` folder. If a post or a page folder contain other files other than markdown then those files will also get moved to the `/public/<folder>`. This makes it easy to organize a single page or posts with custom js, css, or images.
|
|
72
|
+
|
|
73
|
+
All markdown files will get parsed with `markdown-it` and you can add additional `markdown-it` plugins in the `siarc.js` file.
|
|
74
|
+
|
|
75
|
+
## Local developement
|
|
76
|
+
|
|
77
|
+
Currently these are the apps that I use on my blog for local development and building
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
"scripts": {
|
|
81
|
+
"serve": "npx http-server public",
|
|
82
|
+
"watch": "forever --watchDirectory ./src -w ./node_modules/@terrymooreii/sia/lib/index.js build",
|
|
83
|
+
"dev": "concurrently --kill-others \"npm run watch\" \"npm run serve\"",
|
|
84
|
+
"clean": "rm -rf public",
|
|
85
|
+
"build": "sia build"
|
|
86
|
+
},
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
npm install forever concurrently http-server
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
coming soon will be a simple way to run a local web server to see live updates to posts and pages as you work via the `sia` command.
|
|
94
|
+
|
|
95
|
+
## Templates and site configuration
|
|
96
|
+
|
|
97
|
+
All `njk` files are in a simple default state to generate a simple and clean website. You can modifiy the html in these file to customer your site to look how you want.
|
|
98
|
+
|
|
99
|
+
If you make something cool please let me know.
|
|
100
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import url from 'url'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
const __filename = url.fileURLToPath(import.meta.url)
|
|
5
|
+
const __dirname = path.dirname(__filename)
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
// User Config
|
|
9
|
+
site: {
|
|
10
|
+
blog_url: process.env.BLOG_URL || '',
|
|
11
|
+
blog_title: '',
|
|
12
|
+
blog_description: '',
|
|
13
|
+
blog_image: '',
|
|
14
|
+
author: '',
|
|
15
|
+
email_address: '',
|
|
16
|
+
highlightjs_theme: 'atom-one-dark.min',
|
|
17
|
+
nav: [
|
|
18
|
+
{
|
|
19
|
+
title: 'Home',
|
|
20
|
+
href: '/',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: 'Blog',
|
|
24
|
+
href: '/blog',
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// App config
|
|
30
|
+
app: {
|
|
31
|
+
public: `${__dirname}/public`,
|
|
32
|
+
src: `${__dirname}/src`,
|
|
33
|
+
partials: '_partials',
|
|
34
|
+
template_ext: '.njk',
|
|
35
|
+
content: 'content',
|
|
36
|
+
css: 'css',
|
|
37
|
+
js: 'js',
|
|
38
|
+
assets: 'assets',
|
|
39
|
+
images: 'imgs',
|
|
40
|
+
posts_template: 'posts.njk',
|
|
41
|
+
blog_list: 'blog',
|
|
42
|
+
feed: {
|
|
43
|
+
count: 10,
|
|
44
|
+
rss2: true,
|
|
45
|
+
atom1: true,
|
|
46
|
+
json1: true,
|
|
47
|
+
},
|
|
48
|
+
markdown: {
|
|
49
|
+
highlightjs: true,
|
|
50
|
+
plugins: [],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<footer>Made with Sia</footer>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<head>
|
|
2
|
+
<meta charset="UTF-8" />
|
|
3
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
4
|
+
<title>{{ page.title if page.title else site.blog_title }}</title>
|
|
5
|
+
<meta name="author" content="{{ site.author }}" />
|
|
6
|
+
<meta
|
|
7
|
+
name="description"
|
|
8
|
+
content="{{ page.description if page.description else site.blog_description }}"
|
|
9
|
+
/>
|
|
10
|
+
{% if page.slug %}
|
|
11
|
+
<meta property="og:url" content="{{site.blog_url}}{{ page.slug }}" />
|
|
12
|
+
{% else %}
|
|
13
|
+
<meta property="og:url" content="{{site.blog_url}}" />
|
|
14
|
+
{% endif %}
|
|
15
|
+
<meta property="og:title" content="{{ page.title if page.title else site.blog_title }}" />
|
|
16
|
+
<meta property="og:description" content="{{ page.description if page.description else site.blog_description }}" />
|
|
17
|
+
<meta property="og:image" content="{{ page.post_image }}" />
|
|
18
|
+
|
|
19
|
+
<link type="application/rss+xml" rel="alternate" href="{{ site.blog_url }}/rss.xml" title="{{ site.blog_title }} - RSS Feed" />
|
|
20
|
+
<link type="application/atom+xml" rel="alternate" href="{{ site.blog_url }}/atom.xml" title="{{ site.blog_title }} - Atom Feed" />
|
|
21
|
+
<link type="application/feed+json" rel="alternate" href="{{ site.blog_url }}/feed.json" title="{{ site.blog_title }} - JSON Feed" />
|
|
22
|
+
|
|
23
|
+
<link rel="icon" type="image/x-icon" href="{{ site.blog_url }}/assest/favicon.ico">
|
|
24
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ site.blog_url }}/assets/apple-touch-icon.png">
|
|
25
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ site.blog_url }}/assets/favicon-32x32.png">
|
|
26
|
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ site.blog_url }}/assets/favicon-16x16.png">
|
|
27
|
+
<link rel="manifest" href="{{ site.blog_url }}/assets/site.webmanifest">
|
|
28
|
+
|
|
29
|
+
<link rel="stylesheet" type="text/css" href="{{ site.blog_url }}/css/theme.css" />
|
|
30
|
+
<link rel="stylesheet" type="text/css" href="{{ site.blog_url }}/css/markdown.css" />
|
|
31
|
+
<link
|
|
32
|
+
rel="stylesheet"
|
|
33
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/{{ site.highlightjs_theme }}.css"
|
|
34
|
+
/>
|
|
35
|
+
</head>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!-- add content here to add it to the top of each page/post -->
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE >
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
{% include "_head.njk" %}
|
|
4
|
+
<body class="markdown-body" data-theme="dark">
|
|
5
|
+
{% include "_nav.njk" %}
|
|
6
|
+
<main class="content">
|
|
7
|
+
{% include "_header.njk" %}
|
|
8
|
+
{% block content %}{% endblock %}
|
|
9
|
+
{% include "_footer.njk" %}
|
|
10
|
+
</main>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<nav>
|
|
2
|
+
<div class="content nav-container">
|
|
3
|
+
<h1 class="blog-title"><a href="{{ site.blog_url }}">{{ site.blog_title }}</a></h1>
|
|
4
|
+
<ul>
|
|
5
|
+
{% for link in site.nav %}
|
|
6
|
+
<li>
|
|
7
|
+
<a href="{{ site.blog_url }}{{ link.href }}" title="{{ link.title }}">{{ link.title }}</a>
|
|
8
|
+
</li>
|
|
9
|
+
{% endfor %}
|
|
10
|
+
</ul>
|
|
11
|
+
</div>
|
|
12
|
+
</nav>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{%extends "_layout.njk" %}
|
|
2
|
+
|
|
3
|
+
{% block content %}
|
|
4
|
+
<article>
|
|
5
|
+
<header>
|
|
6
|
+
<h1 class="post-title">{{ page.title }}</h1>
|
|
7
|
+
<time datetime="{{page.date.datetime}}" class="date">
|
|
8
|
+
{{ page.date.datetime }}
|
|
9
|
+
</time>
|
|
10
|
+
</header>
|
|
11
|
+
<p>{{ content }}</p>
|
|
12
|
+
</article>
|
|
13
|
+
{% endblock %}
|