diff --git a/README.md b/README.md index 13188a9ca..0ac2093e8 100644 --- a/README.md +++ b/README.md @@ -160,8 +160,8 @@ To install Jekyll for use with PCjs: 1. Install Ruby (on OS X, it should already be installed) 2. Install Bundler (on OS X, run `sudo gem install bundler`) - 3. Checkout the `gh-pages` branch, since only that branch contains all the Jekyll-related files - 4. Create a `Gemfile` containing `gem 'github-pages'` (this is already checked in) + 3. Checkout the *gh-pages* branch, since only that branch contains all the Jekyll-related files + 4. Create a **Gemfile** containing `gem 'github-pages'` (this is already checked in) 5. Run `bundle install` (GitHub Pages alternatively suggests: `bundle exec jekyll build --safe`) 6. Run `bundle exec jekyll serve` to start the web server @@ -171,14 +171,14 @@ Some useful Jekyll server options include: bundle exec jekyll serve --host=0.0.0.0 --config _config.yml,_developer.yml -The `--host` option makes it possible to access the web server from other devices on your local network; -for example, you may want to run PCjs on your iPhone, iPad, or other wireless device. And by adding `_developer.yml`, -you can override the Jekyll configuration defaults in `_config.yml`. Using development (non-production) settings in -`_developer.yml` is analogous to running the Node web server with certain development options; see +The *--host* option makes it possible to access the web server from other devices on your local network; +for example, you may want to run PCjs on your iPhone, iPad, or other wireless device. And by adding **_developer.yml**, +you can override the Jekyll configuration defaults in **_config.yml**. Using development (non-production) settings in +**_developer.yml** is analogous to running the Node web server with certain development options; see [Debugging PCjs](#debugging-pcjs). GitHub Pages says you can run `jekyll serve` instead of `bundle exec jekyll serve`, but with the addition of -more gems to `Gemfile` (eg, `jekyll-sitemap`), running `jekyll serve` may trigger dependency errors on some systems. +more gems to **Gemfile** (eg, "jekyll-sitemap"), running `jekyll serve` may trigger dependency errors on some systems. `bundle exec jekyll serve` should always work. Don't see any YML files in the root of your project? You probably forgot to switch to the @@ -198,7 +198,7 @@ However, in order to build and test PCjs modifications, you'll want to use [Grun Grunt tasks defined by [Gruntfile.js](Gruntfile.js). Although Grunt was installed locally when you ran `npm install`, you'll also want to install the command-line -interface to Grunt. You can install that locally as well, but it's recommended you install it globally with `-g`; +interface to Grunt. You can install that locally as well, but it's recommended you install it globally with *-g*; OS X users may also need to preface this command with `sudo`: npm install grunt-cli -g @@ -249,7 +249,7 @@ Here's what I installed to get Gulp working: npm install --save-dev gulp gulp-concat gulp-rename gulp-replace gulp-header gulp-foreach gulp-wrapper run-sequence npm install --save-dev google-closure-compiler-js -Running `gulp` should build a new `pcx86.js` in the [versions](/versions/) directory. However, +Running `gulp` should build a new **pcx86.js** in the [versions](/versions/) directory. However, you should consider Gulp support (and anything built with Gulp) as **experimental** until further notice. The [JavaScript-based Closure Compiler](https://github.com/google/closure-compiler-js) is in a state of flux as well; for example, *output_wrapper* support is documented in their @@ -354,8 +354,8 @@ you can start the server with some additional options; eg: node server.js --logging --console --debug -The `--logging` option will create a [node.log](/logs/) that records all the HTTP requests, `--debug` -will generate additional debug-only messages (which will also be logged if `--logging` is enabled), and `--console` +The *--logging* option will create a [node.log](/logs/) that records all the HTTP requests, *--debug* +will generate additional debug-only messages (which will also be logged if *--logging* is enabled), and *--console* will replicate any messages to your console as well. If you want server.js to use a different port (the default is 8088), set PORT in your environment before starting @@ -363,7 +363,7 @@ the server: export PORT=80 -or add `--port` to your command-line: +or add *--port* to your command-line: node server.js --logging --console --debug --port=80 @@ -376,7 +376,7 @@ PCjs emulators much easier to debug, albeit much slower: http://localhost:8088/?gort=debug -The "gort=debug" command is unnecessary if the server is started with `--debug`; the server always serves uncompiled +The "gort=debug" command is unnecessary if the server is started with *--debug*; the server always serves uncompiled files when running in debug mode. Conversely, if the server is in debug mode but you want to test a compiled version of PCx86, use: diff --git a/modules/markout/lib/markout.js b/modules/markout/lib/markout.js index 8f17c997e..dd1cf2e78 100644 --- a/modules/markout/lib/markout.js +++ b/modules/markout/lib/markout.js @@ -383,11 +383,16 @@ MarkOut.prototype.convertMD = function(sIndent) var sMD = this.sMD; /* - * Convert any escaped asterisks, square brackets, etc, to their HTML-entity equivalents, + * Convert any escaped asterisks, square brackets, etc, to their HTML entity equivalents, * as a convenient way of avoiding parsing problems later. We also take this opportunity * to replace any \r\n sequences with \n. + * + * UPDATE: I've moved the HTML entity replacement into convertMDBlock(), AFTER we check for + * code blocks and call escapeHTML(), because otherwise we run into entity "double-encoding" + * problems. Hopefully, the aforementioned "parsing problems" don't rear their head before then. */ - sMD = str.replaceArray(MarkOut.aHTMLEntities, sMD).replace(/\r\n/g, "\n").replace(/\r/g, "\n"); + sMD = sMD.replace(/\r\n/g, "\n").replace(/\r/g, "\n"); + // sMD = str.replaceArray(MarkOut.aHTMLEntities, sMD).replace(/\r\n/g, "\n").replace(/\r/g, "\n"); /* * Before performing the original comment-elimination step, a new step has been added that @@ -402,7 +407,7 @@ MarkOut.prototype.convertMD = function(sIndent) * triple-dash-style comments. */ if (!this.fDebug) { - sMD = sMD.replace(/\{%\s*if\s+page\.developer\s*%}[\s\S]*?{%\s*endif\s*%}\s*/g, ""); + sMD = sMD.replace(/{%\s*if\s+page\.developer\s*%}[\s\S]*?{%\s*endif\s*%}\s*/g, ""); sMD = sMD.replace(/[ \t]*/g, ""); /* @@ -601,7 +606,7 @@ MarkOut.prototype.convertMD = function(sIndent) * you want the second paragraph to appear as a code block, it must be indented TWICE (by 8 spaces * or 2 tabs). That behavior should fall out of this hack as well. */ - var re = /(^|\n)( ? ?)([*+-]|[0-9]+\.)([^\n]*\n)([ \t]+[^\n]*\n|\n)+([ \t]+[^\n]+)/g; + var re = /(^|\n)( {1,2} ?)([*+-]|[0-9]+\.)([^\n]*\n)([ \t]+[^\n]*\n|\n)+([ \t]+[^\n]+)/g; //noinspection UnnecessaryLocalVariableJS var sMDOrig = sMD; while ((aMatch = re.exec(sMDOrig))) { @@ -742,9 +747,9 @@ MarkOut.prototype.convertMDBlock = function(sBlock, sIndent) * No other conversions should occur in such a block, so we don't "fall into" the other conversions. */ var aMatch; - var re = /^((^|\n)( |\t)([^\n]*))+$/; + var re = /^((^|\n)( {4}|\t)([^\n]*))+$/; if ((aMatch = re.exec(sBlock))) { - var sUndented = aMatch[0].replace(/(^|\n)( |\t)([^\n]*)/g, "$1$3"); + var sUndented = aMatch[0].replace(/(^|\n)( {4}|\t)([^\n]*)/g, "$1$3"); sBlock = sBlock.replace(aMatch[0], "
" + str.escapeHTML(sUndented.replace(/\t/g, "    ")) + "
"); sHTML += this.sIndent + sBlock + "\n"; return sHTML; @@ -771,8 +776,8 @@ MarkOut.prototype.convertMDBlock = function(sBlock, sIndent) * treated as literal; we translate those to HTML entity "`" to prevent them from being * detected as part of a "single-backtick" sequence below. * - * Note that we also do the entity replacement AFTER calling htmlspecialchars(), because - * our implementation of htmlspecialchars() isn't smart enough to avoid the "double-encoding" + * Note that we also do entity replacement AFTER calling escapeHTML(), our simplified version + * of PHP's htmlspecialchars(), because it isn't smart enough to avoid the "double-encoding" * problem (ie, translating the leading "&" of an entity into yet another "&" entity). */ var sBlockOrig = sBlock; @@ -790,11 +795,18 @@ MarkOut.prototype.convertMDBlock = function(sBlock, sIndent) sBlock = sBlock.replace(aMatch[0], "" + str.escapeHTML(aMatch[1]) + ""); } + /* + * As mentioned at the top of convertMD(), the Markdown escape-sequence-to-HTML-entity conversion + * has been moved here, after we've dealt with code blocks and escapeHTML() operations, in an effort + * to avoid HTML entity "double-encoding" issues. + */ + sBlock = str.replaceArray(MarkOut.aHTMLEntities, sBlock); + /* * Per markdown syntax: "When you do want to insert a
break tag using Markdown, * you end a line with two or more spaces, then type return." */ - sBlock = sBlock.replace(/ +\n/g, "
\n" + this.sIndent); + sBlock = sBlock.replace(/ {2,}\n/g, "
\n" + this.sIndent); /* * If the block looks like a list, convertMDList() will convert it; if not, then it will wrap the @@ -890,10 +902,10 @@ MarkOut.prototype.convertMDList = function(sBlock, sIndent) * If this list item contains one or more lines indented by 4 or more spaces (or 1 or more tabs) * then we need to strip them, so that they can be parsed as a sub-list. */ - re = /((^|\n)( |\t)([^\n]*))+/; + re = /((^|\n)( {4}|\t)([^\n]*))+/; if ((aMatch = re.exec(sListItem))) { // if (this.fDebug) sList += this.encodeComment("subList", aMatch[0]); - var sSubList = aMatch[0].replace(/(^|\n)( |\t)([^\n]*)/g, "$1$3").replace(/\n\t\n/g, "\n\n"); + var sSubList = aMatch[0].replace(/(^|\n)( {4}|\t)([^\n]*)/g, "$1$3").replace(/\n\t\n/g, "\n\n"); if (sSubList.charAt(0) == "\n") sSubList = sSubList.substr(1); sListItem = str.replaceAll(aMatch[0], "\n" + this.sIndent + this.convertMDBlocks(sSubList, sIndent).trim() + "\n" + this.sIndent, sListItem); } else { @@ -971,8 +983,8 @@ MarkOut.prototype.convertMDLinks = function(sBlock) * page's Front Matter; however, unless/until we start using Node again to host the public site, * that's low priority. */ - sBlock = sBlock.replace(/([^\t])\{([{%]).*?\2}/g, "$1"); - sBlock = sBlock.replace(/(\{)([{%])(.*?\2})/g, "
$1$2$3
"); + sBlock = sBlock.replace(/([^\t]){([{%]).*?\2}/g, "$1"); + sBlock = sBlock.replace(/({)([{%])(.*?\2})/g, "
$1$2$3
"); var aMatch; var re = /\[([^\[\]]*)]\((.*?)(?:\s*"(.*?)"\)|\))/g; @@ -1023,7 +1035,7 @@ MarkOut.prototype.convertMDImageLinks = function(sBlock, sIndent) * (in case this Markdown file is part of a Jekyll installation) and convert them to Markdown-style links. */ var aMatch; - var reIncludes = /\{%\s*include\s+screenshot\.html\s+(.*?)\s*%}/g; + var reIncludes = /{%\s*include\s+screenshot\.html\s+(.*?)\s*%}/g; while ((aMatch = reIncludes.exec(sBlock))) { var option, aOptions = {}; @@ -1211,7 +1223,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) /* * Ditto for any Liquid-style machine build links. */ - sBlock = sBlock.replace(/\{%\s*include\s+machine-build\.html\s+id=(["'])(.*?)\1\s*%}/g, '
'); + sBlock = sBlock.replace(/{%\s*include\s+machine-build\.html\s+id=(["'])(.*?)\1\s*%}/g, '
'); /* * Start looking for Markdown-style machine links now... @@ -1288,7 +1300,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) /* * Last but not least, see if there are any Liquid-style machine command links that need to be converted. */ - reIncludes = /([ \t]*)\{%\s*include\s+machine-command\.html\s+(.*?)\s*%}/g; + reIncludes = /([ \t]*){%\s*include\s+machine-command\.html\s+(.*?)\s*%}/g; var findParm = function(aParms, sParm) { sParm += '='; diff --git a/modules/shared/lib/strlib.js b/modules/shared/lib/strlib.js index 9c349910f..9b8f3b255 100644 --- a/modules/shared/lib/strlib.js +++ b/modules/shared/lib/strlib.js @@ -506,7 +506,7 @@ class Str { } /** - * replace(sFind, sReplace, s) + * replace(sSearch, sReplace, s) * * The JavaScript replace() function ALWAYS interprets "$" specially in replacement strings, even when * the search string is NOT a RegExp; specifically: @@ -521,36 +521,36 @@ class Str { * So, if a replacement string containing dollar signs passes through a series of replace() calls, untold * problems could result. Hence, this function, which simply uses the replacement string as-is. * - * Similar to the JavaScript replace() method, this replaces only one occurrence (ie, the FIRST occurrence); - * it might be nice to add options to replace the LAST occurrence and/or ALL occurrences, but we'll revisit - * that later. + * Similar to the JavaScript replace() method (when sSearch is a string), this replaces only ONE occurrence + * (ie, the FIRST occurrence); it might be nice to add options to replace the LAST occurrence and/or ALL + * occurrences, but we'll revisit that later. * - * @param {string} sFind + * @param {string} sSearch * @param {string} sReplace * @param {string} s * @return {string} */ - static replace(sFind, sReplace, s) + static replace(sSearch, sReplace, s) { - var i = s.indexOf(sFind); + var i = s.indexOf(sSearch); if (i >= 0) { - s = s.substr(0, i) + sReplace + s.substr(i + sFind.length); + s = s.substr(0, i) + sReplace + s.substr(i + sSearch.length); } return s; } /** - * replaceAll(sFind, sReplace, s) + * replaceAll(sSearch, sReplace, s) * - * @param {string} sFind + * @param {string} sSearch * @param {string} sReplace * @param {string} s * @return {string} */ - static replaceAll(sFind, sReplace, s) + static replaceAll(sSearch, sReplace, s) { var a = {}; - a[sFind] = sReplace; + a[sSearch] = sReplace; return Str.replaceArray(a, s); }