tailwindcss 0.0.0-oxide-insiders.0ddc71e → 0.0.0-oxide-insiders.2f21b22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/index.css +5 -0
  2. package/lib/cli/build/plugin.js +10 -5
  3. package/lib/cli/init/index.js +4 -0
  4. package/lib/css/preflight.css +7 -1
  5. package/lib/lib/content.js +23 -2
  6. package/lib/lib/evaluateTailwindFunctions.js +5 -3
  7. package/lib/oxide/cli/build/plugin.js +10 -5
  8. package/lib/oxide/cli/init/index.js +4 -0
  9. package/lib/util/dataTypes.js +14 -6
  10. package/lib/util/getAllConfigs.js +3 -1
  11. package/lib/util/normalizeConfig.js +30 -8
  12. package/lib/util/validateConfig.js +7 -1
  13. package/lib/value-parser/LICENSE +22 -0
  14. package/lib/value-parser/README.md +3 -0
  15. package/lib/value-parser/index.d.js +2 -0
  16. package/lib/value-parser/index.js +22 -0
  17. package/lib/value-parser/parse.js +259 -0
  18. package/lib/value-parser/stringify.js +38 -0
  19. package/lib/value-parser/unit.js +86 -0
  20. package/lib/value-parser/walk.js +16 -0
  21. package/package.json +2 -2
  22. package/src/cli/build/plugin.js +8 -1
  23. package/src/cli/init/index.js +5 -0
  24. package/src/css/preflight.css +7 -1
  25. package/src/lib/content.js +31 -4
  26. package/src/lib/evaluateTailwindFunctions.js +4 -1
  27. package/src/oxide/cli/build/plugin.ts +8 -1
  28. package/src/oxide/cli/init/index.ts +5 -0
  29. package/src/util/dataTypes.js +17 -6
  30. package/src/util/getAllConfigs.js +8 -1
  31. package/src/util/normalizeConfig.js +51 -17
  32. package/src/util/validateConfig.js +8 -1
  33. package/src/value-parser/LICENSE +22 -0
  34. package/src/value-parser/README.md +3 -0
  35. package/src/value-parser/index.d.ts +177 -0
  36. package/src/value-parser/index.js +28 -0
  37. package/src/value-parser/parse.js +303 -0
  38. package/src/value-parser/stringify.js +41 -0
  39. package/src/value-parser/unit.js +118 -0
  40. package/src/value-parser/walk.js +18 -0
  41. package/stubs/config.full.js +1 -0
  42. package/types/generated/default-theme.d.ts +1 -0
package/index.css ADDED
@@ -0,0 +1,5 @@
1
+ @tailwind base;
2
+
3
+ @tailwind components;
4
+
5
+ @tailwind utilities;
@@ -29,6 +29,7 @@ const _findAtConfigPath = require("../../lib/findAtConfigPath.js");
29
29
  const _log = /*#__PURE__*/ _interop_require_default(require("../../util/log"));
30
30
  const _loadconfig = require("../../lib/load-config");
31
31
  const _getModuleDependencies = /*#__PURE__*/ _interop_require_default(require("../../lib/getModuleDependencies"));
