poops 1.0.10 → 1.0.12

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.
@@ -1,4 +1,4 @@
1
- /* poops v1.0.10 | https://github.com/stamat/poops | MIT License */
1
+ /* poops v1.0.12 | https://github.com/stamat/poops | MIT License */
2
2
  @charset "UTF-8";
3
3
  /*! Sulphuris 🜍 1.0.4 */
4
4
  .border, .border-y, .border-x, .border-r, .border-l, .border-b, .border-t {
@@ -1,4 +1,4 @@
1
- /* poops v1.0.10 | https://github.com/stamat/poops | MIT License */
1
+ /* poops v1.0.12 | https://github.com/stamat/poops | MIT License */
2
2
  @charset "UTF-8";
3
3
  /*! Sulphuris 🜍 1.0.4 */.border,.border-b,.border-l,.border-r,.border-t,.border-x,.border-y{border:1px solid}.border-t{border-bottom:none}.border-b,.border-t{border-left:none;border-right:none}.border-b{border-top:none}.border-l{border-right:none}.border-l,.border-r{border-bottom:none;border-top:none}.border-r{border-left:none}.border-x{border-bottom:none;border-top:none}.border-y{border-left:none;border-right:none}.border-2{border-width:2px}.border-3{border-width:3px}.border-4{border-width:4px}.border-6{border-width:6px}.border-8{border-width:8px}@media only screen and (min-width:421px){.border-sm-2{border-width:2px}.border-sm-3{border-width:3px}.border-sm-4{border-width:4px}.border-sm-6{border-width:6px}.border-sm-8{border-width:8px}}@media only screen and (min-width:768px){.border-md-2{border-width:2px}.border-md-3{border-width:3px}.border-md-4{border-width:4px}.border-md-6{border-width:6px}.border-md-8{border-width:8px}}@media only screen and (min-width:1024px){.border-lg-2{border-width:2px}.border-lg-3{border-width:3px}.border-lg-4{border-width:4px}.border-lg-6{border-width:6px}.border-lg-8{border-width:8px}}@media only screen and (min-width:1366px){.border-xl-2{border-width:2px}.border-xl-3{border-width:3px}.border-xl-4{border-width:4px}.border-xl-6{border-width:6px}.border-xl-8{border-width:8px}}@media only screen and (min-width:1680px){.border-xxl-2{border-width:2px}.border-xxl-3{border-width:3px}.border-xxl-4{border-width:4px}.border-xxl-6{border-width:6px}.border-xxl-8{border-width:8px}}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-dotted{border-style:dotted}.border-0{border:0}.border-t-0{border-top:0}.border-r-0{border-right:0}.border-b-0{border-bottom:0}.border-l-0,.border-x-0{border-left:0}.border-x-0{border-right:0}.border-y-0{border-bottom:0;border-top:0}@media only screen and (min-width:421px){.border-sm-0{border:0}.border-t-sm-0{border-top:0}.border-r-sm-0{border-right:0}.border-b-sm-0{border-bottom:0}.border-l-sm-0{border-left:0}.border-x-sm-0{border-left:0;border-right:0}.border-y-sm-0{border-bottom:0;border-top:0}}@media only screen and (min-width:768px){.border-md-0{border:0}.border-t-md-0{border-top:0}.border-r-md-0{border-right:0}.border-b-md-0{border-bottom:0}.border-l-md-0{border-left:0}.border-x-md-0{border-left:0;border-right:0}.border-y-md-0{border-bottom:0;border-top:0}}@media only screen and (min-width:1024px){.border-lg-0{border:0}.border-t-lg-0{border-top:0}.border-r-lg-0{border-right:0}.border-b-lg-0{border-bottom:0}.border-l-lg-0{border-left:0}.border-x-lg-0{border-left:0;border-right:0}.border-y-lg-0{border-bottom:0;border-top:0}}@media only screen and (min-width:1366px){.border-xl-0{border:0}.border-t-xl-0{border-top:0}.border-r-xl-0{border-right:0}.border-b-xl-0{border-bottom:0}.border-l-xl-0{border-left:0}.border-x-xl-0{border-left:0;border-right:0}.border-y-xl-0{border-bottom:0;border-top:0}}@media only screen and (min-width:1680px){.border-xxl-0{border:0}.border-t-xxl-0{border-top:0}.border-r-xxl-0{border-right:0}.border-b-xxl-0{border-bottom:0}.border-l-xxl-0{border-left:0}.border-x-xxl-0{border-left:0;border-right:0}.border-y-xxl-0{border-bottom:0;border-top:0}}.round{border-radius:50%}.round,[class*=rounded-]{overflow:hidden}.rounded-fix{-webkit-mask-image:-webkit-radial-gradient(#fff,#000)}.rounded-0{border-radius:0}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-16{border-radius:16px}.rounded-24{border-radius:24px}.rounded-32{border-radius:32px}.rounded-tl-0{border-top-left-radius:0}.rounded-t-0,.rounded-tr-0{border-top-right-radius:0}.rounded-t-0{border-top-left-radius:0}.rounded-r-0{border-bottom-right-radius:0;border-top-right-radius:0}.rounded-bl-0{border-bottom-left-radius:0}.rounded-b-0,.rounded-br-0{border-bottom-right-radius:0}.rounded-b-0,.rounded-l-0{border-bottom-left-radius:0}.rounded-l-0{border-top-left-radius:0}.btn,button.reset{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:inherit;margin:0;padding:0;text-decoration:none}.btn{background-color:#f6c026;border-radius:4px;color:#fff;cursor:pointer;display:inline-flex;justify-content:center;min-height:56px;padding:16px 32px;transition:color .25s cubic-bezier(.86,0,.07,1),background .25s cubic-bezier(.86,0,.07,1)}@media only screen and (min-width:1024px){.btn:hover{background-color:#1a1a1d}}.btn-inverted{background-color:#1a1a1d}@media only screen and (min-width:1024px){.btn-inverted:hover{background-color:#f6c026}}.btn-outline{background:transparent;border:2px solid #1a1a1d;color:#1a1a1d}@media only screen and (min-width:1024px){.btn-outline:hover{background-color:#1a1a1d;color:#fff}}.btn-outline.btn-inverted{border-color:#fff;color:#fff}@media only screen and (min-width:1024px){.btn-outline.btn-inverted:hover{background-color:#fff;color:#1a1a1d}}.text-black{color:#1a1a1d}.text-white{color:#fff}.text-primary{color:#f6c026}.text-gray-900{color:#323237}.text-gray-800{color:#494952}.text-gray-700{color:#61616c}.text-gray-600{color:#797986}.text-gray-500{color:#93939e}.text-gray-400{color:#adadb6}.text-gray-300{color:#c8c8cd}.text-gray-200{color:#e2e2e5}.text-gray-100{color:#fcfcfd}.text-transparent{color:transparent}.bg-black{background-color:#1a1a1d}.bg-white{background-color:#fff}.bg-primary{background-color:#f6c026}.bg-gray-900{background-color:#323237}.bg-gray-800{background-color:#494952}.bg-gray-700{background-color:#61616c}.bg-gray-600{background-color:#797986}.bg-gray-500{background-color:#93939e}.bg-gray-400{background-color:#adadb6}.bg-gray-300{background-color:#c8c8cd}.bg-gray-200{background-color:#e2e2e5}.bg-gray-100{background-color:#fcfcfd}.border-black{border-color:#1a1a1d}.border-white{border-color:#fff}.border-primary{border-color:#f6c026}.border-gray-900{border-color:#323237}.border-gray-800{border-color:#494952}.border-gray-700{border-color:#61616c}.border-gray-600{border-color:#797986}.border-gray-500{border-color:#93939e}.border-gray-400{border-color:#adadb6}.border-gray-300{border-color:#c8c8cd}.border-gray-200{border-color:#e2e2e5}.border-gray-100{border-color:#fcfcfd}ol.reset,ul.reset{list-style:none;margin:0;padding:0;text-indent:0}html{font-size:16px;line-height:1.2}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#1a1a1d;font-family:Nunito,sans-serif}.h1,h1{font-size:4rem;font-weight:700;letter-spacing:-.03125rem;line-height:1}@media only screen and (min-width:1024px){.h1,h1{font-size:6rem;font-weight:700;letter-spacing:-.09375rem;line-height:1}}.h2,h2{font-size:3rem;font-weight:700;letter-spacing:0;line-height:1}@media only screen and (min-width:1024px){.h2,h2{font-size:4rem;font-weight:700;letter-spacing:-.03125rem;line-height:1}}.h3,h3{font-size:2rem;font-weight:700;letter-spacing:.015625rem;line-height:1}@media only screen and (min-width:1024px){.h3,h3{font-size:3rem;font-weight:700;letter-spacing:0;line-height:1}}.h4,h4{font-size:1.5rem;font-weight:700;letter-spacing:0;line-height:1}@media only screen and (min-width:1024px){.h4,h4{font-size:2rem;font-weight:700;letter-spacing:.015625rem;line-height:1}}.h5,h5{font-size:1.25rem;font-weight:700;letter-spacing:.009375rem;line-height:1}@media only screen and (min-width:1024px){.h5,h5{font-size:1.5rem;font-weight:700;letter-spacing:0;line-height:1}}.h6,h6{font-size:1rem;font-weight:700;letter-spacing:.009375rem;line-height:1}@media only screen and (min-width:1024px){.h6,h6{font-size:1.25rem;font-weight:700;letter-spacing:.009375rem;line-height:1}}.p1{font-size:1.5rem;letter-spacing:.01875rem;line-height:1.5}.p2{font-size:1.25rem}.p2,p{letter-spacing:.0125rem;line-height:1.5}p{font-size:1rem}.p3,figcaption{font-size:.875rem;letter-spacing:.025rem;line-height:1.5}.p4,small{font-size:.75rem;letter-spacing:.0375rem;line-height:1.5}.supertitle{font-size:.875rem;font-weight:500;letter-spacing:.125rem;line-height:1.5;text-transform:uppercase}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif}.font-paragraph{font-family:Nunito,sans-serif!important}.font-heading{font-family:Roboto,sans-serif!important}.font-mono{font-family:monospace!important}.text-thin{font-weight:100!important}.text-ultra-light{font-weight:200!important}.text-light{font-weight:300!important}.text-normal{font-weight:400!important}.text-bold{font-weight:700!important}.text-bolder{font-weight:bolder!important}.text-lighter{font-weight:lighter!important}.text-medium{font-weight:500!important}.text-semi-bold{font-weight:600!important}.text-ultra-bold{font-weight:800!important}.text-heavy{font-weight:900!important}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}@media only screen and (min-width:421px){.text-sm-left{text-align:left}.text-sm-right{text-align:right}.text-sm-center{text-align:center}}@media only screen and (min-width:768px){.text-md-left{text-align:left}.text-md-right{text-align:right}.text-md-center{text-align:center}}@media only screen and (min-width:1024px){.text-lg-left{text-align:left}.text-lg-right{text-align:right}.text-lg-center{text-align:center}}@media only screen and (min-width:1366px){.text-xl-left{text-align:left}.text-xl-right{text-align:right}.text-xl-center{text-align:center}}@media only screen and (min-width:1680px){.text-xxl-left{text-align:left}.text-xxl-right{text-align:right}.text-xxl-center{text-align:center}}.text-italic{font-style:italic}.text-underline{text-decoration:underline}.text-overline{text-decoration:overline}.text-line-through{text-decoration:line-through}.text-none{text-decoration:none}@media only screen and (min-width:421px){.text-sm-underline{text-decoration:underline}.text-sm-overline{text-decoration:overline}.text-sm-line-through{text-decoration:line-through}.text-sm-none{text-decoration:none}}@media only screen and (min-width:768px){.text-md-underline{text-decoration:underline}.text-md-overline{text-decoration:overline}.text-md-line-through{text-decoration:line-through}.text-md-none{text-decoration:none}}@media only screen and (min-width:1024px){.text-lg-underline{text-decoration:underline}.text-lg-overline{text-decoration:overline}.text-lg-line-through{text-decoration:line-through}.text-lg-none{text-decoration:none}}@media only screen and (min-width:1366px){.text-xl-underline{text-decoration:underline}.text-xl-overline{text-decoration:overline}.text-xl-line-through{text-decoration:line-through}.text-xl-none{text-decoration:none}}@media only screen and (min-width:1680px){.text-xxl-underline{text-decoration:underline}.text-xxl-overline{text-decoration:overline}.text-xxl-line-through{text-decoration:line-through}.text-xxl-none{text-decoration:none}}.text-uppercase{text-transform:uppercase}.text-lowercase{text-transform:lowercase}.text-capitalize{text-transform:capitalize}.text-full-width{text-transform:full-width}@media only screen and (min-width:421px){.text-sm-uppercase{text-transform:uppercase}.text-sm-lowercase{text-transform:lowercase}.text-sm-capitalize{text-transform:capitalize}.text-sm-full-width{text-transform:full-width}}@media only screen and (min-width:768px){.text-md-uppercase{text-transform:uppercase}.text-md-lowercase{text-transform:lowercase}.text-md-capitalize{text-transform:capitalize}.text-md-full-width{text-transform:full-width}}@media only screen and (min-width:1024px){.text-lg-uppercase{text-transform:uppercase}.text-lg-lowercase{text-transform:lowercase}.text-lg-capitalize{text-transform:capitalize}.text-lg-full-width{text-transform:full-width}}@media only screen and (min-width:1366px){.text-xl-uppercase{text-transform:uppercase}.text-xl-lowercase{text-transform:lowercase}.text-xl-capitalize{text-transform:capitalize}.text-xl-full-width{text-transform:full-width}}@media only screen and (min-width:1680px){.text-xxl-uppercase{text-transform:uppercase}.text-xxl-lowercase{text-transform:lowercase}.text-xxl-capitalize{text-transform:capitalize}.text-xxl-full-width{text-transform:full-width}}h1{margin-bottom:.33em}h2{margin-bottom:.42em}h3{margin-bottom:.5em}h4{margin-bottom:.65em}h5{margin-bottom:.8em}h6{margin-bottom:1em}.text-nowrap{white-space:nowrap}*{box-sizing:border-box}.content-box{box-sizing:content-box}@media screen and (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}[hidden]{display:none!important}.smooth-touch{-webkit-overflow-scrolling:touch}.cover{height:100%;left:0;top:0;width:100%}.absolute-center,.self-center{transform:translate3d(-50%,-50%,0)}.self-center-vertical{transform:translateY(-50%)}.self-center-horizontal{transform:translateX(-50%)}.absolute-center{left:50%;position:absolute;top:50%}.bg-cover{background-size:cover}.bg-contain,.bg-cover{background-position:50%;background-repeat:no-repeat}.bg-contain{background-size:contain}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.hide-native-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.hide-native-scrollbar::-webkit-scrollbar{display:none}.spacer{display:block;height:auto!important;visibility:hidden;width:100%!important}.events-none,.spacer{pointer-events:none}
4
4
 
@@ -1,4 +1,4 @@
1
- /* poops v1.0.10 | https://github.com/stamat/poops | MIT License */
1
+ /* poops v1.0.12 | https://github.com/stamat/poops | MIT License */
2
2
  "use strict";
3
3
  (() => {
4
4
  // example/src/js/scripts/utils.ts
@@ -1,2 +1,2 @@
1
- /* poops v1.0.10 | https://github.com/stamat/poops | MIT License */
1
+ /* poops v1.0.12 | https://github.com/stamat/poops | MIT License */
2
2
  "use strict";(()=>{var e;new class{constructor(e,t){this.name=e,this.age=t}greet(){console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`)}}("Stamat",(new Date).getFullYear()-1988).greet(),console.log((e="hello").charAt(0).toUpperCase()+e.slice(1)),console.log([1,2,3,4,5].reduce(((e,t)=>e+t),0));var t,a=new Date;console.log(`${(t=a).getFullYear()}-${`${t.getMonth()+1}`.padStart(2,"0")}-${`${t.getDate()}`.padStart(2,"0")}`)})();
@@ -17,10 +17,12 @@
17
17
  <body>
18
18
  {% block content %} {% endblock %}
19
19
 
20
+ {% if livereload_port %}
20
21
  <script>document.write('<script src="http://'
21
22
  + (location.host || 'localhost').split(':')[0]
22
- + ':35729/livereload.js?snipver=1"></'
23
+ + ':{{livereload_port}}/livereload.js?snipver=1"></'
23
24
  + 'script>')</script>
25
+ {% endif %}
24
26
 
25
27
  <script type="text/javascript">
26
28
  var poop = document.getElementById('poop');
package/index.html CHANGED
@@ -17,7 +17,7 @@
17
17
  <body>
18
18
 
19
19
  <header class="mt-32 container text-center">
20
- <h1><span id="poop"><img src="poop.png" alt="💩" width="160" height="160" class="d-block"></span><br>POOPS v1.0.10</h1>
20
+ <h1><span id="poop"><img src="poop.png" alt="💩" width="160" height="160" class="d-block"></span><br>POOPS v1.0.12</h1>
21
21
  <a href="https://www.npmjs.com/package/poops"><img src="https://img.shields.io/badge/npm-CB3837.svg?style=for-the-badge&logo=npm&logoColor=white" alt="npm"></a> <a href="https://github.com/stamat/poops"><img src="https://img.shields.io/badge/GitHub-181717.svg?style=for-the-badge&logo=GitHub&logoColor=white" alt="github"></a>
22
22
  <p class="p2">Straightforward, no-bullshit bundler for the web.</p>
23
23
 
@@ -71,10 +71,12 @@
71
71
  </div>
72
72
 
73
73
 
74
+
74
75
  <script>document.write('<script src="http://'
75
76
  + (location.host || 'localhost').split(':')[0]
76
- + ':35729/livereload.js?snipver=1"></'
77
+ + ':35730/livereload.js?snipver=1"></'
77
78
  + 'script>')</script>
79
+
78
80
 
79
81
  <script type="text/javascript">
80
82
  var poop = document.getElementById('poop');
package/lib/markups.js CHANGED
@@ -76,6 +76,10 @@ module.exports = class Markups {
76
76
  this.nunjucksEnv.addGlobal('site', this.config.markup.site)
77
77
  }
78
78
 
79
+ if (this.config.livereload_port) {
80
+ this.nunjucksEnv.addGlobal('livereload_port', this.config.livereload_port)
81
+ }
82
+
79
83
  this.loadDataFiles(this.config.markup.data)
80
84
 
81
85
  this.payload = {} // TODO: still not used. This is where we can store data from data files. Can be used to pass front matter data or even a way to pass data from files to templates
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "poops",
3
3
  "description": "Straightforward, no-bullshit bundler for the web.",
4
- "version": "1.0.10",
4
+ "version": "1.0.12",
5
5
  "license": "MIT",
6
6
  "main": "poops.js",
7
7
  "repository": "https://github.com/stamat/poops.git",
@@ -35,6 +35,7 @@
35
35
  "glob": "^10.3.1",
36
36
  "livereload": "^0.9.3",
37
37
  "nunjucks": "^3.2.4",
38
+ "portscanner": "^2.2.0",
38
39
  "postcss": "^8.4.24",
39
40
  "sass": "^1.63.4",
40
41
  "serve-static": "^1.15.0",
@@ -49,4 +50,4 @@
49
50
  "eslint-plugin-promise": "^6.1.1",
50
51
  "sulphuris": "^1.0.5"
51
52
  }
52
- }
53
+ }
package/poops.js CHANGED
@@ -11,6 +11,7 @@ const serveStatic = require('serve-static')
11
11
  const Scripts = require('./lib/scripts.js')
12
12
  const PrintStyle = require('./lib/utils/print-style.js')
13
13
  const Styles = require('./lib/styles.js')
14
+ const portscanner = require('portscanner')
14
15
 
15
16
  const { pathExists } = helpers
16
17
 
@@ -19,17 +20,94 @@ const pkg = require('./package.json')
19
20
  const args = process.argv.slice(2)
20
21
  const pstyle = new PrintStyle()
21
22
 
23
+ let build = false
22
24
  let defaultConfigPath = 'poops.json'
23
- if (args.length) defaultConfigPath = args[0]
25
+ let overridePort = null
26
+ let overrideLivereloadPort = null
27
+
28
+ for (let i = 0; i < args.length; i++) {
29
+ const arg = args[i]
30
+ switch (arg) {
31
+ case '-b':
32
+ case '--build':
33
+ build = true
34
+ break
35
+ case '-c':
36
+ case '--config':
37
+ if (args.length === i + 1 || args[i + 1].startsWith('-')) {
38
+ console.log(`${pstyle.redBright + pstyle.bold}[error]${pstyle.reset} Missing config file path`)
39
+ process.exit(1)
40
+ }
41
+ defaultConfigPath = args[i + 1]
42
+ i++
43
+ break
44
+ case '-p':
45
+ case '--port':
46
+ if (args.length === i + 1 || args[i + 1].startsWith('-') || isNaN(args[i + 1])) {
47
+ console.log(`${pstyle.redBright + pstyle.bold}[error]${pstyle.reset} Missing port number`)
48
+ process.exit(1)
49
+ }
50
+ overridePort = args[i + 1]
51
+ i++
52
+ break
53
+ case '-l':
54
+ case '--livereload':
55
+ if (args.length === i + 1 || args[i + 1].startsWith('-') || isNaN(args[i + 1])) {
56
+ console.log(`${pstyle.redBright + pstyle.bold}[error]${pstyle.reset} Missing livereload port number`)
57
+ process.exit(1)
58
+ }
59
+ overrideLivereloadPort = args[i + 1]
60
+ i++
61
+ break
62
+ case '-v':
63
+ case '--version':
64
+ console.log(pkg.version)
65
+ process.exit(0)
66
+ break
67
+ case '-h':
68
+ case '--help':
69
+ console.log(`Usage: ${pkg.name} [config-file] [options]
70
+ -b, --build\t\tBuild the project and exit
71
+ -c, --config\t\tSpecify the config file
72
+ -h, --help\t\tShow this help message
73
+ -l, --livereload\t\tSpecify the port to use for the livereload server, overrides the config file
74
+ -p, --port\t\tSpecify the port to use for the server, overrides the config file
75
+ -v, --version\t\tShow version number`)
76
+ process.exit(0)
77
+ break
78
+ default:
79
+ if (arg.startsWith('-')) {
80
+ console.log(`Unknown option: ${arg}`)
81
+ process.exit(1)
82
+ } else {
83
+ defaultConfigPath = arg
84
+ }
85
+ }
86
+ }
87
+
24
88
  let configPath = path.join(cwd, defaultConfigPath)
25
89
  if (!args.length && !pathExists(configPath)) configPath = path.join(cwd, '💩.json')
26
90
 
27
91
  // Main function 💩
28
92
  async function poops() {
93
+ let lport
94
+ if (config.livereload) {
95
+ lport = overrideLivereloadPort || config.livereload.port || 35729
96
+ if (!overrideLivereloadPort) lport = await getAvailablePort(lport, lport + 10)
97
+ config.livereload_port = lport
98
+ }
99
+
29
100
  const styles = new Styles(config)
30
101
  const scripts = new Scripts(config)
31
102
  const markups = new Markups(config)
32
103
 
104
+ if (build || (!config.watch && !config.livereload && !config.serve)) {
105
+ await styles.compile()
106
+ await scripts.compile()
107
+ await markups.compile()
108
+ process.exit(0)
109
+ }
110
+
33
111
  if (config.livereload) {
34
112
  const lrExcludes = ['.git', '.svn', '.hg']
35
113
 
@@ -47,7 +125,7 @@ async function poops() {
47
125
 
48
126
  const lrserver = livereload.createServer({
49
127
  exclusions: [...new Set(lrExcludes)],
50
- port: config.livereload.port || 35729
128
+ port: lport
51
129
  })
52
130
  console.log(`${pstyle.blue + pstyle.bold}[info]${pstyle.reset} ${pstyle.dim}🔃 LiveReload server:${pstyle.reset} ${pstyle.italic + pstyle.underline}http://localhost:${lrserver.config.port}${pstyle.reset}`)
53
131
  lrserver.watch(cwd)
@@ -73,15 +151,12 @@ async function poops() {
73
151
  }
74
152
  })
75
153
  }
76
-
77
- if (!config.watch && !config.livereload && !config.serve) {
78
- process.exit(1)
79
- }
80
154
  }
81
155
 
82
156
  // CLI Header
83
- console.log(`\n${pstyle.color('#8b4513')}💩 Poops — v${pkg.version}
84
- ----------------${pstyle.reset + pstyle.bell}\n`)
157
+ const title = `💩 Poops — v${pkg.version}`
158
+ console.log(`\n${pstyle.color('#8b4513')}${title}
159
+ ${title.replace(/./g, '-')}${pstyle.reset + pstyle.bell}\n`)
85
160
 
86
161
  // Check if poops.json exists
87
162
  if (!pathExists(configPath)) {
@@ -105,8 +180,19 @@ if (config.includePaths) {
105
180
  config.includePaths = ['node_modules']
106
181
  }
107
182
 
108
- // Start the webserver
109
- if (config.serve) {
183
+ async function getAvailablePort(port, max) {
184
+ while (port < max) {
185
+ const status = await portscanner.checkPortStatus(port, 'localhost')
186
+ if (status === 'closed') {
187
+ return port
188
+ } else {
189
+ port++
190
+ }
191
+ }
192
+ return port
193
+ }
194
+
195
+ async function startServer() {
110
196
  const app = connect()
111
197
 
112
198
  if (config.serve.base && pathExists(cwd, config.serve.base)) {
@@ -115,11 +201,18 @@ if (config.serve) {
115
201
  app.use(serveStatic(cwd))
116
202
  }
117
203
 
118
- const port = config.serve.port ? parseInt(config.serve.port, 10) : 4040
119
- http.createServer(app).listen(port, () => {
204
+ let port = overridePort || config.serve.port || 4040
205
+ if (!overridePort) port = await getAvailablePort(port, port + 10)
206
+
207
+ http.createServer(app).listen(parseInt(port), () => {
120
208
  console.log(`${pstyle.blue + pstyle.bold}[info]${pstyle.reset} ${pstyle.dim}🌍 Local server:${pstyle.reset} ${pstyle.italic + pstyle.underline}http://localhost:${port}${pstyle.reset}`)
121
209
  poops()
122
210
  })
211
+ }
212
+
213
+ // Start the webserver
214
+ if (!build && config.serve) {
215
+ startServer()
123
216
  } else {
124
217
  poops()
125
218
  }
package/script/build ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ ./poops.js -b
package/script/publish ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * This script is used to publish a new version of the package.
5
+ * It can automatically increment the patch version if no version is specified in the package.json and commit the changes.
6
+ * It can also automatically tag and push the tags.
7
+ * Using GH CLI, it can also create a release.
8
+ *
9
+ * Fucking awesome, right?
10
+ *
11
+ * With love, @stamat
12
+ */
13
+ const readline = require('readline')
14
+ const { execSync } = require('child_process')
15
+ const fs = require('fs')
16
+ const path = require('path')
17
+ let version = process.argv[2]
18
+
19
+ const packageJson = require(path.join(process.cwd(), './package.json'))
20
+
21
+ if (!packageJson.version) {
22
+ console.log('No version found in package.json')
23
+ process.exit(1)
24
+ }
25
+
26
+ const rl = readline.createInterface({
27
+ input: process.stdin,
28
+ output: process.stdout
29
+ })
30
+
31
+ if (version && !isValidVersion(version)) {
32
+ console.log('Invalid version: ', version)
33
+ console.log('Current version: ', packageJson.version)
34
+ process.exit(1)
35
+ }
36
+
37
+ if (version && packageJson.version === version) {
38
+ console.log('Version is already ', version)
39
+ process.exit(1)
40
+ }
41
+
42
+ if (!version) {
43
+ console.log('Current version: ', packageJson.version)
44
+ version = incrementPatchVersion(packageJson.version)
45
+ rl.question(`Do you want to increment the version to ${version}? (y/n) `, (answer) => {
46
+ if (answer === 'y') {
47
+ publish(version)
48
+ } else {
49
+ console.log('Aborted')
50
+ process.exit(0)
51
+ }
52
+ rl.close()
53
+ })
54
+ } else {
55
+ publish(version)
56
+ }
57
+
58
+ function isValidVersion(version) {
59
+ return /^(\d+)\.(\d+)\.(\d+)(?:-([\w-]+(?:\.[\w-]+)*))?(?:\+([\w-]+(?:\.[\w-]+)*))?$/.test(version)
60
+ }
61
+
62
+ function incrementPatchVersion(version) {
63
+ const parts = version.split('.')
64
+ const patch = parseInt(parts[2]) + 1
65
+ return `${parts[0]}.${parts[1]}.${patch}`
66
+ }
67
+
68
+ function run(cmd, exitOnError = true) {
69
+ console.log(cmd)
70
+ try {
71
+ const out = execSync(cmd)
72
+ console.log(out.toString())
73
+ } catch (e) {
74
+ if (exitOnError) process.exit(1)
75
+ }
76
+ }
77
+
78
+ function publish(version) {
79
+ packageJson.version = version
80
+ fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2))
81
+
82
+ run('git add package.json')
83
+ run(`git commit -m "Bump version to ${version}"`)
84
+
85
+ if (fs.existsSync(path.join(process.cwd(), 'script/build'))) {
86
+ run('script/build')
87
+ execSync('git add .')
88
+ execSync(`git commit -m "Build version ${version}"`)
89
+ }
90
+
91
+ run(`git tag v${version}`)
92
+ run('git push')
93
+ run('git push --tags')
94
+
95
+ rl.question('Do you want to create a release on GitHub? (y/n) ', (answer) => {
96
+ if (answer === 'y') {
97
+ let notesArg = '--generate-notes'
98
+ rl.question('Enter notes for the release (optional): ', (notes) => {
99
+ if (notes.trim() !== '') {
100
+ notesArg = `--notes "${notes}"`
101
+ }
102
+ run(`gh release create v${version} --title "v${version}" ${notesArg} --latest`)
103
+ run('npm publish', true)
104
+ rl.close()
105
+ })
106
+ } else {
107
+ run('npm publish')
108
+ rl.close()
109
+ }
110
+ })
111
+ }
package/script/server ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ ./poops.js "$@"