123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- /*!
- * Stylus - SourceMapper
- * Copyright (c) Automattic <developer.wordpress.com>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Compiler = require('./compiler')
- , Buffer = require('safer-buffer').Buffer
- , SourceMapGenerator = require('source-map').SourceMapGenerator
- , basename = require('path').basename
- , extname = require('path').extname
- , dirname = require('path').dirname
- , join = require('path').join
- , relative = require('path').relative
- , sep = require('path').sep
- , fs = require('fs');
- /**
- * Initialize a new `SourceMapper` generator with the given `root` Node
- * and the following `options`.
- *
- * @param {Node} root
- * @api public
- */
- var SourceMapper = module.exports = function SourceMapper(root, options){
- options = options || {};
- this.column = 1;
- this.lineno = 1;
- this.contents = {};
- this.filename = options.filename;
- this.dest = options.dest;
- var sourcemap = options.sourcemap;
- this.basePath = sourcemap.basePath || '.';
- this.inline = sourcemap.inline;
- this.comment = sourcemap.comment;
- if (this.dest && extname(this.dest) === '.css') {
- this.basename = basename(this.dest);
- this.dest = dirname(this.dest);
- } else {
- this.basename = basename(this.filename, extname(this.filename)) + '.css';
- }
- this.utf8 = false;
- this.map = new SourceMapGenerator({
- file: this.basename,
- sourceRoot: sourcemap.sourceRoot || null
- });
- Compiler.call(this, root, options);
- };
- /**
- * Inherit from `Compiler.prototype`.
- */
- SourceMapper.prototype.__proto__ = Compiler.prototype;
- /**
- * Generate and write source map.
- *
- * @return {String}
- * @api private
- */
- var compile = Compiler.prototype.compile;
- SourceMapper.prototype.compile = function(){
- var css = compile.call(this)
- , out = this.basename + '.map'
- , url = this.normalizePath(this.dest
- ? join(this.dest, out)
- : join(dirname(this.filename), out))
- , map;
- if (this.inline) {
- map = this.map.toString();
- url = 'data:application/json;'
- + (this.utf8 ? 'charset=utf-8;' : '') + 'base64,'
- + Buffer.from(map).toString('base64');
- }
- if (this.inline || false !== this.comment)
- css += '/*# sourceMappingURL=' + url + ' */';
- return css;
- };
- /**
- * Add mapping information.
- *
- * @param {String} str
- * @param {Node} node
- * @return {String}
- * @api private
- */
- SourceMapper.prototype.out = function(str, node){
- if (node && node.lineno) {
- var filename = this.normalizePath(node.filename);
- this.map.addMapping({
- original: {
- line: node.lineno,
- column: node.column - 1
- },
- generated: {
- line: this.lineno,
- column: this.column - 1
- },
- source: filename
- });
- if (this.inline && !this.contents[filename]) {
- this.map.setSourceContent(filename, fs.readFileSync(node.filename, 'utf-8'));
- this.contents[filename] = true;
- }
- }
- this.move(str);
- return str;
- };
- /**
- * Move current line and column position.
- *
- * @param {String} str
- * @api private
- */
- SourceMapper.prototype.move = function(str){
- var lines = str.match(/\n/g)
- , idx = str.lastIndexOf('\n');
- if (lines) this.lineno += lines.length;
- this.column = ~idx
- ? str.length - idx
- : this.column + str.length;
- };
- /**
- * Normalize the given `path`.
- *
- * @param {String} path
- * @return {String}
- * @api private
- */
- SourceMapper.prototype.normalizePath = function(path){
- path = relative(this.dest || this.basePath, path);
- if ('\\' == sep) {
- path = path.replace(/^[a-z]:\\/i, '/')
- .replace(/\\/g, '/');
- }
- return path;
- };
- /**
- * Visit Literal.
- */
- var literal = Compiler.prototype.visitLiteral;
- SourceMapper.prototype.visitLiteral = function(lit){
- var val = literal.call(this, lit)
- , filename = this.normalizePath(lit.filename)
- , indentsRe = /^\s+/
- , lines = val.split('\n');
- // add mappings for multiline literals
- if (lines.length > 1) {
- lines.forEach(function(line, i) {
- var indents = line.match(indentsRe)
- , column = indents && indents[0]
- ? indents[0].length
- : 0;
- if (lit.css) column += 2;
- this.map.addMapping({
- original: {
- line: lit.lineno + i,
- column: column
- },
- generated: {
- line: this.lineno + i,
- column: 0
- },
- source: filename
- });
- }, this);
- }
- return val;
- };
- /**
- * Visit Charset.
- */
- var charset = Compiler.prototype.visitCharset;
- SourceMapper.prototype.visitCharset = function(node){
- this.utf8 = ('utf-8' == node.val.string.toLowerCase());
- return charset.call(this, node);
- };
|