Skip to content

Commit

Permalink
Merge branch 'feature/sourcemaps' into dev
Browse files Browse the repository at this point in the history
* feature/sourcemaps:
  added: simple test for sourcemaps
  updated: skip empty lines
  added: initial sourcemaps support #56
  • Loading branch information
GianlucaGuarini committed Dec 9, 2017
2 parents b8b74b5 + d8187eb commit 2519c46
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ratings:
paths:
- "dist/compiler.js"

exclude_paths:
exclude_patterns:
- "dist/riot.compiler.js"
- "test/**/*"
- "lib/**/*"
6 changes: 0 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ JSPP_NODE_FLAGS = $(JSPP_FLAGS) -D NODE -F jsdoc
JSPP_RIOT_FLAGS = $(JSPP_FLAGS)
JSPP_ES6_FLAGS = $(JSPP_FLAGS)

# Code Climate only accepts the first job of default branch
TESTCOVER = $(TRAVIS_BRANCH) $(TRAVIS_NODE_VERSION)
NODE_VER := $(shell node nodever)

# Command line paths
Expand Down Expand Up @@ -50,10 +48,6 @@ test-mocha:

send-coverage:
@ RIOT_COV=1 cat ./coverage/lcov.info | $(COVERALLS)
ifeq ($(TESTCOVER),master 4.2)
@ npm install codeclimate-test-reporter
@ codeclimate-test-reporter < coverage/lcov.info
endif

debug: build
# launching node-inspector
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ _Please note: the documentation is a work in progress. Contributions are welcome
[npm-version-image]: https://img.shields.io/npm/v/riot-compiler.svg?style=flat-square
[npm-downloads-image]: https://img.shields.io/npm/dm/riot-compiler.svg?style=flat-square
[npm-url]: https://npmjs.org/package/riot-compiler
[coverage-image]: https://codeclimate.com/github/riot/compiler/badges/coverage.svg
[coverage-url]: https://codeclimate.com/github/riot/compiler/coverage
[codeclimate-image]: https://codeclimate.com/github/riot/compiler/badges/issue_count.svg
[coverage-image]: https://img.shields.io/coveralls/riot/compiler/master.svg?style=flat-square
[coverage-url]: https://coveralls.io/r/riot/compiler?branch=master
[codeclimate-image]: https://api.codeclimate.com/v1/badges/37de24282e8d113bb0cc/maintainability
[codeclimate-url]: https://codeclimate.com/github/riot/compiler
22 changes: 17 additions & 5 deletions lib/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @copyright Muut Inc. + contributors
*/
'use strict'

