Comparing version 0.3.0 to 0.4.0
@@ -0,1 +1,14 @@ | ||
### Version 0.4.0 (2014-12-19) ### | ||
- Changed: The `cssTokens.names` array has been replaced with the | ||
`cssTokens.matchToToken` function. The capturing groups of `cssTokens` are no | ||
longer part of the public API; instead use said function. See this [gist] for | ||
an example. (Backwards-incompatible change.) | ||
- Changed: The empty string is now considered an “invalid” token, instead an | ||
“empty” token (its own group). (Backwards-incompatible change.) | ||
- Removed: component support. (Backwards-incompatible change.) | ||
[gist]: https://gist.github.com/lydell/be49dbf80c382c473004 | ||
### Version 0.3.0 (2014-06-19) ### | ||
@@ -2,0 +15,0 @@ |
@@ -9,13 +9,4 @@ // Copyright 2014 Simon Lydell | ||
var source = fs.readFileSync("regex.coffee").toString() | ||
var names = [] | ||
source.replace(/^\s*\( # <([^>]+)>/mg, function(match, name) { | ||
names.push(name) | ||
}) | ||
var code = [ | ||
"module.exports = /" + regex.source.replace(/\//g, "\\/") + "/g", | ||
"module.exports.names = " + JSON.stringify(names, null, 2), | ||
].join("\n") | ||
var code = fs.readFileSync("index.js").toString() | ||
code = code.replace(/\/.+\/.+/, "/" + regex.source.replace(/\//g, "\\/") + "/g") | ||
fs.writeFileSync("index.js", code) |
32
index.js
@@ -1,13 +0,19 @@ | ||
module.exports = /(\s+)|(\/\*(?:[^*]|\*(?!\/))*(?:\*\/)?)|('(?:[^'\\\r\n]|\\(?:\r\n|[\s\S]))*'?|"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"?)|([+-]?\d*\.?\d+(?:[eE][+-]?\d+)?)|(url\((?!\s*["'])\s*(?:[^"'()\\\s]|\\(?:[\da-fA-F]{1,6}\s?|.))*(?:\s*\))?)|((?:[@.]?(?!-?\d)|\#)(?!-+(?![\w\-\u0080-\uFFFF\\]))(?:[\w\-\u0080-\uFFFF]|\\(?:[\da-fA-F]{1,6}\s?|.))+)|([~|^$*]?=|[>~+*\/]|-)|([|[\](){},;!%]|:{1,2})|(^$)|([\s\S])/g | ||
module.exports.names = [ | ||
"whitespace", | ||
"comment", | ||
"string", | ||
"number", | ||
"unquotedUrl", | ||
"name", | ||
"operator", | ||
"punctuation", | ||
"empty", | ||
"invalid" | ||
] | ||
// Copyright 2014 Simon Lydell | ||
// X11 (“MIT”) Licensed. (See LICENSE.) | ||
// This regex comes from regex.coffee, and is inserted here by generate-index.js | ||
// (run `npm run build`). | ||
module.exports = /((['"])(?:(?!\2)[^\\\r\n]|\\(?:\r\n|[\s\S]))*(\2)?)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|([+-]?\d*\.?\d+(?:[eE][+-]?\d+)?)|(url\((?!\s*["'])\s*(?:[^"'()\\\s]|\\(?:[\da-fA-F]{1,6}\s?|.))*(?:\s*\))?)|((?:[@.]?(?!-?\d)|\#)(?!-+(?![\w\-\u0080-\uFFFF\\]))(?:[\w\-\u0080-\uFFFF]|\\(?:[\da-fA-F]{1,6}\s?|.))+)|([~|^$*]?=|[>~+*\/]|-)|([|[\](){},;!%]|:{1,2})|(\s+)|(^$|[\s\S])/g | ||
module.exports.matchToToken = function(match) { | ||
token = {type: "invalid", value: match[0]} | ||
if (match[ 1]) token.type = "string" , token.closed = !!match[3] | ||
if (match[ 4]) token.type = "comment", token.closed = !!match[5] | ||
if (match[ 6]) token.type = "number" | ||
if (match[ 7]) token.type = "unquotedUrl" | ||
if (match[ 8]) token.type = "name" | ||
if (match[ 9]) token.type = "operator" | ||
if (match[10]) token.type = "punctuation" | ||
if (match[11]) token.type = "whitespace" | ||
return token | ||
} |
{ | ||
"name": "css-tokens", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"author": "Simon Lydell", | ||
"license": "MIT", | ||
"description": "A regex that tokenizes CSS.", | ||
"main": "index.js", | ||
"keywords": [ | ||
@@ -17,8 +16,10 @@ "CSS", | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "mocha --ui tdd", | ||
"build": "node generate-index.js", | ||
"dev": "npm run build && npm test" | ||
}, | ||
"devDependencies": { | ||
"mocha": "^1.17.1", | ||
"coffee-script": "~1.7.1" | ||
"coffee-script": "^1.8.0", | ||
"mocha": "^2.0.1" | ||
} | ||
} | ||
} |
@@ -9,14 +9,6 @@ Overview [![Build Status](https://travis-ci.org/lydell/css-tokens.png?branch=master)](https://travis-ci.org/lydell/css-tokens) | ||
// Tokenize a whole string of CSS: | ||
var cssString = ".foo{prop: foo;}\n..." | ||
cssString.match(cssTokens) | ||
// [".foo", "{", "prop", ":", " ", "foo", ";", "}", "\n", ...] | ||
// Rename the class `foo` to `bar`: | ||
cssString.replace(cssTokens, function(token) { | ||
if (token === ".foo") { | ||
token = "bar" | ||
} | ||
return token | ||
}) | ||
// [".bar", "{", "prop", ":", " ", "foo", ";", "}", "\n", ...] | ||
``` | ||
@@ -29,3 +21,2 @@ | ||
- `npm install css-tokens` | ||
- `component install lydell/css-tokens` | ||
@@ -44,13 +35,33 @@ ```js | ||
The regex _always_ matches, even invalid CSS and the empty string. For | ||
example, `cssTokens.exec(string)` never returns `null`. | ||
The regex _always_ matches, even invalid CSS and the empty string. | ||
The next match is always directly after the previous. Each token has its own | ||
capturing group. | ||
The next match is always directly after the previous. | ||
### `cssTokens.names` ### | ||
### `var token = cssTokens.matchToToken(match)` ### | ||
An array of names for each token, in the capturing group order. | ||
Takes a `match` returned by `cssTokens.exec(string)`, and returns a `{type: | ||
String, value: String}` object. The following types are available: | ||
- string | ||
- comment | ||
- number | ||
- unquotedUrl | ||
- name | ||
- operator | ||
- punctuation | ||
- whitespace | ||
- invalid | ||
Comments and strings also have a `closed` property indicating if the token was | ||
closed or not (see below). | ||
Strings come in two flavors. To distinguish them, check if the token starts with | ||
`'` or `"`. | ||
For example usage, please see this [gist]. | ||
[gist]: https://gist.github.com/lydell/be49dbf80c382c473004 | ||
Invalid code handling | ||
@@ -92,20 +103,2 @@ ===================== | ||
Build | ||
===== | ||
index.js is generated by running `node generate-index.js`. The regex is written | ||
in regex.coffee. Don’t worry, you don’t need to know anything about | ||
CoffeeScript: regex.coffee should be kept as simple as possible. CoffeeScript | ||
is only used for its block regexes, which have the following benefits: | ||
- Insignificant whitespace. | ||
- Comments. | ||
- No need to escape slashes. | ||
- No need to double-escape everything (as opposed to using `RegExp("regex as a | ||
string. One backslash: \\\\")`). | ||
- Plenty of syntax highlighters available. | ||
Everything else is written in JavaScript. | ||
License | ||
@@ -112,0 +105,0 @@ ======= |
@@ -19,7 +19,6 @@ // Copyright 2014 Simon Lydell | ||
suite("cssTokens.names", function() { | ||
suite("cssTokens.matchToToken", function() { | ||
test("is an array of strings", function() { | ||
assert(util.isArray(cssTokens.names)) | ||
assert(cssTokens.names.every(function(name) { return typeof name === "string" })) | ||
test("is a function", function() { | ||
assert.equal(typeof cssTokens.matchToToken, "function") | ||
}) | ||
@@ -36,16 +35,25 @@ | ||
function matchHelper(name, string, expected) { | ||
function matchHelper(type, string, expected, extra) { | ||
extra = extra || {} | ||
if (typeof expected === "object") { | ||
extra = expected | ||
expected = undefined | ||
} | ||
cssTokens.lastIndex = 0 | ||
var match = cssTokens.exec(string) | ||
var token = cssTokens.matchToToken(cssTokens.exec(string)) | ||
var index = 1 | ||
while (match[index] === undefined) index++ | ||
var actualName = cssTokens.names[index-1] | ||
test(string, function() { | ||
if (expected === false) { | ||
assert.notEqual(actualName, name) | ||
assert.notEqual(token.type, type) | ||
} else { | ||
assert.equal(cssTokens.names[index-1], name) | ||
assert.equal(match[0], (typeof expected === "string" ? expected : string)) | ||
assert.equal(token.type, type) | ||
assert.equal( | ||
token.value, | ||
(typeof expected === "string" ? expected : string) | ||
) | ||
if ("closed" in extra) { | ||
assert.equal(token.closed, extra.closed) | ||
} else if (type === "string" || type === "comment") { | ||
assert.equal(token.closed, true) | ||
} | ||
} | ||
@@ -85,6 +93,6 @@ }) | ||
match("/*") | ||
match("/*/") | ||
match("/*unclosed comment") | ||
match("/*unclosed comment\n@new .Line { is: this; } code:any(.true, .false) {}") | ||
match("/*", {closed: false}) | ||
match("/*/", {closed: false}) | ||
match("/*unclosed", {closed: false}) | ||
match("/*unclosed\n@new .Line{is:this;}code:any(.true,.false) {}", {closed: false}) | ||
@@ -107,3 +115,3 @@ }) | ||
match("'\\1d306'") | ||
match('"\\1d306') | ||
match('"\\1d306"') | ||
match("'\\\n'") | ||
@@ -120,18 +128,18 @@ match('"\\\n"') | ||
match("'") | ||
match('"') | ||
match("'unclosed string") | ||
match('"unclosed string') | ||
match("'\n", "'") | ||
match('"\n', '"') | ||
match("'\r", "'") | ||
match('"\r', '"') | ||
match("'\r\n", "'") | ||
match('"\r\n', '"') | ||
match("'\\\n") | ||
match('"\\\n') | ||
match("'\\\r") | ||
match('"\\\r') | ||
match("'\\\r\n") | ||
match('"\\\r\n') | ||
match("'", {closed: false}) | ||
match('"', {closed: false}) | ||
match("'unclosed", {closed: false}) | ||
match('"unclosed', {closed: false}) | ||
match("'\n", "'", {closed: false}) | ||
match('"\n', '"', {closed: false}) | ||
match("'\r", "'", {closed: false}) | ||
match('"\r', '"', {closed: false}) | ||
match("'\r\n", "'", {closed: false}) | ||
match('"\r\n', '"', {closed: false}) | ||
match("'\\\n", {closed: false}) | ||
match('"\\\n', {closed: false}) | ||
match("'\\\r", {closed: false}) | ||
match('"\\\r', {closed: false}) | ||
match("'\\\r\n", {closed: false}) | ||
match('"\\\r\n', {closed: false}) | ||
@@ -473,11 +481,5 @@ }) | ||
token("empty", function(match) { | ||
token("invalid", function(match) { | ||
match("") | ||
}) | ||
token("invalid", function(match) { | ||
match("@") | ||
@@ -484,0 +486,0 @@ match("#") |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27037
18
695
104