32
+ const _validateConfig = require("../../util/validateConfig");
32
33
  function _interop_require_default(obj) {
33
34
  return obj && obj.__esModule ? obj : {
34
35
  default: obj
@@ -144,11 +145,15 @@ let state = {
144
145
  }
145
146
  };
146
147
  // @ts-ignore
147
- this.configBag.config = (0, _resolveConfig.default)(this.configBag.config, {
148
- content: {
149
- files: []
150
- }
151
- });
148
+ if (true) {
149
+ this.configBag.config = (0, _validateConfig.validateConfig)((0, _resolveConfig.default)(this.configBag.config));
150
+ } else {
151
+ this.configBag.config = (0, _validateConfig.validateConfig)((0, _resolveConfig.default)(this.configBag.config, {
152
+ content: {
153
+ files: []
154
+ }
155
+ }));
156
+ }
152
157
  // Override content files if `--content` has been passed explicitly
153
158
  if ((content === null || content === void 0 ? void 0 : content.length) > 0) {
154
159
  this.configBag.config.content.files = content;
@@ -37,6 +37,10 @@ function init(args) {
37
37
  } else {
38
38
  let stubContentsFile = _fs.default.readFileSync(args["--full"] ? _path.default.resolve(__dirname, "../../../stubs/config.full.js") : _path.default.resolve(__dirname, "../../../stubs/config.simple.js"), "utf8");
39
39
  let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, `../../../stubs/tailwind.config.${syntax}`), "utf8");
40
+ // Drop `content` in the oxide engine to promote auto content
41
+ if (true) {
42
+ stubContentsFile = stubContentsFile.replace(/\s*content: \[\],\n/, "");
43
+ }
40
44
  // Change colors import
41
45
  stubContentsFile = stubContentsFile.replace("../colors", "tailwindcss/colors");
42
46
  // Replace contents of {ts,js,cjs} file with the stub {simple,full}.
@@ -163,6 +163,8 @@ optgroup,
163
163
  select,
164
164
  textarea {
165
165
  font-family: inherit; /* 1 */
166
+ font-feature-settings: inherit; /* 1 */
167
+ font-variation-settings: inherit; /* 1 */
166
168
  font-size: 100%; /* 1 */
167
169
  font-weight: inherit; /* 1 */
168
170
  line-height: inherit; /* 1 */
@@ -264,7 +266,7 @@ summary {
264
266
  }
265
267
 
266
268
  /*
267
- Removes the default spacing and border for appropriate elements.
269
+ Removes the default spacing for appropriate elements.
268
270
  */
269
271
 
270
272
  blockquote,
@@ -300,6 +302,10 @@ menu {
300
302
  padding: 0;
301
303
  }
302
304
 
305
+ dialog {
306
+ padding: 0;
307
+ }
308
+
303
309
  /*
304
310
  Prevent resizing textareas horizontally by default.
305
311
  */
@@ -29,8 +29,29 @@ function _interop_require_default(obj) {
29
29
  default: obj
30
30
  };
31
31
  }
32
+ /** @typedef {import('../../types/config.js').RawFile} RawFile */ /** @typedef {import('../../types/config.js').FilePath} FilePath */ /*
33
+ * @param {import('tailwindcss').Config} tailwindConfig
34
+ * @param {{skip:string[]}} options
35
+ * @returns {ContentPath[]}
36
+ */ function resolveContentFiles(tailwindConfig, { skip =[] } = {}) {
37
+ if (tailwindConfig.content.files === "auto" && true) {
38
+ _sharedState.env.DEBUG && console.time("Calculating resolve content paths");
39
+ tailwindConfig.content.files = require("@tailwindcss/oxide").resolveContentPaths({
40
+ base: process.cwd()
41
+ });
42
+ if (skip.length > 0) {
43
+ tailwindConfig.content.files = tailwindConfig.content.files.filter((filePath)=>!skip.includes(filePath));
44
+ }
45
+ _sharedState.env.DEBUG && console.timeEnd("Calculating resolve content paths");
46
+ }
47
+ return tailwindConfig.content.files;
48
+ }
32
49
  function parseCandidateFiles(context, tailwindConfig) {
33
- let files = tailwindConfig.content.files;
50
+ let files = resolveContentFiles(tailwindConfig, {
51
+ skip: [
52
+ context.userConfigPath
53
+ ]
54
+ });
34
55
  // Normalize the file globs
35
56
  files = files.filter((filePath)=>typeof filePath === "string");
36
57
  files = files.map(_normalizepath.default);
@@ -135,7 +156,7 @@ function parseCandidateFiles(context, tailwindConfig) {
135
156
  return paths;
136
157
  }
137
158
  function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
138
- let changedContent = context.tailwindConfig.content.files.filter((item)=>typeof item.raw === "string").map(({ raw , extension ="html" })=>({
159
+ let changedContent = context.tailwindConfig.content.files === "auto" && true ? [] : context.tailwindConfig.content.files.filter((item)=>typeof item.raw === "string").map(({ raw , extension ="html" })=>({
139
160
  content: raw,
140
161
  extension
141
162
  }));
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "default", {
11
11
  const _dlv = /*#__PURE__*/ _interop_require_default(require("dlv"));
12
12
  const _didyoumean = /*#__PURE__*/ _interop_require_default(require("didyoumean"));
13
13
  const _transformThemeValue = /*#__PURE__*/ _interop_require_default(require("../util/transformThemeValue"));
14
- const _postcssvalueparser = /*#__PURE__*/ _interop_require_default(require("postcss-value-parser"));
14
+ const _index = /*#__PURE__*/ _interop_require_default(require("../value-parser/index"));
15
15
  const _normalizeScreens = require("../util/normalizeScreens");
16
16
  const _buildMediaQuery = /*#__PURE__*/ _interop_require_default(require("../util/buildMediaQuery"));
17
17
  const _toPath = require("../util/toPath");
@@ -121,7 +121,7 @@ function extractArgs(node, vNodes, functions) {
121
121
  if (vNode.type === "div" && vNode.value === ",") {
122
122
  args.push("");
123
123
  } else {
124
- args[args.length - 1] += _postcssvalueparser.default.stringify(vNode);
124
+ args[args.length - 1] += _index.default.stringify(vNode);
125
125
  }
126
126
  }
127
127
  return args;
@@ -135,7 +135,9 @@ function resolveVNode(node, vNode, functions) {
135
135
  return vNode;
136
136
  }
137
137
  function resolveFunctions(node, input, functions) {
138
- return (0, _postcssvalueparser.default)(input).walk((vNode)=>{
138
+ let hasAnyFn = Object.keys(functions).some((fn)=>input.includes(`${fn}(`));
139
+ if (!hasAnyFn) return input;
140
+ return (0, _index.default)(input).walk((vNode)=>{
139
141
  resolveVNode(node, vNode, functions);
140
142
  }).toString();
141
143
  }
@@ -28,6 +28,7 @@ const _findAtConfigPath = require("../../../lib/findAtConfigPath");
28
28
  const _log = /*#__PURE__*/ _interop_require_default(require("../../../util/log"));
29
29
  const _loadconfig = require("../../../lib/load-config");
30
30
  const _getModuleDependencies = /*#__PURE__*/ _interop_require_default(require("../../../lib/getModuleDependencies"));
31
+ const _validateConfig = require("../../../util/validateConfig");
31
32
  function _interop_require_default(obj) {
32
33
  return obj && obj.__esModule ? obj : {
33
34
  default: obj
@@ -143,11 +144,15 @@ let state = {
143
144
  }
144
145
  };
145
146
  // @ts-ignore
146
- this.configBag.config = (0, _resolveConfig.default)(this.configBag.config, {
147
- content: {
148
- files: []
149
- }
150
- });
147
+ if (true) {
148
+ this.configBag.config = (0, _validateConfig.validateConfig)((0, _resolveConfig.default)(this.configBag.config));
149
+ } else {
150
+ this.configBag.config = (0, _validateConfig.validateConfig)((0, _resolveConfig.default)(this.configBag.config, {
151
+ content: {
152
+ files: []
153
+ }
154
+ }));
155
+ }
151
156
  // Override content files if `--content` has been passed explicitly
152
157
  if ((content === null || content === void 0 ? void 0 : content.length) > 0) {
153
158
  this.configBag.config.content.files = content;
@@ -36,6 +36,10 @@ function init(args) {
36
36
  } else {
37
37
  let stubContentsFile = _fs.default.readFileSync(args["--full"] ? _path.default.resolve(__dirname, "../../../../stubs/config.full.js") : _path.default.resolve(__dirname, "../../../../stubs/config.simple.js"), "utf8");
38
38
  let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, `../../../../stubs/tailwind.config.${syntax}`), "utf8");
39
+ // Drop `content` in the oxide engine to promote auto content
40
+ if (true) {
41
+ stubContentsFile = stubContentsFile.replace(/\s*content: \[\],\n/, "");
42
+ }
39
43
  // Change colors import
40
44
  stubContentsFile = stubContentsFile.replace("../colors", "tailwindcss/colors");
41
45
  // Replace contents of {ts,js,cjs} file with the stub {simple,full}.
@@ -89,16 +89,23 @@ function normalize(value, isRoot = true) {
89
89
  if (isRoot) {
90
90
  value = value.trim();
91
91
  }
92
- // Add spaces around operators inside math functions like calc() that do not follow an operator
93
- // or '('.
94
- value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
92
+ value = normalizeMathOperatorSpacing(value);
93
+ return value;
94
+ }
95
+ /**
96
+ * Add spaces around operators inside math functions
97
+ * like calc() that do not follow an operator or '('.
98
+ *
99
+ * @param {string} value
100
+ * @returns {string}
101
+ */ function normalizeMathOperatorSpacing(value) {
102
+ return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
95
103
  let vars = [];
96
104
  return match.replace(/var\((--.+?)[,)]/g, (match, g1)=>{
97
105
  vars.push(g1);
98
106
  return match.replace(g1, placeholder);
99
107
  }).replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ").replace(placeholderRe, ()=>vars.shift());
100
108
  });
101
- return value;
102
109
  }
103
110
  function url(value) {
104
111
  return value.startsWith("url(");
@@ -199,11 +206,12 @@ function image(value) {
199
206
  return images > 0;
200
207
  }
201
208
  let gradientTypes = new Set([
209
+ "conic-gradient",
202
210
  "linear-gradient",
203
211
  "radial-gradient",
212
+ "repeating-conic-gradient",
204
213
  "repeating-linear-gradient",
205
- "repeating-radial-gradient",
206
- "conic-gradient"
214
+ "repeating-radial-gradient"
207
215
  ]);
208
216
  function gradient(value) {
209
217
  value = normalize(value);
@@ -18,7 +18,9 @@ function _interop_require_default(obj) {
18
18
  function getAllConfigs(config) {
19
19
  var _config_presets;
20
20
  const configs = ((_config_presets = config === null || config === void 0 ? void 0 : config.presets) !== null && _config_presets !== void 0 ? _config_presets : [
21
- _configfull.default
21
+ true ? Object.assign({}, _configfull.default, {
22
+ content: "auto"
23
+ }) : _configfull.default
22
24
  ]).slice().reverse().flatMap((preset)=>getAllConfigs(preset instanceof Function ? preset() : preset));
23
25
  const features = {
24
26
  // Add experimental configs here...
@@ -65,6 +65,9 @@ function normalizeConfig(config) {
65
65
  * transform?: TransformerFn | { [extension: string]: TransformerFn }
66
66
  * }
67
67
  */ let valid = (()=>{
68
+ if (config.content === "auto") {
69
+ return true;
70
+ }
68
71
  // `config.purge` should not exist anymore
69
72
  if (config.purge) {
70
73
  return false;
@@ -191,6 +194,22 @@ function normalizeConfig(config) {
191
194
  var _config_prefix;
192
195
  config.prefix = (_config_prefix = config.prefix) !== null && _config_prefix !== void 0 ? _config_prefix : "";
193
196
  }
197
+ let auto = (()=>{
198
+ // Config still has a `purge` option (for backwards compatibility), auto content should not be
199
+ // used
200
+ if (config.purge) return false;
201
+ //
202
+ if (config.content === "auto") return true;
203
+ // We don't have content at all, auto content should be used
204
+ if (config.content === undefined) return true;
205
+ // We do have content as an object, but we don't have any files defined, auto content should
206
+ // be used
207
+ if (typeof config.content === "object" && config.content !== null && !Array.isArray(config.content)) {
208
+ return config.content.files === undefined;
209
+ }
210
+ // We do have content defined, auto content should not be used
211
+ return false;
212
+ })();
194
213
  // Normalize the `content`
195
214
  config.content = {
196
215
  relative: (()=>{
@@ -200,8 +219,9 @@ function normalizeConfig(config) {
200
219
  }
201
220
  return (0, _featureFlags.flagEnabled)(config, "relativeContentPathsByDefault");
202
221
  })(),
203
- files: (()=>{
222
+ files: auto ? "auto" : (()=>{
204
223
  let { content , purge } = config;
224
+ if (content === undefined && purge === undefined) return [];
205
225
  if (Array.isArray(purge)) return purge;
206
226
  if (Array.isArray(purge === null || purge === void 0 ? void 0 : purge.content)) return purge.content;
207
227
  if (Array.isArray(content)) return content;
@@ -269,13 +289,15 @@ function normalizeConfig(config) {
269
289
  };
270
290
  // Validate globs to prevent bogus globs.
271
291
  // E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html`
272
- for (let file of config.content.files){
273
- if (typeof file === "string" && /{([^,]*?)}/g.test(file)) {
274
- _log.default.warn("invalid-glob-braces", [
275
- `The glob pattern ${(0, _log.dim)(file)} in your Tailwind CSS configuration is invalid.`,
276
- `Update it to ${(0, _log.dim)(file.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`
277
- ]);
278
- break;
292
+ if (config.content.files !== "auto") {
293
+ for (let file of config.content.files){
294
+ if (typeof file === "string" && /{([^,]*?)}/g.test(file)) {
295
+ _log.default.warn("invalid-glob-braces", [
296
+ `The glob pattern ${(0, _log.dim)(file)} in your Tailwind CSS configuration is invalid.`,
297
+ `Update it to ${(0, _log.dim)(file.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`
298
+ ]);
299
+ break;
300
+ }
279
301
  }
280
302
  }
281
303
  return config;
@@ -15,13 +15,19 @@ function _interop_require_default(obj) {
15
15
  };
16
16
  }
17
17
  function validateConfig(config) {
18
- if (config.content.files.length === 0) {
18
+ if (config.content.files !== "auto" && config.content.files.length === 0) {
19
19
  _log.default.warn("content-problems", [
20
20
  "The `content` option in your Tailwind CSS configuration is missing or empty.",
21
21
  "Configure your content sources or your generated CSS will be missing styles.",
22
22
  "https://tailwindcss.com/docs/content-configuration"
23
23
  ]);
24
24
  }
25
+ if (config.content.files === "auto") {
26
+ _log.default.warn("auto-content-experimental", [
27
+ "Automatic content detection in Tailwind CSS is currently in experimental preview.",
28
+ "Preview features are not covered by semver, and may change at any time."
29
+ ]);
30
+ }
25
31
  // Warn if the line-clamp plugin is installed
26
32
  try {
27
33
  let plugin = require("@tailwindcss/line-clamp");
@@ -0,0 +1,22 @@
1
+ Copyright (c) Bogdan Chadkin <trysound@yandex.ru>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # postcss-value-parser (forked + inlined)
2
+
3
+ This is a customized version of of [PostCSS Value Parser](https://github.com/TrySound/postcss-value-parser) to fix some bugs around parsing CSS functions.
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ module.exports = postcssValueParser;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var parse = require("./parse");
3
+ var walk = require("./walk");
4
+ var stringify = require("./stringify");
5
+ function ValueParser(value) {
6
+ if (this instanceof ValueParser) {
7
+ this.nodes = parse(value);
8
+ return this;
9
+ }
10
+ return new ValueParser(value);
11
+ }
12
+ ValueParser.prototype.toString = function() {
13
+ return Array.isArray(this.nodes) ? stringify(this.nodes) : "";
14
+ };
15
+ ValueParser.prototype.walk = function(cb, bubble) {
16
+ walk(this.nodes, cb, bubble);
17
+ return this;
18
+ };
19
+ ValueParser.unit = require("./unit");
20
+ ValueParser.walk = walk;
21
+ ValueParser.stringify = stringify;
22
+ module.exports = ValueParser;
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ var openParentheses = "(".charCodeAt(0);
3
+ var closeParentheses = ")".charCodeAt(0);
4
+ var singleQuote = "'".charCodeAt(0);
5
+ var doubleQuote = '"'.charCodeAt(0);
6
+ var backslash = "\\".charCodeAt(0);
7
+ var slash = "/".charCodeAt(0);
8
+ var comma = ",".charCodeAt(0);
9
+ var colon = ":".charCodeAt(0);
10
+ var star = "*".charCodeAt(0);
11
+ var uLower = "u".charCodeAt(0);
12
+ var uUpper = "U".charCodeAt(0);
13
+ var plus = "+".charCodeAt(0);
14
+ var isUnicodeRange = /^[a-f0-9?-]+$/i;
15
+ module.exports = function(input) {
16
+ var tokens = [];
17
+ var value = input;
18
+ var next, quote, prev, token, escape, escapePos, whitespacePos, parenthesesOpenPos;
19
+ var pos = 0;
20
+ var code = value.charCodeAt(pos);
21
+ var max = value.length;
22
+ var stack = [
23
+ {
24
+ nodes: tokens
25
+ }
26
+ ];
27
+ var balanced = 0;
28
+ var parent;
29
+ var name = "";
30
+ var before = "";
31
+ var after = "";
32
+ while(pos < max){
33
+ // Whitespaces
34
+ if (code <= 32) {
35
+ next = pos;
36
+ do {
37
+ next += 1;
38
+ code = value.charCodeAt(next);
39
+ }while (code <= 32);
40
+ token = value.slice(pos, next);
41
+ prev = tokens[tokens.length - 1];
42
+ if (code === closeParentheses && balanced) {
43
+ after = token;
44
+ } else if (prev && prev.type === "div") {
45
+ prev.after = token;
46
+ prev.sourceEndIndex += token.length;
47
+ } else if (code === comma || code === colon || code === slash && value.charCodeAt(next + 1) !== star && (!parent || parent && parent.type === "function" && false)) {
48
+ before = token;
49
+ } else {
50
+ tokens.push({
51
+ type: "space",
52
+ sourceIndex: pos,
53
+ sourceEndIndex: next,
54
+ value: token
55
+ });
56
+ }
57
+ pos = next;
58
+ // Quotes
59
+ } else if (code === singleQuote || code === doubleQuote) {
60
+ next = pos;
61
+ quote = code === singleQuote ? "'" : '"';
62
+ token = {
63
+ type: "string",
64
+ sourceIndex: pos,
65
+ quote: quote
66
+ };
67
+ do {
68
+ escape = false;
69
+ next = value.indexOf(quote, next + 1);
70
+ if (~next) {
71
+ escapePos = next;
72
+ while(value.charCodeAt(escapePos - 1) === backslash){
73
+ escapePos -= 1;
74
+ escape = !escape;
75
+ }
76
+ } else {
77
+ value += quote;
78
+ next = value.length - 1;
79
+ token.unclosed = true;
80
+ }
81
+ }while (escape);
82
+ token.value = value.slice(pos + 1, next);
83
+ token.sourceEndIndex = token.unclosed ? next : next + 1;
84
+ tokens.push(token);
85
+ pos = next + 1;
86
+ code = value.charCodeAt(pos);
87
+ // Comments
88
+ } else if (code === slash && value.charCodeAt(pos + 1) === star) {
89
+ next = value.indexOf("*/", pos);
90
+ token = {
91
+ type: "comment",
92
+ sourceIndex: pos,
93
+ sourceEndIndex: next + 2
94
+ };
95
+ if (next === -1) {
96
+ token.unclosed = true;
97
+ next = value.length;
98
+ token.sourceEndIndex = next;
99
+ }
100
+ token.value = value.slice(pos + 2, next);
101
+ tokens.push(token);
102
+ pos = next + 2;
103
+ code = value.charCodeAt(pos);
104
+ // Operation within calc
105
+ } else if ((code === slash || code === star) && parent && parent.type === "function" && true) {
106
+ token = value[pos];
107
+ tokens.push({
108
+ type: "word",
109
+ sourceIndex: pos - before.length,
110
+ sourceEndIndex: pos + token.length,
111
+ value: token
112
+ });
113
+ pos += 1;
114
+ code = value.charCodeAt(pos);
115
+ // Dividers
116
+ } else if (code === slash || code === comma || code === colon) {
117
+ token = value[pos];
118
+ tokens.push({
119
+ type: "div",
120
+ sourceIndex: pos - before.length,
121
+ sourceEndIndex: pos + token.length,
122
+ value: token,
123
+ before: before,
124
+ after: ""
125
+ });
126
+ before = "";
127
+ pos += 1;
128
+ code = value.charCodeAt(pos);
129
+ // Open parentheses
130
+ } else if (openParentheses === code) {
131
+ // Whitespaces after open parentheses
132
+ next = pos;
133
+ do {
134
+ next += 1;
135
+ code = value.charCodeAt(next);
136
+ }while (code <= 32);
137
+ parenthesesOpenPos = pos;
138
+ token = {
139
+ type: "function",
140
+ sourceIndex: pos - name.length,
141
+ value: name,
142
+ before: value.slice(parenthesesOpenPos + 1, next)
143
+ };
144
+ pos = next;
145
+ if (name === "url" && code !== singleQuote && code !== doubleQuote) {
146
+ next -= 1;
147
+ do {
148
+ escape = false;
149
+ next = value.indexOf(")", next + 1);
150
+ if (~next) {
151
+ escapePos = next;
152
+ while(value.charCodeAt(escapePos - 1) === backslash){
153
+ escapePos -= 1;
154
+ escape = !escape;
155
+ }
156
+ } else {
157
+ value += ")";
158
+ next = value.length - 1;
159
+ token.unclosed = true;
160
+ }
161
+ }while (escape);
162
+ // Whitespaces before closed
163
+ whitespacePos = next;
164
+ do {
165
+ whitespacePos -= 1;
166
+ code = value.charCodeAt(whitespacePos);
167
+ }while (code <= 32);
168
+ if (parenthesesOpenPos < whitespacePos) {
169
+ if (pos !== whitespacePos + 1) {
170
+ token.nodes = [
171
+ {
172
+ type: "word",
173
+ sourceIndex: pos,
174
+ sourceEndIndex: whitespacePos + 1,
175
+ value: value.slice(pos, whitespacePos + 1)
176
+ }
177
+ ];
178
+ } else {
179
+ token.nodes = [];
180
+ }
181
+ if (token.unclosed && whitespacePos + 1 !== next) {
182
+ token.after = "";
183
+ token.nodes.push({
184
+ type: "space",
185
+ sourceIndex: whitespacePos + 1,
186
+ sourceEndIndex: next,
187
+ value: value.slice(whitespacePos + 1, next)
188
+ });
189
+ } else {
190
+ token.after = value.slice(whitespacePos + 1, next);
191
+ token.sourceEndIndex = next;
192
+ }
193
+ } else {
194
+ token.after = "";
195
+ token.nodes = [];
196
+ }
197
+ pos = next + 1;
198
+ token.sourceEndIndex = token.unclosed ? next : pos;
199
+ code = value.charCodeAt(pos);
200
+ tokens.push(token);
201
+ } else {
202
+ balanced += 1;
203
+ token.after = "";
204
+ token.sourceEndIndex = pos + 1;
205
+ tokens.push(token);
206
+ stack.push(token);
207
+ tokens = token.nodes = [];
208
+ parent = token;
209
+ }
210
+ name = "";
211
+ // Close parentheses
212
+ } else if (closeParentheses === code && balanced) {
213
+ pos += 1;
214
+ code = value.charCodeAt(pos);
215
+ parent.after = after;
216
+ parent.sourceEndIndex += after.length;
217
+ after = "";
218
+ balanced -= 1;
219
+ stack[stack.length - 1].sourceEndIndex = pos;
220
+ stack.pop();
221
+ parent = stack[balanced];
222
+ tokens = parent.nodes;
223
+ // Words
224
+ } else {
225
+ next = pos;
226
+ do {
227
+ if (code === backslash) {
228
+ next += 1;
229
+ }
230
+ next += 1;
231
+ code = value.charCodeAt(next);
232
+ }while (next < max && !(code <= 32 || code === singleQuote || code === doubleQuote || code === comma || code === colon || code === slash || code === openParentheses || code === star && parent && parent.type === "function" && true || code === slash && parent.type === "function" && true || code === closeParentheses && balanced));
233
+ token = value.slice(pos, next);
234
+ if (openParentheses === code) {
235
+ name = token;
236
+ } else if ((uLower === token.charCodeAt(0) || uUpper === token.charCodeAt(0)) && plus === token.charCodeAt(1) && isUnicodeRange.test(token.slice(2))) {
237
+ tokens.push({
238
+ type: "unicode-range",
239
+ sourceIndex: pos,
240
+ sourceEndIndex: next,
241
+ value: token
242
+ });
243
+ } else {
244
+ tokens.push({
245
+ type: "word",
246
+ sourceIndex: pos,
247
+ sourceEndIndex: next,
248
+ value: token
249
+ });
250
+ }
251
+ pos = next;
252
+ }
253
+ }
254
+ for(pos = stack.length - 1; pos; pos -= 1){
255
+ stack[pos].unclosed = true;
256
+ stack[pos].sourceEndIndex = value.length;
257
+ }
258
+ return stack[0].nodes;
259
+ };