kiss-ssg 1.3.0 → 1.4.4

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.
@@ -44,11 +44,17 @@
44
44
  {{/if}}
45
45
  </div>
46
46
 
47
- {{#scripts}}
48
- <p>not rendered</p>
49
- <script src='/assets/js/sub/script2.js'></script>
50
- <script src="assets/script3.js"></script>
51
- <script src="/assets/js/script1.js"></script>
52
- {{/scripts}}
47
+ {{#env is="development"}}
48
+ <p>Is Dev</p>
49
+ {{else}}
50
+ <p>Is NOT Dev</p>
51
+ {{/env}}
52
+
53
+ {{#env is="production"}}
54
+ <p>Is Production</p>
55
+ {{else}}
56
+ <p>Is NOT Production</p>
57
+ {{/env}}
58
+
53
59
  </body>
54
60
  </html>
@@ -1,11 +1,13 @@
1
1
  const Kiss = require('../kiss-ssg')
2
2
  const kiss = new Kiss({
3
3
  folders: {
4
+ root: '..',
4
5
  src: './5-helpers',
5
6
  build: '../public/5-helpers',
6
7
  },
7
8
  verbose: true,
8
- dev: false,
9
+ dev: true,
10
+ port: 8080,
9
11
  })
10
12
  .page({
11
13
  view: 'index.hbs',
package/kiss-serve.js CHANGED
@@ -4,8 +4,10 @@ const static = require('serve-static')
4
4
  const colors = require('colors')
5
5
  const app = connect()
6
6
 
7
- module.exports = async (httpRoot) => {
7
+ module.exports = async (httpRoot, port) => {
8
8
  if (!httpRoot) httpRoot = '/public'
9
+ if (!port) port = 3000
10
+
9
11
  app.use(function (req, res, next) {
10
12
  console.log(req.url)
11
13
  next()
@@ -26,9 +28,9 @@ module.exports = async (httpRoot) => {
26
28
 
27
29
  console.log(
28
30
  `Serving (${httpRoot}): `.grey,
29
- colors.yellow('http://localhost:3000')
31
+ colors.yellow('http://localhost:' + port)
30
32
  )
31
- app.listen(3000)
33
+ app.listen(port)
32
34
 
33
35
  const livereload = require('livereload')
34
36
  const server = livereload.createServer()
package/kiss-ssg.js CHANGED
@@ -5,21 +5,23 @@ const sass = require('sass')
5
5
  const chokidar = require('chokidar')
6
6
  const path = require('path')
7
7
  const htmlMinify = require('html-minifier').minify // https://www.npmjs.com/package/html-minifier
8
- const { minify } = require('terser')
9
8
  const colors = require('colors')
10
9
  const fetch = require('node-fetch')
11
10
  const handlebars = require('handlebars') // https://handlebarsjs.com/
12
11
  const layouts = require('handlebars-layouts') // https://www.npmjs.com/package/handlebars-layouts
13
12
  handlebars.registerHelper(layouts(handlebars))
14
13
 
14
+ const utils = require('./libs/utils.js')
15
+ console.log(typeof utils.trimLines)
16
+
15
17
  const { Remarkable } = require('remarkable')
16
18
  var remarkable = new Remarkable({
17
19
  html: true, // Enable HTML tags in source
18
- xhtmlOut: false, // Use '/' to close single tags (<br />)
19
- breaks: false, // Convert '\n' in paragraphs into <br>
20
+ xhtmlOut: true, // Use '/' to close single tags (<br />)
21
+ breaks: true, // Convert '\n' in paragraphs into <br>
20
22
  })
21
23
 
22
- async function registerHandlebarsHelpers(config) {
24
+ function registerHandlebarsHelpers(config) {
23
25
  handlebars.registerHelper('markdown', function (obj) {
24
26
  let returnVal = ''
25
27
  if (typeof obj === 'object') {
@@ -35,16 +37,21 @@ async function registerHandlebarsHelpers(config) {
35
37
  typeof obj
36
38
  )
37
39
  }
38
- return new handlebars.SafeString(remarkable.render(returnVal))
40
+ const md = remarkable.render(utils.trimLines(returnVal))
41
+ return new handlebars.SafeString(md)
39
42
  })
40
43
 
41
44
  handlebars.registerHelper('sass', function (context, options) {
42
45
  // console.log('params: ', typeof options, options, context)
43
46
  let output = ''
47
+ let outputStyle = 'expanded'
48
+ if (!config.dev) outputStyle = 'compressed'
49
+
44
50
  if (typeof context === 'string') {
45
51
  const sassOutput = sass.renderSync({
46
52
  file: path.join(process.cwd(), context),
47
53
  includePaths: config.sass.includePaths,
54
+ outputStyle: outputStyle,
48
55
  })
49
56
  output = `${output} \n${sassOutput.css}`
50
57
  }
@@ -109,124 +116,24 @@ async function registerHandlebarsHelpers(config) {
109
116
  return options.fn(context)
110
117
  })
111
118
 
112
- handlebars.registerHelper('scripts', function (context, options) {
113
- const returnLines = ['<!--Dev Script Output-->']
114
- const scripts = {}
115
- let scriptFolder = ''
116
- function stripStartingSlash(path) {
117
- if (path.startsWith('/')) {
118
- path = path.substring(1, path.length)
119
- path = stripStartingSlash(path)
119
+ handlebars.registerHelper('env', function (options) {
120
+ if (options.hash.is) {
121
+ const envIs = options.hash.is.toLowerCase()
122
+ if (envIs.includes('dev') && config.dev) {
123
+ return options.fn(this)
124
+ } else if (envIs.includes('prod') && !config.dev) {
125
+ return options.fn(this)
126
+ } else {
127
+ return options.inverse(this)
120
128
  }
121
- return path
122
- }
123
- context
124
- .fn(this)
125
- .split(/\r?\n/)
126
- .filter((line) => line.includes('src'))
127
- .forEach((line) => {
128
- let script = line.substring(line.search(/src=[',\"]/) + 5, line.length)
129
- script = script.substring(0, script.search(/[',\"]/))
130
- scriptFolder = script.substring(0, script.lastIndexOf('/'))
131
- scriptFolder = scriptFolder.replace('assets', '')
132
- scriptFolder = stripStartingSlash(scriptFolder)
133
- if (!scriptFolder) scriptFolder = 'bundles'
134
-
135
- const scriptPath = path.join(
136
- process.cwd(),
137
- this.config.folders.src,
138
- script
139
- )
140
-
141
- try {
142
- if (fs.existsSync(scriptPath)) {
143
- scripts[script] = fs.readFileSync(scriptPath, 'utf8')
144
- returnLines.push(line)
145
- } else {
146
- console.error(`404: ${scriptPath}`.red)
147
- }
148
- } catch (err) {
149
- console.error(err.yellow)
150
- }
151
- })
152
-
153
- const genRandomHex = (size) =>
154
- [...Array(size)]
155
- .map(() => Math.floor(Math.random() * 16).toString(16))
156
- .join('')
157
-
158
- const scriptPath = `${
159
- config.folders.build
160
- }/${scriptFolder}/bundle-${genRandomHex(12)}.js`
161
-
162
- if (config.dev) {
163
- return returnLines.join('\n')
164
129
  } else {
165
- console.log('Compressing scripts to:'.grey, scriptPath.green)
166
- minify(scripts, {
167
- output: {
168
- comments: false,
169
- },
170
- compress: {
171
- typeofs: false,
172
- },
173
- sourceMap: false,
174
- })
175
- .then((compressedScripts) => {
176
- fs.writeFileSync(scriptPath, compressedScripts.code, 'utf8')
177
- })
178
- .catch((error) => {
179
- console.error('Error compressing scripts'.red)
180
- console.error(color.yellow(error.message))
181
- })
182
- return `<script src='${scriptPath}'></script>`
130
+ console.error(
131
+ 'Environment helper missing "is" property'.red,
132
+ '{{#env}'.grey
133
+ )
134
+ return ''
183
135
  }
184
136
  })
185
-
186
- // handlebars.registerHelper('helperMissing', function () {
187
- // var options = arguments[arguments.length - 1]
188
- // var args = Array.prototype.slice.call(arguments, 0, arguments.length - 1)
189
- // return new handlebars.SafeString(
190
- // `<!-- Missing: ${options.name} (${args}) -->`
191
- // )
192
- // })
193
- }
194
-
195
- const utils = {
196
- toSlug(slug) {
197
- return slug
198
- .toLowerCase()
199
- .trim()
200
- .replace(/[\W_]+/g, '-')
201
- },
202
- toTitleCase(str) {
203
- return str
204
- .toLowerCase()
205
- .split(' ')
206
- .map(function (word) {
207
- return word.charAt(0).toUpperCase() + word.slice(1)
208
- })
209
- .join(' ')
210
- },
211
- trimPath(path) {
212
- if (path.startsWith('/')) path = path.substring(1, path.length)
213
- if (path.endsWith('/')) path = path.substring(0, path.length - 1)
214
- return path
215
- },
216
- sanitizePath(path) {
217
- if (path) {
218
- path = this.trimPath(path)
219
-
220
- let pathSegments = path.split('/')
221
- const cleanedSegments = []
222
- pathSegments.forEach((segment) => {
223
- const slugifiedSegment = this.toSlug(segment)
224
- cleanedSegments.push(slugifiedSegment.trim())
225
- })
226
- path = cleanedSegments.join('/')
227
- }
228
- return path
229
- },
230
137
  }
231
138
 
232
139
  class KissPage {
@@ -331,8 +238,8 @@ class KissPage {
331
238
  conservativeCollapse: false,
332
239
  removeComments: true,
333
240
  removeEmptyAttributes: true,
334
- minifyCSS: true,
335
- minifyJS: true,
241
+ minifyCSS: !this._dev,
242
+ minifyJS: !this._dev,
336
243
  })
337
244
 
338
245
  fs.outputFile(this.buildTo, minifiedHtml, (err) => {
@@ -400,10 +307,12 @@ class Kiss {
400
307
  console.log(' Starting Kiss \n'.zebra)
401
308
  // Setup defaults
402
309
  let folders = {
310
+ root: './',
403
311
  src: './src',
404
312
  pages: './src/pages',
405
313
  build: './public',
406
314
  assets: './src/assets',
315
+ static: './src/static',
407
316
  layouts: './src/layouts',
408
317
  partials: './src/partials',
409
318
  models: './src/models',
@@ -415,17 +324,16 @@ class Kiss {
415
324
  if (this.verbose)
416
325
  console.log(`Setting base src folder to: ${config.folders.src}`.grey)
417
326
 
418
- folders = {
419
- src: config.folders.src,
420
- assets: `${config.folders.src}/assets`,
421
- layouts: `${config.folders.src}/layouts`,
422
- pages: `${config.folders.src}/pages`,
423
- partials: `${config.folders.src}/partials`,
424
- models: `${config.folders.src}/models`,
425
- controllers: `${config.folders.src}/controllers`,
426
- build: './public',
427
- }
327
+ folders.src = config.folders.src
328
+ folders.assets = `${config.folders.src}/assets`
329
+ folders.static = `${config.folders.src}/static`
330
+ folders.layouts = `${config.folders.src}/layouts`
331
+ folders.pages = `${config.folders.src}/pages`
332
+ folders.partials = `${config.folders.src}/partials`
333
+ folders.models = `${config.folders.src}/models`
334
+ folders.controllers = `${config.folders.src}/controllers`
428
335
  }
336
+
429
337
  folders = { ...folders, ...config.folders }
430
338
  this.config = {
431
339
  ...{
@@ -436,6 +344,7 @@ class Kiss {
436
344
  sass: {
437
345
  includePaths: [],
438
346
  },
347
+ port: 3001,
439
348
  },
440
349
  ...config,
441
350
  }
@@ -456,7 +365,7 @@ class Kiss {
456
365
  const kissServe = require('./kiss-serve')
457
366
  var publicDir = path.resolve(this.config.folders.build)
458
367
  try {
459
- kissServe(publicDir)
368
+ kissServe(publicDir, this.config.port)
460
369
  } catch (error) {
461
370
  console.error('Error running live reload server'.red)
462
371
  console.log(error.message)
@@ -518,10 +427,16 @@ class Kiss {
518
427
  let cssFile = sassFile.replace(sourceDir, targetDir)
519
428
  cssFile = cssFile.substr(0, cssFile.lastIndexOf('.'))
520
429
 
430
+ let outputStyle = 'expanded'
431
+ if (!this.config.dev) {
432
+ outputStyle = 'compressed'
433
+ }
434
+
521
435
  try {
522
436
  const sassOutput = sass.renderSync({
523
437
  file: sassFile,
524
438
  includePaths: this.config.sass.includePaths,
439
+ outputStyle: outputStyle,
525
440
  })
526
441
 
527
442
  fs.outputFile(`${cssFile}.css`, sassOutput.css, (err) => {
@@ -950,7 +865,7 @@ class Kiss {
950
865
  })
951
866
  }
952
867
  if (module.parent.filename) {
953
- console.log('Caller: '.cyan, module.parent.filename)
868
+ // console.log('Caller: '.cyan, module.parent.filename)
954
869
  chokidar.watch(module.parent.filename).on('change', (path, stats) => {
955
870
  console.log(`Changed: ${path}: `.cyan)
956
871
  rebuildSite()
@@ -0,0 +1,114 @@
1
+ {{#script-bundler}}
2
+ <p>not rendered</p>
3
+ <script src='~~/node_modules/highlight.js/lib/highlight.js'></script>
4
+ <script src='~/assets/js/sub/script2.js'></script>
5
+ <script src="script3.js"></script>
6
+ <script src="/js/script1.js"></script>
7
+ {{/script-bundler}}
8
+
9
+ const { minify } = require('terser')
10
+
11
+
12
+ handlebars.registerHelper('script-bundler', function (context, options) {
13
+ // const returnLines = ['<!--Dev Script Output-->']
14
+ // const scripts = {}
15
+ // // let scriptFolder = ''
16
+
17
+ // context
18
+ // .fn(this)
19
+ // .split(/\r?\n/)
20
+ // .filter((line) => line.includes('src'))
21
+ // .forEach((line) => {
22
+ // let script = line.substring(line.search(/src=[',\"]/) + 5, line.length)
23
+ // script = script.substring(0, script.search(/[',\"]/))
24
+ // // scriptFolder = script.substring(0, script.lastIndexOf('/'))
25
+ // const scriptPath = utils.resolve.alias(script, config)
26
+ // const fullScriptPath = path.join(process.cwd(), scriptPath)
27
+
28
+ // try {
29
+ // if (fs.existsSync(fullScriptPath)) {
30
+ // scripts[script] = fs.readFileSync(fullScriptPath, 'utf8')
31
+
32
+ // // Root Dir
33
+ // console.log('script', script)
34
+ // if (script.startsWith('~~/')) {
35
+ // const rootScriptPath = `${config.folders.root}/${script.substring(
36
+ // 3,
37
+ // script.length
38
+ // )}`
39
+
40
+ // try {
41
+ // const rootPubPath = 'kiss'
42
+ // const rootScript = rootScriptPath.substr(
43
+ // rootScriptPath.lastIndexOf('/') + 1,
44
+ // rootScriptPath.length
45
+ // )
46
+
47
+ // fs.ensureDirSync(`${config.folders.build}/${rootPubPath}`)
48
+ // fs.copyFileSync(
49
+ // rootScriptPath,
50
+ // `${config.folders.build}/${rootPubPath}/${rootScript}`
51
+ // )
52
+
53
+ // script = `/${rootPubPath}/${rootScript}`
54
+ // } catch (error) {
55
+ // console.error('Error copying root script in bundler'.red)
56
+ // console.error(error.message)
57
+ // }
58
+ // }
59
+
60
+ // returnLines.push(
61
+ // `<script src='${utils.resolve.deployAlias(
62
+ // script,
63
+ // config
64
+ // )}'></script>`
65
+ // )
66
+ // } else {
67
+ // console.error(`404: ${fullScriptPath}`.red)
68
+ // }
69
+ // } catch (err) {
70
+ // console.error(err.yellow)
71
+ // }
72
+ // })
73
+
74
+ // const genRandomHex = (size) =>
75
+ // [...Array(size)]
76
+ // .map(() => Math.floor(Math.random() * 16).toString(16))
77
+ // .join('')
78
+
79
+ // // const scriptPath = `${scriptFolder}/bundle-${genRandomHex(12)}.js`
80
+ // const scriptPath = `/kiss/bundle-${genRandomHex(12)}.js`
81
+
82
+ // if (config.dev) {
83
+ // return returnLines.join('\n')
84
+ // } else {
85
+ // console.log('Compressing scripts to:'.grey, scriptPath.green)
86
+ // minify(scripts, {
87
+ // output: {
88
+ // comments: false,
89
+ // },
90
+ // compress: {
91
+ // typeofs: false,
92
+ // },
93
+ // sourceMap: false,
94
+ // })
95
+ // .then((compressedScripts) => {
96
+ // fs.ensureDirSync(
97
+ // `${config.folders.build}/${scriptPath.substring(
98
+ // 0,
99
+ // scriptPath.lastIndexOf('/')
100
+ // )}`
101
+ // )
102
+ // fs.writeFileSync(
103
+ // `${config.folders.build}/${scriptPath}`,
104
+ // compressedScripts.code,
105
+ // 'utf8'
106
+ // )
107
+ // })
108
+ // .catch((error) => {
109
+ // console.error('Error compressing scripts'.red)
110
+ // console.error(color.yellow(error.message))
111
+ // })
112
+ // return `<script src='${scriptPath}'></script>`
113
+ // }
114
+ // })
@@ -0,0 +1,15 @@
1
+ // handlebars.registerHelper('isDev', function (options) {
2
+ // if (config.dev) {
3
+ // return options.fn(this)
4
+ // } else {
5
+ // return options.inverse(this)
6
+ // }
7
+ // })
8
+
9
+ // handlebars.registerHelper('helperMissing', function () {
10
+ // var options = arguments[arguments.length - 1]
11
+ // var args = Array.prototype.slice.call(arguments, 0, arguments.length - 1)
12
+ // return new handlebars.SafeString(
13
+ // `<!-- Missing: ${options.name} (${args}) -->`
14
+ // )
15
+ // })
package/libs/utils.js ADDED
@@ -0,0 +1,83 @@
1
+ const utils = {
2
+ trimLines(lines) {
3
+ let text = ''
4
+ lines.split('\n').forEach((line) => {
5
+ text = text + line.trim() + '\n'
6
+ })
7
+ return text
8
+ },
9
+ toSlug(slug) {
10
+ return slug
11
+ .toLowerCase()
12
+ .trim()
13
+ .replace(/[\W_]+/g, '-')
14
+ },
15
+ toTitleCase(str) {
16
+ return str
17
+ .toLowerCase()
18
+ .split(' ')
19
+ .map(function (word) {
20
+ return word.charAt(0).toUpperCase() + word.slice(1)
21
+ })
22
+ .join(' ')
23
+ },
24
+ trimPath(path) {
25
+ if (path.startsWith('/')) path = path.substring(1, path.length)
26
+ if (path.endsWith('/')) path = path.substring(0, path.length - 1)
27
+ return path
28
+ },
29
+ sanitizePath(path) {
30
+ if (path) {
31
+ path = this.trimPath(path)
32
+
33
+ let pathSegments = path.split('/')
34
+ const cleanedSegments = []
35
+ pathSegments.forEach((segment) => {
36
+ const slugifiedSegment = this.toSlug(segment)
37
+ cleanedSegments.push(slugifiedSegment.trim())
38
+ })
39
+ path = cleanedSegments.join('/')
40
+ }
41
+ return path
42
+ },
43
+ resolve: {
44
+ alias: function (path, config) {
45
+ // console.log('Resolving Alias for: ', path)
46
+ // Root Dir
47
+ if (path.startsWith('~~/')) {
48
+ return `${config.folders.root}/${path.substring(3, path.length)}`
49
+ }
50
+ // Assets Dir
51
+ if (path.startsWith('~/assets')) {
52
+ return `${config.folders.assets}/${path.substring(8, path.length)}`
53
+ }
54
+ // Src Dir
55
+ if (path.startsWith('~/')) {
56
+ return `${config.folders.src}/${path.substring(2, path.length)}`
57
+ }
58
+
59
+ return `${config.folders.assets}/${utils.stripStartingSlash(path)}`
60
+ },
61
+ deployAlias: function (path, config) {
62
+ // Assets Dir
63
+ if (path.startsWith('~/assets')) {
64
+ return `${path.substring(8, path.length)}`
65
+ }
66
+ // Src Dir
67
+ if (path.startsWith('~/')) {
68
+ return `/${path.substring(2, path.length)}`
69
+ }
70
+ // console.log('No match for', path)
71
+ return path
72
+ },
73
+ },
74
+ stripStartingSlash: function (path) {
75
+ if (path.startsWith('/')) {
76
+ path = path.substring(1, path.length)
77
+ path = utils.stripStartingSlash(path)
78
+ }
79
+ return path
80
+ },
81
+ }
82
+
83
+ module.exports = utils
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiss-ssg",
3
- "version": "1.3.0",
3
+ "version": "1.4.4",
4
4
  "description": "Simple Static Website Generator",
5
5
  "main": "kiss-ssg.js",
6
6
  "scripts": {
@@ -36,8 +36,7 @@
36
36
  "pretty": "^2.0.0",
37
37
  "remarkable": "^2.0.1",
38
38
  "sass": "^1.32.8",
39
- "serve-static": "^1.14.1",
40
- "terser": "^5.6.0"
39
+ "serve-static": "^1.14.1"
41
40
  },
42
41
  "devDependencies": {
43
42
  "eslint-config-prettier": "^6.15.0",