Skip to content

Commit

Permalink
v2.3.22
Browse files Browse the repository at this point in the history
Regression of logic to parse style and script tags, due to loss of performance and other issues.
Correction to doc/guide.md
Fixed Makefile and .eslintignore for working with the new "src" directory.
  • Loading branch information
amarcruz committed Jan 24, 2016
1 parent 5b05a7f commit 9eaeb0a
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 69 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
**/test/specs/parsers/js/
**/test/v223/
**/test/perf.js
**/src/
11 changes: 5 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# Compiler Changes

### v2.3.22
- Complete code refactorization with comments in preparation for JSDoc.
- Preserved the fix to [riot#1511](https://github.com/riot/riot/issues/1511) from the deleted v2.3.21, without the regex error.
- Removed the "compress" option of the `less` parser, it is deprecated and generates warnings on the console.
- Fix [riot#1511](https://github.com/riot/riot/issues/1511) : Escape Quotes - They may be some issues to fix.
- Regression of logic to parse style and script tags, due to loss of performance and other issues.
- Removed the "compress" option of the `less` parser, which is deprecated and generates warnings in the console.
- Removed the unuseful CSS parser `stylus` from the browser version.
- Refactorization of all the code, with more comments in preparation for the automatic documentation of the API.
- Various tweaks to increase performance and reduce (~55%) memory consumption.
- Files to preprocess are moved from "lib" to the "src" directory, now "lib" has the required node.js files only.

### v2.3.21 (unpublished due to errors)
- Code refactorization of the `parsers` module, removed unuseful CSS parser `stylus` for browsers.
- Fix [riot#1511](https://github.com/riot/riot/issues/1511) : Escape Quotes - They may be some issues to fix.
- New logic for parsing `<script>/<style>` blocks. See [doc/guide.md](https://github.com/riot/compiler/blob/dev/doc/guide.md#the-untagged-javascript-block) for details.

### v2.3.20
- Fix [riot#1495](https://github.com/riot/riot/issues/1495) : Warning of input tag value - Avoids warnings for date/datetime/time/month/email/color types with expression in its value.
Expand Down
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ DIST = "./dist/"
# default job
test: build test-mocha

build: eslint
build: pre-build eslint
# rebuild all
@ mkdir -p $(DIST)
@ $(JSPP) $(JSPP_NODE_FLAGS) src/core.js > lib/compiler.js
@ $(JSPP) $(JSPP_RIOT_FLAGS) src/_riot.js > $(DIST)riot.compiler.js
@ $(JSPP) $(JSPP_ES6_FLAGS) src/_es6.js > $(DIST)es6.compiler.js

pre-build:
# build the node version
@ mkdir -p $(DIST)
@ $(JSPP) $(JSPP_NODE_FLAGS) src/core.js > lib/compiler.js

eslint:
# check code style
@ $(ESLINT) -c ./.eslintrc.yml lib test
Expand All @@ -53,4 +56,4 @@ perf: build
docs: build
@ jsdoc lib/ --configure ./jsdoc.json -P ./package.json --verbose

.PHONY: test build eslint test-mocha send-coverage debug perf docs
.PHONY: test pre-build build eslint test-mocha send-coverage debug perf docs
28 changes: 16 additions & 12 deletions dist/es6.compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ function _compileHTML (html, opts, pcex) {
var p = []

if (/<pre[\s>]/.test(html)) {
html = html.replace(PRE_TAGS, function (_q) {
p.push(_q)
html = html.replace(PRE_TAGS, function (q) {
p.push(q)
return '\u0002'
})
}
Expand Down Expand Up @@ -439,19 +439,23 @@ var MISC_ATTR = '\\s*=\\s*(' + S_STRINGS + '|{[^}]+}|\\S+)'

var END_TAGS = /\/>\n|^<(?:\/?[-\w]+\s*|[-\w]+\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/

function q (s) {
return SQ + (s ? s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") : '') + SQ
function _q (s, r) {
if (!s) return "''"
s = SQ + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + SQ
return r && ~s.indexOf('\n') ? s.replace(/\n/g, '\\n') : s
}

function mktag (name, html, css, attribs, js, pcex) {
var
c = ', ',
s = '}' + (pcex.length ? ', ' + q(pcex._bp[8]) : '') + ');'
s = '}' + (pcex.length ? ', ' + _q(pcex._bp[8]) : '') + ');'

if (js && js.slice(-1) !== '\n') s = '\n' + s

return 'riot.tag2(\'' + name + SQ + c + q(html).replace(/\n/g, '\\n') +
c + q(css) + c + q(attribs) + ', function(opts) {\n' + js + s
return 'riot.tag2(\'' + name + SQ +
c + _q(html, 1) +
c + _q(css) +
c + _q(attribs) + ', function(opts) {\n' + js + s
}

function splitBlocks (str) {
Expand Down Expand Up @@ -582,11 +586,9 @@ function compile (src, opts, url) {
if (included('html')) html = _compileHTML(body2, opts, pcex)
} else {

var blocks = splitBlocks(
body.replace(RegExp('^' + indent, 'gm'), '').replace(TRIM_TRAIL, '')
)
body = body.replace(RegExp('^' + indent, 'gm'), '')

body = blocks[0].replace(STYLES, function (_m, _attrs, _style) {
body = body.replace(STYLES, function (_m, _attrs, _style) {
if (included('css')) {
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName)
}
Expand All @@ -602,8 +604,10 @@ function compile (src, opts, url) {
return ''
})

var blocks = splitBlocks(body.replace(TRIM_TRAIL, ''))

if (included('html')) {
html = _compileHTML(body, opts, pcex)
html = _compileHTML(blocks[0], opts, pcex)
}

if (included('js')) {
Expand Down
28 changes: 16 additions & 12 deletions dist/riot.compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ var compile = (function () {
var p = []

if (/<pre[\s>]/.test(html)) {
html = html.replace(PRE_TAGS, function (_q) {
p.push(_q)
html = html.replace(PRE_TAGS, function (q) {
p.push(q)
return '\u0002'
})
}
Expand Down Expand Up @@ -437,19 +437,23 @@ var compile = (function () {

var END_TAGS = /\/>\n|^<(?:\/?[-\w]+\s*|[-\w]+\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/

function q (s) {
return SQ + (s ? s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") : '') + SQ
function _q (s, r) {
if (!s) return "''"
s = SQ + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + SQ
return r && ~s.indexOf('\n') ? s.replace(/\n/g, '\\n') : s
}

function mktag (name, html, css, attribs, js, pcex) {
var
c = ', ',
s = '}' + (pcex.length ? ', ' + q(pcex._bp[8]) : '') + ');'
s = '}' + (pcex.length ? ', ' + _q(pcex._bp[8]) : '') + ');'

if (js && js.slice(-1) !== '\n') s = '\n' + s

return 'riot.tag2(\'' + name + SQ + c + q(html).replace(/\n/g, '\\n') +
c + q(css) + c + q(attribs) + ', function(opts) {\n' + js + s
return 'riot.tag2(\'' + name + SQ +
c + _q(html, 1) +
c + _q(css) +
c + _q(attribs) + ', function(opts) {\n' + js + s
}

function splitBlocks (str) {
Expand Down Expand Up @@ -580,11 +584,9 @@ var compile = (function () {
if (included('html')) html = _compileHTML(body2, opts, pcex)
} else {

var blocks = splitBlocks(
body.replace(RegExp('^' + indent, 'gm'), '').replace(TRIM_TRAIL, '')
)
body = body.replace(RegExp('^' + indent, 'gm'), '')

body = blocks[0].replace(STYLES, function (_m, _attrs, _style) {
body = body.replace(STYLES, function (_m, _attrs, _style) {
if (included('css')) {
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName)
}
Expand All @@ -600,8 +602,10 @@ var compile = (function () {
return ''
})

var blocks = splitBlocks(body.replace(TRIM_TRAIL, ''))

if (included('html')) {
html = _compileHTML(body, opts, pcex)
html = _compileHTML(blocks[0], opts, pcex)
}

if (included('js')) {
Expand Down
14 changes: 11 additions & 3 deletions doc/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,23 @@ The first action taken by the compiler is send the received source to any html p
After that, the compiler normalizes line endings to `\n`.
This is done in the entire source.

Once prepared the source, searches the html elements. For each found element separates its parts (closing/opening tag, root attributes, and content) and parses the root attributes, then removes _html_ comments and trims trailing whitespace from the content.
Once prepared the source, searches the html elements. For each found element separates its parts (closing/opening tag, root attributes, and content) and parses the root attributes, then removes _html_ comments and trim trailing whitespace from the content.

Then, one at the time, removes the `style` blocks and sends its content to the CSS parser. Next, it does the same for the `script` blocks.

In the remaining content, looks for the last html tag which _terminate its line_.
If found, its closing tag signals the end of the html markup and the beginning of the untagged JavaScript code.
If not found, all remaining is considered JavaScript.

In the html part, one by one, removes the `style` blocks and sends its content to the CSS parser. Next, it does the same for the `script` tags.
So, you can put `style` and `script` blocks anywhere in the content, the only restriction is that the untagged JavaScript block must follow the html and you can't use JavaScript comments outside this block.

So, you can put html comments anywhere inside the tag, but keep the `style` and `script` blocks in the html part; the only restriction is that the untagged JavaScript block must follow the html and you can't use JavaScript comments outside this block.
**Note:** This freedom has a cost: JavaScript strings containing script or style tags have to be written with tricks as:
```js
<script>
var js1 = '<script><\/script>' // tagged JS, you can write '<script>' as-is
</script>
var js2 = '\x3cscript><\/script>' // in untagged block you need another trick
```

### To ES6 Users

Expand Down
36 changes: 21 additions & 15 deletions lib/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ function _compileHTML (html, opts, pcex) {
var p = []

if (/<pre[\s>]/.test(html)) {
html = html.replace(PRE_TAGS, function (_q) {
p.push(_q)
html = html.replace(PRE_TAGS, function (q) {
p.push(q)
return '\u0002'
})
}
Expand Down Expand Up @@ -630,13 +630,17 @@ var END_TAGS = /\/>\n|^<(?:\/?[-\w]+\s*|[-\w]+\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/
* Encloses the given string in single quotes.
*
* 2016-01-18: we must escape single quotes and backslashes before quoting the
* string, but there's no need to care about line-endings, each submodule does it.
* string, but there's no need to care about line-endings unless is required,
* as each submodule normalizes the lines.
*
* @param {string} s - unquoted string
* @returns {string} quoted string, with escaped single-quotes and backslashes
* @param {string} s - The unquoted, source string
* @param {number} r - If 1, escape embeded EOLs in the source
* @returns {string} Quoted string, with escaped single-quotes and backslashes.
*/
function q (s) {
return SQ + (s ? s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") : '') + SQ
function _q (s, r) {
if (!s) return "''"
s = SQ + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + SQ
return r && ~s.indexOf('\n') ? s.replace(/\n/g, '\\n') : s
}

/**
Expand All @@ -653,12 +657,14 @@ function q (s) {
function mktag (name, html, css, attribs, js, pcex) {
var
c = ', ',
s = '}' + (pcex.length ? ', ' + q(pcex._bp[8]) : '') + ');'
s = '}' + (pcex.length ? ', ' + _q(pcex._bp[8]) : '') + ');'

if (js && js.slice(-1) !== '\n') s = '\n' + s

return 'riot.tag2(\'' + name + SQ + c + q(html).replace(/\n/g, '\\n') +
c + q(css) + c + q(attribs) + ', function(opts) {\n' + js + s
return 'riot.tag2(\'' + name + SQ +
c + _q(html, 1) +
c + _q(css) +
c + _q(attribs) + ', function(opts) {\n' + js + s
}

/**
Expand Down Expand Up @@ -900,11 +906,9 @@ function compile (src, opts, url) {
if (included('html')) html = _compileHTML(body2, opts, pcex)
} else {

var blocks = splitBlocks(
body.replace(RegExp('^' + indent, 'gm'), '').replace(TRIM_TRAIL, '')
)
body = body.replace(RegExp('^' + indent, 'gm'), '')

body = blocks[0].replace(STYLES, function (_m, _attrs, _style) {
body = body.replace(STYLES, function (_m, _attrs, _style) {
if (included('css')) {
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName)
}
Expand All @@ -921,8 +925,10 @@ function compile (src, opts, url) {
return ''
})

var blocks = splitBlocks(body.replace(TRIM_TRAIL, ''))

if (included('html')) {
html = _compileHTML(body, opts, pcex)
html = _compileHTML(blocks[0], opts, pcex)
}

if (included('js')) {
Expand Down
41 changes: 24 additions & 17 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ function _compileHTML (html, opts, pcex) {

// hide any `<pre>` tags from the compactation
if (/<pre[\s>]/.test(html)) {
html = html.replace(PRE_TAGS, function (_q) {
p.push(_q)
html = html.replace(PRE_TAGS, function (q) {
p.push(q)
return '\u0002'
})
}
Expand Down Expand Up @@ -686,13 +686,17 @@ var END_TAGS = /\/>\n|^<(?:\/?[-\w]+\s*|[-\w]+\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/
* Encloses the given string in single quotes.
*
* 2016-01-18: we must escape single quotes and backslashes before quoting the
* string, but there's no need to care about line-endings, each submodule does it.
* string, but there's no need to care about line-endings unless is required,
* as each submodule normalizes the lines.
*
* @param {string} s - unquoted string
* @returns {string} quoted string, with escaped single-quotes and backslashes
* @param {string} s - The unquoted, source string
* @param {number} r - If 1, escape embeded EOLs in the source
* @returns {string} Quoted string, with escaped single-quotes and backslashes.
*/
function q (s) {
return SQ + (s ? s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") : '') + SQ
function _q (s, r) {
if (!s) return "''"
s = SQ + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + SQ
return r && ~s.indexOf('\n') ? s.replace(/\n/g, '\\n') : s
}

/**
Expand All @@ -709,14 +713,16 @@ function q (s) {
function mktag (name, html, css, attribs, js, pcex) {
var
c = ', ',
s = '}' + (pcex.length ? ', ' + q(pcex._bp[$_RIX_PAIR]) : '') + ');'
s = '}' + (pcex.length ? ', ' + _q(pcex._bp[$_RIX_PAIR]) : '') + ');'

// give more consistency to the output
if (js && js.slice(-1) !== '\n') s = '\n' + s

// 2016-01-18: html can contain eols if opts.whitespace=1, fix after q()
return 'riot.tag2(\'' + name + SQ + c + q(html).replace(/\n/g, '\\n') +
c + q(css) + c + q(attribs) + ', function(opts) {\n' + js + s
// 2016-01-18: html can contain eols if opts.whitespace=1, fix with q(s,1)
return 'riot.tag2(\'' + name + SQ +
c + _q(html, 1) +
c + _q(css) +
c + _q(attribs) + ', function(opts) {\n' + js + s
}

/**
Expand Down Expand Up @@ -980,13 +986,11 @@ function compile (src, opts, url) {
/* is-tanbul ignore next */
if (included('html')) html = _compileHTML(body2, opts, pcex)
} else {
// separate the untagged javascript block from the html
var blocks = splitBlocks(
body.replace(RegExp('^' + indent, 'gm'), '').replace(TRIM_TRAIL, '')
)
// remove tag indentation in the content
body = body.replace(RegExp('^' + indent, 'gm'), '')

// get and process the style blocks
body = blocks[0].replace(STYLES, function (_m, _attrs, _style) {
body = body.replace(STYLES, function (_m, _attrs, _style) {
if (included('css')) {
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName)
}
Expand All @@ -1006,9 +1010,12 @@ function compile (src, opts, url) {
return ''
})

// separate the untagged javascript block from the html
var blocks = splitBlocks(body.replace(TRIM_TRAIL, ''))

// process the remaining html part
if (included('html')) {
html = _compileHTML(body, opts, pcex)
html = _compileHTML(blocks[0], opts, pcex)
}

// and the untagged js block
Expand Down

0 comments on commit 9eaeb0a

Please sign in to comment.