[6a3a178] | 1 |
|
---|
| 2 | /*!
|
---|
| 3 | * Stylus - plugin - url
|
---|
| 4 | * Copyright (c) Automattic <developer.wordpress.com>
|
---|
| 5 | * MIT Licensed
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | /**
|
---|
| 9 | * Module dependencies.
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | var Compiler = require('../visitor/compiler')
|
---|
| 13 | , events = require('../renderer').events
|
---|
| 14 | , nodes = require('../nodes')
|
---|
| 15 | , parse = require('url').parse
|
---|
| 16 | , extname = require('path').extname
|
---|
| 17 | , utils = require('../utils')
|
---|
| 18 | , fs = require('fs');
|
---|
| 19 |
|
---|
| 20 | /**
|
---|
| 21 | * Mime table.
|
---|
| 22 | */
|
---|
| 23 |
|
---|
| 24 | var defaultMimes = {
|
---|
| 25 | '.gif': 'image/gif'
|
---|
| 26 | , '.png': 'image/png'
|
---|
| 27 | , '.jpg': 'image/jpeg'
|
---|
| 28 | , '.jpeg': 'image/jpeg'
|
---|
| 29 | , '.svg': 'image/svg+xml'
|
---|
| 30 | , '.webp': 'image/webp'
|
---|
| 31 | , '.ttf': 'application/x-font-ttf'
|
---|
| 32 | , '.eot': 'application/vnd.ms-fontobject'
|
---|
| 33 | , '.woff': 'application/font-woff'
|
---|
| 34 | , '.woff2': 'application/font-woff2'
|
---|
| 35 | };
|
---|
| 36 |
|
---|
| 37 | /**
|
---|
| 38 | * Supported encoding types
|
---|
| 39 | */
|
---|
| 40 | var encodingTypes = {
|
---|
| 41 | BASE_64: 'base64',
|
---|
| 42 | UTF8: 'charset=utf-8'
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | /**
|
---|
| 46 | * Return a url() function with the given `options`.
|
---|
| 47 | *
|
---|
| 48 | * Options:
|
---|
| 49 | *
|
---|
| 50 | * - `limit` bytesize limit defaulting to 30Kb
|
---|
| 51 | * - `paths` image resolution path(s), merged with general lookup paths
|
---|
| 52 | *
|
---|
| 53 | * Examples:
|
---|
| 54 | *
|
---|
| 55 | * stylus(str)
|
---|
| 56 | * .set('filename', __dirname + '/css/test.styl')
|
---|
| 57 | * .define('url', stylus.url({ paths: [__dirname + '/public'] }))
|
---|
| 58 | * .render(function(err, css) { ... })
|
---|
| 59 | *
|
---|
| 60 | * @param {Object} options
|
---|
| 61 | * @return {Function}
|
---|
| 62 | * @api public
|
---|
| 63 | */
|
---|
| 64 |
|
---|
| 65 | module.exports = function(options) {
|
---|
| 66 | options = options || {};
|
---|
| 67 |
|
---|
| 68 | var _paths = options.paths || [];
|
---|
| 69 | var sizeLimit = null != options.limit ? options.limit : 30000;
|
---|
| 70 | var mimes = options.mimes || defaultMimes;
|
---|
| 71 |
|
---|
| 72 | /**
|
---|
| 73 | * @param {object} url - The path to the image you want to encode.
|
---|
| 74 | * @param {object} enc - The encoding for the image. Defaults to base64, the
|
---|
| 75 | * other valid option is `utf8`.
|
---|
| 76 | */
|
---|
| 77 | function fn(url, enc) {
|
---|
| 78 | // Compile the url
|
---|
| 79 | var compiler = new Compiler(url)
|
---|
| 80 | , encoding = encodingTypes.BASE_64;
|
---|
| 81 |
|
---|
| 82 | compiler.isURL = true;
|
---|
| 83 | url = url.nodes.map(function(node) {
|
---|
| 84 | return compiler.visit(node);
|
---|
| 85 | }).join('');
|
---|
| 86 |
|
---|
| 87 | // Parse literal
|
---|
| 88 | url = parse(url);
|
---|
| 89 | var ext = extname(url.pathname)
|
---|
| 90 | , mime = mimes[ext]
|
---|
| 91 | , hash = url.hash || ''
|
---|
| 92 | , literal = new nodes.Literal('url("' + url.href + '")')
|
---|
| 93 | , paths = _paths.concat(this.paths)
|
---|
| 94 | , buf
|
---|
| 95 | , result;
|
---|
| 96 |
|
---|
| 97 | // Not supported
|
---|
| 98 | if(!mime) return literal;
|
---|
| 99 |
|
---|
| 100 | // Absolute
|
---|
| 101 | if(url.protocol) return literal;
|
---|
| 102 |
|
---|
| 103 | // Lookup
|
---|
| 104 | var found = utils.lookup(url.pathname, paths);
|
---|
| 105 |
|
---|
| 106 | // Failed to lookup
|
---|
| 107 | if(!found) {
|
---|
| 108 | events.emit(
|
---|
| 109 | 'file not found'
|
---|
| 110 | , 'File ' + literal + ' could not be found, literal url retained!'
|
---|
| 111 | );
|
---|
| 112 |
|
---|
| 113 | return literal;
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | // Read data
|
---|
| 117 | var str = fs.readFileSync(found, 'utf8');
|
---|
| 118 |
|
---|
| 119 | // Too large
|
---|
| 120 | if(false !== sizeLimit && str.length > sizeLimit) return literal;
|
---|
| 121 |
|
---|
| 122 | if(enc && 'utf8' == enc.first.val.toLowerCase()) {
|
---|
| 123 | encoding = encodingTypes.UTF8;
|
---|
| 124 | result = str.replace(/\s+/g, ' ')
|
---|
| 125 | .replace(/[{}\|\\\^~\[\]`"<>#%]/g, function(match) {
|
---|
| 126 | return '%' + match[0].charCodeAt(0).toString(16).toUpperCase();
|
---|
| 127 | }).trim();
|
---|
| 128 | } else {
|
---|
| 129 | result = Buffer.from(str.replace(/\r\n?/g, '\n')).toString(encoding) + hash;
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | // Encode
|
---|
| 133 | return new nodes.Literal('url("data:' + mime + ';' + encoding + ',' + result + '")');
|
---|
| 134 | };
|
---|
| 135 |
|
---|
| 136 | fn.raw = true;
|
---|
| 137 | return fn;
|
---|
| 138 | };
|
---|
| 139 |
|
---|
| 140 | // Exporting default mimes so we could easily access them
|
---|
| 141 | module.exports.mimes = defaultMimes;
|
---|
| 142 |
|
---|