-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.js
More file actions
139 lines (119 loc) Β· 4.65 KB
/
build.js
File metadata and controls
139 lines (119 loc) Β· 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')
const getRepoName = () => {
try {
return execSync('git remote get-url origin', { encoding: 'utf8' }).split('/').pop().replace('.git', '').trim()
} catch {
return null
}
}
const srcDir = 'src'
const buildDir = 'build'
const isDev = process.argv.includes('--dev')
const repoName = getRepoName()
const basePath = isDev || fs.existsSync('CNAME') ? '/' : `/${repoName}/`
const build = () => {
fs.rmSync(buildDir, { force: true, recursive: true })
fs.mkdirSync(buildDir, { recursive: true })
const layout = fs.readFileSync(path.join(srcDir, 'layout.html'), 'utf8')
const pages = JSON.parse(fs.readFileSync(path.join(srcDir, 'pages.json'), 'utf8'))
const buildPage = (content, pageName, outputPath, pageDir, htmlFileName, layout) => {
const pageBase = pageName === 'home' ? basePath : `${basePath}${pageName}/`
const cssPath = path.join(pageDir, `${htmlFileName}.css`)
const jsPath = path.join(pageDir, `${htmlFileName}.js`)
const styles = fs.existsSync(cssPath) ? `<link rel="stylesheet" href="${htmlFileName}.css" />` : ''
const scripts = fs.existsSync(jsPath) ? `<script defer src="${htmlFileName}.js"></script>` : ''
const replacements = {
base: basePath,
pageBase,
content,
scripts,
styles,
...(pages['index'] || {}),
...(pages[pageName] || {}),
}
let html = Object.keys(replacements).reduce(
(acc, key) => acc.replace(new RegExp(`{${key}}`, 'g'), replacements[key]),
layout,
)
fs.writeFileSync(outputPath, html)
}
const copyAsset = (dir, outputDir, fileName) => {
const srcPath = path.join(dir, fileName)
if (fs.existsSync(srcPath)) {
fs.copyFileSync(srcPath, path.join(outputDir, fileName))
console.log(`π ${path.relative(srcDir, srcPath)}`)
}
}
const processDir = (dir, outputDir, layout) => {
const localLayoutPath = path.join(dir, 'layout.html')
const activeLayout = fs.existsSync(localLayoutPath) ? fs.readFileSync(localLayoutPath, 'utf8') : layout
const entries = fs.readdirSync(dir, { withFileTypes: true })
const htmlFiles = entries
.filter(e => e.name.endsWith('.html') && e.name !== 'layout.html')
.map(e => e.name.replace('.html', ''))
entries.forEach(entry => {
const srcPath = path.join(dir, entry.name)
const relPath = path.relative(srcDir, srcPath)
if (entry.name === 'layout.html') return
if (entry.isDirectory()) {
const newOutputDir = path.join(outputDir, entry.name)
fs.mkdirSync(newOutputDir, { recursive: true })
processDir(srcPath, newOutputDir, activeLayout)
} else if (entry.name.endsWith('.html')) {
const htmlFileName = entry.name.replace('.html', '')
const dirPath = path.relative(srcDir, dir)
const folderName = path.basename(dir)
const isHome = htmlFileName === 'home' && !dirPath
const matchesFolder = htmlFileName === folderName && folderName !== 'src'
const pageName = isHome
? 'home'
: dirPath && !matchesFolder
? `${dirPath}/${htmlFileName}`
: dirPath || htmlFileName
const targetDir = isHome || matchesFolder ? outputDir : path.join(outputDir, htmlFileName)
if (!isHome && !matchesFolder) fs.mkdirSync(targetDir, { recursive: true })
buildPage(
fs.readFileSync(srcPath, 'utf8'),
pageName,
path.join(targetDir, 'index.html'),
dir,
htmlFileName,
activeLayout,
)
console.log(
`β
${relPath} β ${
isHome || matchesFolder ? path.relative(buildDir, targetDir) + '/' : htmlFileName + '/'
}index.html`,
)
copyAsset(dir, targetDir, `${htmlFileName}.css`)
copyAsset(dir, targetDir, `${htmlFileName}.js`)
} else {
const shouldSkip = entry.name.match(/\.(css|js)$/) && htmlFiles.includes(entry.name.replace(/\.(css|js)$/, ''))
if (!shouldSkip) {
fs.copyFileSync(srcPath, path.join(outputDir, entry.name))
console.log(`π ${relPath}`)
}
}
})
}
processDir(srcDir, buildDir, layout)
if (isDev) {
console.log('\n⨠Formatting all files')
execSync('npx prettier --write .', { stdio: 'inherit' })
}
console.log(`\nπ Build complete! ${isDev ? '(dev mode)' : ''}`)
}
build()
if (process.argv.includes('--watch')) {
let timeout
fs.watch(srcDir, { recursive: true }, () => {
clearTimeout(timeout)
timeout = setTimeout(() => {
console.log('\nπ Rebuilding')
build()
}, 100)
})
console.log('π Watching for changes')
}