Skip to content

Commit

Permalink
RELEASE: v2.36.1
Browse files Browse the repository at this point in the history
* Fixed an issue with the build system that was producing subtly broken builds.
  • Loading branch information
tmedwards authored Dec 22, 2021
2 parents 7d7c866 + a1251d8 commit 27903a8
Show file tree
Hide file tree
Showing 19 changed files with 5,513 additions and 5,791 deletions.
5 changes: 5 additions & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# WARNING: The `defaults` query must be explicitly spelled out or various
# plugins—e.g., `@babel/preset-env`—will not properly process the aggregate
# query.

> 1% or last 3 versions or last 10 Chrome versions or last 10 Firefox versions or IE >= 9 or Opera >= 12
4 changes: 2 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"parserOptions" : {
"ecmaVersion": 6
"ecmaVersion": 2021
},
"env" : {
"browser" : true,
"es6" : true,
"es2021" : true,
"jquery" : true
},
"globals": {
Expand Down
9 changes: 9 additions & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# JavaScript
**/*.js

# Vendored
vendor/

# Development
build/
node_modules/
17 changes: 17 additions & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"extends" : [
"stylelint-config-standard"
],
"reportNeedlessDisables" : true,
"rules" : {
"at-rule-no-unknown" : [true, { "ignoreAtRules": ["define-mixin", "mixin"] }],
"at-rule-empty-line-before" : null,
"comment-empty-line-before" : null,
"indentation" : "tab",
"linebreaks" : "unix",
"max-empty-lines" : 2,
"no-descending-specificity" : null,
"rule-empty-line-before" : null,
"selector-class-pattern" : "^([a-z][a-z0-9]*)(-[a-z0-9]+)*$"
}
}
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"editor.insertSpaces": false,
"css.validate": false
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ You may either download one of the precompiled packages from [SugarCube's websit

If you want to build SugarCube from scratch, rather than grabbing one of the pre-built packages off of its website, then these instructions are for you.

SugarCube uses Node.js as the core of its build system, so you'll need to install it if you don't already have it. Additionally, to retrieve SugarCube's source code from this repository, you'll need to install Git.
SugarCube uses Node.js (currently ≥v16) as the core of its build system, so you'll need to install it if you don't already have it. Additionally, to retrieve SugarCube's source code from this repository, you'll need to install Git.

1. [Download and install the Node.js JavaScript runtime (`https://nodejs.org/`)](https://nodejs.org/)
2. [Download and install the Git source control management tool (`https://git-scm.com/`)](https://git-scm.com/)
Expand Down Expand Up @@ -52,7 +52,7 @@ node build.js

Assuming that completed with no errors, the story format, in Twine 1 and Twine 2 flavors, should be output to the `dist` directory. Congratulations!

**NOTE:** SugarCube's development dependencies are occasionally updated. If you receive errors when attempting to build, then you probably need to update your cached dependencies. You may do this via the `npm update` command or, in extreme cases, by deleting the local `node_modules` directory and rerunning `npm install`.
**NOTE:** SugarCube's development dependencies are occasionally updated. If you receive errors when attempting to build, then you probably need to update your cached dependencies. You may do this via the `npm update` command or, in extreme cases, by running `npm uninstall` and `npm install` in order.

**TIP:** If you'd like additional options when building—e.g., debug builds, limiting the build to a particular version of Twine, etc.—then you may request help from `build.js` by specifying the help (`-h`, `--help`) option. For example:

Expand Down
8 changes: 0 additions & 8 deletions browserslist

This file was deleted.

200 changes: 102 additions & 98 deletions build.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
#!/usr/bin/env node
/***********************************************************************************************************************
build.js (v1.6.0, 2021-12-19)
build.js (v1.7.1, 2021-12-21)
A Node.js-hosted build script for SugarCube.
Copyright © 2013–2021 Thomas Michael Edwards <thomasmedwards@gmail.com>. All rights reserved.
Use of this source code is governed by a BSD 2-clause "Simplified" License, which may be found in the LICENSE file.
***********************************************************************************************************************/
/* eslint-env node, es6 */
/* eslint-env node, es2021 */
'use strict';


/*******************************************************************************
Configuration
*******************************************************************************/

const CONFIG = {
js : {
main : [
files : [
// The ordering herein is significant.
'src/lib/alert.js',
'src/lib/patterns.js',
Expand Down Expand Up @@ -67,20 +69,23 @@ const CONFIG = {
outro : 'src/templates/outro.js'
}
},
css : [
// The ordering herein is significant.
'src/vendor/normalize.css',
'src/css/init-screen.css',
'src/css/font.css',
'src/css/core.css',
'src/css/core-display.css',
'src/css/core-passage.css',
'src/css/core-macro.css',
'src/css/ui-dialog.css',
'src/css/ui.css',
'src/css/ui-bar.css',
'src/css/ui-debug.css'
],
css : {
mixins : 'src/css/_mixins.css',
files : [
// The ordering herein is significant.
'src/vendor/normalize.css',
'src/css/init-screen.css',
'src/css/font.css',
'src/css/core.css',
'src/css/core-display.css',
'src/css/core-passage.css',
'src/css/core-macro.css',
'src/css/ui-dialog.css',
'src/css/ui.css',
'src/css/ui-bar.css',
'src/css/ui-debug.css'
]
},
libs : [
// The ordering herein is significant.
'src/vendor/classList.min.js',
Expand Down Expand Up @@ -133,13 +138,12 @@ const CONFIG = {
/*******************************************************************************
Main Script
*******************************************************************************/
/*
NOTICE!

Where string replacements are done, we use the replacement function style here to
disable all special replacement patterns, since some of them likely exist within
the replacement strings (e.g. '$&' within the application source).
*/
// NOTICE!
//
// Where string replacements are done, we use the replacement function style to
// disable all special replacement patterns, since some of them may exist within
// the replacement strings—e.g., `$&` within the HTML or JavaScript sources.

const {
log,
Expand All @@ -156,21 +160,15 @@ const _opt = require('node-getopt').create([
['b', 'build=VERSION', 'Build only for Twine major version: 1 or 2; default: build for all.'],
['d', 'debug', 'Keep debugging code; gated by DEBUG symbol.'],
['u', 'unminified', 'Suppress minification stages.'],
['6', 'es6', 'Suppress JavaScript transpilation stages.'],
['n', 'no-transpile', 'Suppress JavaScript transpilation stages.'],
['h', 'help', 'Print this help, then exit.']
])
.bindHelp() // bind option 'help' to default action
.parseSystem(); // parse command line

// uglify-js (v2) does not currently support ES6, so force `unminified` when `es6` is enabled.
if (_opt.options.es6 && !_opt.options.unminified) {
_opt.options.unminified = true;
}
.bindHelp()
.parseSystem();

let _buildForTwine1 = true;
let _buildForTwine2 = true;

// build selection
if (_opt.options.build) {
switch (_opt.options.build) {
case '1':
Expand All @@ -187,8 +185,8 @@ if (_opt.options.build) {
}
}

// build the project
(() => {
// Build the project.
(async () => {
console.log('Starting builds...');

// Create the build ID file, if nonexistent.
Expand Down Expand Up @@ -226,9 +224,9 @@ if (_opt.options.build) {
projectBuild({
build : CONFIG.twine1.build,
version : version, // eslint-disable-line object-shorthand
libSource : assembleLibraries(CONFIG.libs), // combine the libraries
appSource : compileJavaScript(CONFIG.js, { twine1 : true }), // combine and minify the app JS
cssSource : compileStyles(CONFIG.css) // combine and minify the app CSS
libSource : assembleLibraries(CONFIG.libs), // combine the libraries
appSource : await compileJavaScript(CONFIG.js, { twine1 : true }), // combine and minify the app JS
cssSource : compileStyles(CONFIG.css) // combine and minify the app CSS
});

// Process the files that simply need copied into the build.
Expand All @@ -243,9 +241,9 @@ if (_opt.options.build) {
projectBuild({
build : CONFIG.twine2.build,
version : version, // eslint-disable-line object-shorthand
libSource : assembleLibraries(CONFIG.libs), // combine the libraries
appSource : compileJavaScript(CONFIG.js, { twine1 : false }), // combine and minify the app JS
cssSource : compileStyles(CONFIG.css), // combine and minify the app CSS
libSource : assembleLibraries(CONFIG.libs), // combine the libraries
appSource : await compileJavaScript(CONFIG.js, { twine1 : false }), // combine and minify the app JS
cssSource : compileStyles(CONFIG.css), // combine and minify the app CSS

postProcess(sourceString) {
// Load the output format.
Expand Down Expand Up @@ -274,10 +272,9 @@ if (_opt.options.build) {

// Update the build ID.
writeFileContents('.build', String(version.build));
})();

// That's all folks!
console.log('\nBuilds complete! (check the "build" directory)');
})()
.then(() => console.log('\nBuilds complete! (check the "build" directory)'))
.catch(reason => console.log('\nERROR:', reason));


/*******************************************************************************
Expand All @@ -290,86 +287,92 @@ function assembleLibraries(filenames) {
}

function compileJavaScript(filenameObj, options) {
/* eslint-disable camelcase, prefer-template */
log('compiling JavaScript...');

const babelCore = require('babel-core');
const babelOpts = {
code : true,
compact : false,
presets : ['env'],
filename : 'sugarcube.js'
};

// Join the files and transpile (ES6 → ES5) with Babel.
let jsSource = concatFiles(filenameObj.main);
jsSource = readFileContents(filenameObj.wrap.intro)
+ '\n'
+ (_opt.options.es6 ? jsSource : babelCore.transform(jsSource, babelOpts).code)
+ '\n'
+ readFileContents(filenameObj.wrap.outro);

if (_opt.options.unminified) {
return [
'window.TWINE1=' + String(!!options.twine1),
'window.DEBUG=' + String(_opt.options.debug || false)
].join(';\n') + ';\n' + jsSource;
// Join the files.
let bundle = concatFiles(filenameObj.files);

// Transpile to ES5 with Babel.
if (!_opt.options.noTranspile) {
const { transform } = require('@babel/core');
bundle = transform(bundle, {
// babelHelpers : 'bundled',
code : true,
compact : false,
presets : [['@babel/preset-env']],
filename : 'sugarcube.bundle.js'
}).code;
}

const uglifyjs = require('uglify-js');
const minified = uglifyjs.minify(jsSource, {
compress : {
global_defs : {
TWINE1 : !!options.twine1,
DEBUG : _opt.options.debug || false
bundle = `${readFileContents(filenameObj.wrap.intro)}\n${bundle}\n${readFileContents(filenameObj.wrap.outro)}`;

return (async source => {
if (_opt.options.unminified) {
return [
`window.TWINE1=${Boolean(options.twine1)}`,
`window.DEBUG=${_opt.options.debug || false}`,
source
].join(';\n');
}

// Minify the code with Terser.
const { minify } = require('terser');
const minified = await minify(source, {
compress : {
global_defs : { // eslint-disable-line camelcase
TWINE1 : !!options.twine1,
DEBUG : _opt.options.debug || false
}
},
keep_infinity : true
},
mangle : false
});
mangle : false
});

if (minified.error) {
const { message, line, col, pos } = minified.error;
die(`JavaScript minification error: ${message}\n[@: ${line}/${col}/${pos}]`);
}
if (minified.error) {
const { message, line, col, pos } = minified.error;
die(`JavaScript minification error: ${message}\n[@: ${line}/${col}/${pos}]`);
}

return minified.code;
/* eslint-enable camelcase, prefer-template */
return minified.code;
})(bundle);
}

function compileStyles(filenames) {
/* eslint-disable prefer-template */
function compileStyles(config) {
log('compiling CSS...');

const postcss = require('postcss');
const CleanCss = require('clean-css');
const normalizeRegExp = /normalize\.css$/;
const autoprefixer = require('autoprefixer');
const mixins = require('postcss-mixins');
const postcss = require('postcss');
const CleanCSS = require('clean-css');
const excludeRE = /(?:normalize)\.css$/;
const mixinContent = readFileContents(config.mixins);

return concatFiles(filenames, (contents, filename) => {
return concatFiles(config.files, (contents, filename) => {
let css = contents;

// Don't run autoprefixer on 'normalize.css'.
if (!normalizeRegExp.test(filename)) {
const processed = postcss([require('autoprefixer')]).process(css, { from : filename });
// Do not run the postcss plugins on files that match the exclusion regexp.
if (!excludeRE.test(filename)) {
css = `${mixinContent}\n${css}`;

const processed = postcss([mixins, autoprefixer]).process(css, { from : filename });

css = processed.css;

processed.warnings().forEach(mesg => console.warn(mesg.text));
}

if (!_opt.options.unminified) {
css = new CleanCss({
level : 1, // [clean-css v4] `1` is the default, but let's be specific
compatibility : 'ie9' // [clean-css v4] 'ie10' is the default, so restore IE9 support
css = new CleanCSS({
level : 1,
compatibility : 'ie9'
})
.minify(css)
.styles;
}

return '<style id="style-' + _path.basename(filename, '.css').toLowerCase().replace(/[^0-9a-z]+/g, '-')
+ '" type="text/css">' + css + '</style>';
const fileSlug = _path.basename(filename, '.css').toLowerCase().replace(/[^0-9a-z]+/g, '-');

return `<style id="style-${fileSlug}" type="text/css">${css}</style>`;
});
/* eslint-enable prefer-template */
}

function projectBuild(project) {
Expand All @@ -378,7 +381,8 @@ function projectBuild(project) {

log(`building: "${outfile}"`);

let output = readFileContents(infile); // load the story format template
// Load the story format template.
let output = readFileContents(infile);

// Process the source replacement tokens. (First!)
output = output.replace(/(['"`])\{\{BUILD_LIB_SOURCE\}\}\1/, () => project.libSource);
Expand Down
2 changes: 1 addition & 1 deletion dist/format.js

Large diffs are not rendered by default.

Loading

0 comments on commit 27903a8

Please sign in to comment.