UNPKG

3.41 kBJavaScriptView Raw
1
2/*!
3 * Stylus - plugin - url
4 * Copyright (c) Automattic <developer.wordpress.com>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
12var 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
24var 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 */
40var 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
65module.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
141module.exports.mimes = defaultMimes;
142