var sourcemap = require('./sourcemap')
var brackets = require('./brackets')
var parsers = require('./parsers')
var safeRegex = require('./safe-regex')
Expand Down Expand Up @@ -874,6 +874,7 @@ function compile (src, opts, url) {
var
parts = [],
included,
output = src,
defaultParserptions = {

template: {},
Expand All @@ -893,10 +894,10 @@ function compile (src, opts, url) {
var _bp = brackets.array(opts.brackets)

if (opts.template) {
src = compileTemplate(src, url, opts.template, opts.parserOptions.template)
output = compileTemplate(output, url, opts.template, opts.parserOptions.template)
}

src = cleanSource(src)
output = cleanSource(output)
.replace(CUST_TAG, function (_, indent, tagName, attribs, body, body2) {
var
jscode = '',
Expand Down Expand Up @@ -980,9 +981,20 @@ function compile (src, opts, url) {

if (opts.debug && url.slice(-2) !== '/.') {
if (/^[\\/]/.test(url)) url = path.relative('.', url)
src = '//src: ' + url.replace(/\\/g, '/') + '\n' + src
output = '//src: ' + url.replace(/\\/g, '/') + '\n' + output
}
return src

if (opts.sourcemap) {
return {
map: sourcemap({
source: src,
generated: output,
file: url
}),
code: output
}
}
return output
}

module.exports = {
Expand Down
73 changes: 73 additions & 0 deletions lib/sourcemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
var SourceMapGenerator = require('source-map').SourceMapGenerator
var stringSimilarity = require('string-similarity')

var LINES_RE = /[\r\n]/
var INDENTATION_RE = /^\s*/

/**
* Find the source code using Levenshtein algorithm.
* At moment riot doesn't use a real parser so that's the easiest solution to create sourcemaps
* @param {string} sourceLine - original source code line
* @param {array} outputLines - output lines
* @returns {object} sourcemap position
*/
function findSource(sourceLine, outputLines) {
// figure out where this line could be located in the source code
var bestMatch = stringSimilarity.findBestMatch(sourceLine, outputLines).bestMatch
// find the index of the line matched
var index = outputLines.indexOf(bestMatch.target)

// figure out the column
var column = bestMatch.target.indexOf(sourceLine)

return {
line: ++index,
column: (column > -1 ? column : getIndentation(bestMatch.target)) + 1
}
}

/**
* Return the indentation amount of a line containing code
* @param {string} code - string containing code
* @returns {number} amount of indentation
*/
function getIndentation(code) {
return code.match(INDENTATION_RE)[0].length
}

/**
* Remove the indentation from the source code
* @param {string} code - target code
* @returns {string} code without indentation
*/
function cleanLine(code) {
return code.replace(INDENTATION_RE, '').trim()
}

/**
* Generate the sourcemap
* @param {object} opts - object containing the source/generated code and the file path
* @returns {SourceMapGenerator} - SourceMapGenerator instance
*/
module.exports = function generate(opts) {
var map = new SourceMapGenerator({
file: opts.file
})

var outputLines = opts.generated.split(LINES_RE).map(cleanLine).filter(l => l.length)

opts.source.split(LINES_RE).forEach(function(line, index) {
// skip empty lines
if (!cleanLine(line).length) return
map.addMapping({
source: opts.file,
original:{
line: ++index,
column: getIndentation(line)
},
generated: findSource(line, outputLines)
})
})

return map
}
43 changes: 24 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
},
"homepage": "https://github.com/riot/compiler#readme",
"dependencies": {
"skip-regex": "^0.3.1"
"skip-regex": "^0.3.1",
"source-map": "^0.6.1",
"string-similarity": "^1.2.0"
}
}
23 changes: 18 additions & 5 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @copyright Muut Inc. + contributors
*/
'use strict'

var sourcemap = require('./sourcemap')
var brackets = require('./brackets')
var parsers = require('./parsers')
var safeRegex = require('./safe-regex')
Expand Down Expand Up @@ -946,6 +946,7 @@ function compile (src, opts, url) {
var
parts = [],
included,
output = src,
defaultParserptions = {
// TODO: rename this key from `template` to `html`in the next major release
template: {},
Expand Down Expand Up @@ -976,12 +977,12 @@ function compile (src, opts, url) {

// run any custom html parser before the compilation
if (opts.template) {
src = compileTemplate(src, url, opts.template, opts.parserOptions.template)
output = compileTemplate(output, url, opts.template, opts.parserOptions.template)
}

// each tag can have attributes first, then html markup with zero or more script
// or style tags of different types, and finish with the untagged JS block.
src = cleanSource(src)
output = cleanSource(output)
.replace(CUST_TAG, function (_, indent, tagName, attribs, body, body2) {
var
jscode = '',
Expand Down Expand Up @@ -1080,10 +1081,22 @@ function compile (src, opts, url) {
//#if NODE
if (opts.debug && url.slice(-2) !== '/.') {
if (/^[\\/]/.test(url)) url = path.relative('.', url)
src = '//src: ' + url.replace(/\\/g, '/') + '\n' + src
output = '//src: ' + url.replace(/\\/g, '/') + '\n' + output
}

//
if (opts.sourcemap) {
return {
map: sourcemap({
source: src,
generated: output,
file: url
}),
code: output
}
}
//#endif
return src
return output
}

//#if NODE
Expand Down
1 change: 1 addition & 0 deletions test/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ describe('Compiler Tests', function () {
require('./specs/css')
require('./specs/js')
require('./specs/tag')
require('./specs/sourcemaps')
require('./specs/parsers/_suite')
})
32 changes: 16 additions & 16 deletions test/specs/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ module.exports = {
*/
requireName: function (name) {
switch (name) {
case 'es6':
return 'babel'
case 'babel':
return 'babel-core'
case 'javascript':
return 'none'
case 'coffee':
case 'coffeescript':
return 'coffee-script'
case 'scss':
case 'sass':
return 'node-sass'
case 'typescript':
return 'typescript-simple'
default:
return name
case 'es6':
return 'babel'
case 'babel':
return 'babel-core'
case 'javascript':
return 'none'
case 'coffee':
case 'coffeescript':
return 'coffee-script'
case 'scss':
case 'sass':
return 'node-sass'
case 'typescript':
return 'typescript-simple'
default:
return name
}
}
}
34 changes: 34 additions & 0 deletions test/specs/sourcemaps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*eslint-env mocha */
/*global compiler, expect */
/*eslint max-len: 0, no-console: 0 */

var fs = require('fs'),
path = require('path')

describe('Sourcemaps generation', function () {
// in Win __dirname is a real path, in Lunux is symlink, path.relative uses symlink
var
basepath = path.resolve(__dirname, './'),
fixtures = path.join(basepath, 'fixtures')


function render (str, name, opts) {
return compiler.compile(str, opts, name ? path.join(fixtures, name) : '')
}

function cat (dir, filename) {
return fs.readFileSync(path.join(dir, filename), 'utf8')
}

function compile (name) {
var src = cat(fixtures, name + '.tag')
return render(src, name + '.tag', { sourcemap: true })
}

it('It generates source and sourcemaps', function () {
var out = compile('timetable')

expect(out.code).to.be.ok
expect(out.sourcemap).to.be.ok
})
})

0 comments on commit 2519c46

Please sign in to comment.