Skip to content

Commit

Permalink
chore(release): 4.0.0-rc.3
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Oct 8, 2020
1 parent f1a8491 commit dc6cd6a
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 93 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [4.0.0-rc.3](https://github.com/postcss-modules-local-by-default/compare/v4.0.0-rc.2...v4.0.0-rc.3) - 2020-10-08

### Fixes

- compatibility with plugins other plugins

## [4.0.0-rc.2](https://github.com/postcss-modules-local-by-default/compare/v4.0.0-rc.1...v4.0.0-rc.2) - 2020-10-08

### BREAKING CHANGE
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-modules-local-by-default",
"version": "4.0.0-rc.2",
"version": "4.0.0-rc.3",
"description": "A CSS Modules transform to make local scope the default",
"main": "src/index.js",
"author": "Mark Dalgleish",
Expand Down
182 changes: 90 additions & 92 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,17 @@ function normalizeNodeArray(nodes) {
}

function localizeNode(rule, mode, localAliasMap) {
const isScopePseudo = (node) =>
node.value === ":local" || node.value === ":global";
const isImportExportPseudo = (node) =>
node.value === ":import" || node.value === ":export";

const transform = (node, context) => {
if (context.ignoreNextSpacing && !isSpacing(node)) {
throw new Error("Missing whitespace after " + context.ignoreNextSpacing);
}

if (context.enforceNoSpacing && isSpacing(node)) {
throw new Error("Missing whitespace before " + context.enforceNoSpacing);
}

let newNodes;

switch (node.type) {
case "root": {
let resultingGlobal;
Expand Down Expand Up @@ -101,8 +98,9 @@ function localizeNode(rule, mode, localAliasMap) {
case "pseudo": {
let childContext;
const isNested = !!node.length;
const isScoped = isScopePseudo(node);
const isImportExport = isImportExportPseudo(node);
const isScoped = node.value === ":local" || node.value === ":global";
const isImportExport =
node.value === ":import" || node.value === ":export";

if (isImportExport) {
context.hasLocals = true;
Expand Down Expand Up @@ -303,91 +301,9 @@ function isWordAFunctionArgument(wordNode, functionNode) {
: false;
}

function localizeAnimationShorthandDeclValues(decl, context) {
const validIdent = /^-?[_a-z][_a-z0-9-]*$/i;

/*
The spec defines some keywords that you can use to describe properties such as the timing
function. These are still valid animation names, so as long as there is a property that accepts
a keyword, it is given priority. Only when all the properties that can take a keyword are
exhausted can the animation name be set to the keyword. I.e.
animation: infinite infinite;
The animation will repeat an infinite number of times from the first argument, and will have an
animation name of infinite from the second.
*/
const animationKeywords = {
$alternate: 1,
"$alternate-reverse": 1,
$backwards: 1,
$both: 1,
$ease: 1,
"$ease-in": 1,
"$ease-in-out": 1,
"$ease-out": 1,
$forwards: 1,
$infinite: 1,
$linear: 1,
$none: Infinity, // No matter how many times you write none, it will never be an animation name
$normal: 1,
$paused: 1,
$reverse: 1,
$running: 1,
"$step-end": 1,
"$step-start": 1,
$initial: Infinity,
$inherit: Infinity,
$unset: Infinity,
};

const didParseAnimationName = false;
let parsedAnimationKeywords = {};
let stepsFunctionNode = null;
const valueNodes = valueParser(decl.value).walk((node) => {
/* If div-token appeared (represents as comma ','), a possibility of an animation-keywords should be reflesh. */
if (node.type === "div") {
parsedAnimationKeywords = {};
}
if (node.type === "function" && node.value.toLowerCase() === "steps") {
stepsFunctionNode = node;
}
const value =
node.type === "word" && !isWordAFunctionArgument(node, stepsFunctionNode)
? node.value.toLowerCase()
: null;

let shouldParseAnimationName = false;

if (!didParseAnimationName && value && validIdent.test(value)) {
if ("$" + value in animationKeywords) {
parsedAnimationKeywords["$" + value] =
"$" + value in parsedAnimationKeywords
? parsedAnimationKeywords["$" + value] + 1
: 0;

shouldParseAnimationName =
parsedAnimationKeywords["$" + value] >=
animationKeywords["$" + value];
} else {
shouldParseAnimationName = true;
}
}

const subContext = {
options: context.options,
global: context.global,
localizeNextItem: shouldParseAnimationName && !context.global,
localAliasMap: context.localAliasMap,
};
return localizeDeclNode(node, subContext);
});

decl.value = valueNodes.toString();
}

function localizeDeclValues(localize, decl, context) {
const valueNodes = valueParser(decl.value);

valueNodes.walk((node, index, nodes) => {
const subContext = {
options: context.options,
Expand All @@ -404,7 +320,89 @@ function localizeDecl(decl, context) {
const isAnimation = /animation$/i.test(decl.prop);

if (isAnimation) {
return localizeAnimationShorthandDeclValues(decl, context);
const validIdent = /^-?[_a-z][_a-z0-9-]*$/i;

/*
The spec defines some keywords that you can use to describe properties such as the timing
function. These are still valid animation names, so as long as there is a property that accepts
a keyword, it is given priority. Only when all the properties that can take a keyword are
exhausted can the animation name be set to the keyword. I.e.
animation: infinite infinite;
The animation will repeat an infinite number of times from the first argument, and will have an
animation name of infinite from the second.
*/
const animationKeywords = {
$alternate: 1,
"$alternate-reverse": 1,
$backwards: 1,
$both: 1,
$ease: 1,
"$ease-in": 1,
"$ease-in-out": 1,
"$ease-out": 1,
$forwards: 1,
$infinite: 1,
$linear: 1,
$none: Infinity, // No matter how many times you write none, it will never be an animation name
$normal: 1,
$paused: 1,
$reverse: 1,
$running: 1,
"$step-end": 1,
"$step-start": 1,
$initial: Infinity,
$inherit: Infinity,
$unset: Infinity,
};

const didParseAnimationName = false;
let parsedAnimationKeywords = {};
let stepsFunctionNode = null;
const valueNodes = valueParser(decl.value).walk((node) => {
/* If div-token appeared (represents as comma ','), a possibility of an animation-keywords should be reflesh. */
if (node.type === "div") {
parsedAnimationKeywords = {};
}
if (node.type === "function" && node.value.toLowerCase() === "steps") {
stepsFunctionNode = node;
}
const value =
node.type === "word" &&
!isWordAFunctionArgument(node, stepsFunctionNode)
? node.value.toLowerCase()
: null;

let shouldParseAnimationName = false;

if (!didParseAnimationName && value && validIdent.test(value)) {
if ("$" + value in animationKeywords) {
parsedAnimationKeywords["$" + value] =
"$" + value in parsedAnimationKeywords
? parsedAnimationKeywords["$" + value] + 1
: 0;

shouldParseAnimationName =
parsedAnimationKeywords["$" + value] >=
animationKeywords["$" + value];
} else {
shouldParseAnimationName = true;
}
}

const subContext = {
options: context.options,
global: context.global,
localizeNextItem: shouldParseAnimationName && !context.global,
localAliasMap: context.localAliasMap,
};
return localizeDeclNode(node, subContext);
});

decl.value = valueNodes.toString();

return;
}

const isAnimationName = /animation(-name)?$/i.test(decl.prop);
Expand Down Expand Up @@ -444,7 +442,7 @@ module.exports = (options = {}) => {
const localAliasMap = new Map();

return {
Once(root) {
Root(root) {
const { icssImports } = extractICSS(root, false);

Object.keys(icssImports).forEach((key) => {
Expand Down

0 comments on commit dc6cd6a

Please sign in to comment.