+```
+
+
+
+
test
+
+
+
+ hi
+ {hello}
+ {/* another comment */}
+
+
+
+````
diff --git a/changelog_unreleased/scss/pr-6918.md b/changelog_unreleased/scss/pr-6918.md
new file mode 100644
index 000000000000..6dd3f4b12080
--- /dev/null
+++ b/changelog_unreleased/scss/pr-6918.md
@@ -0,0 +1,28 @@
+#### Don't add extra comma after last comment in map ([#6918](https://github.com/prettier/prettier/pull/6918) by [@fisker](https://github.com/fisker))
+
+Previously, when `trailingComma` set to `es5`, extra comma added after last comment in map.
+
+
+```scss
+// Input
+$my-map: (
+ 'foo': 1, // Comment
+ 'bar': 2, // Comment
+);
+
+// Prettier stable
+$my-map: (
+ "foo": 1,
+ // Comment
+ "bar": 2,
+ // Comment,
+);
+
+// Prettier master
+$my-map: (
+ "foo": 1,
+ // Comment
+ "bar": 2,
+ // Comment
+);
+```
diff --git a/changelog_unreleased/typescript/pr-6901.md b/changelog_unreleased/typescript/pr-6901.md
new file mode 100644
index 000000000000..e76629a99f65
--- /dev/null
+++ b/changelog_unreleased/typescript/pr-6901.md
@@ -0,0 +1,24 @@
+#### Fix formatting of type operator as arrow function return type ([#6901](https://github.com/prettier/prettier/pull/6901) by [@sosukesuzuki](https://github.com/sosukesuzuki))
+
+
+```ts
+// Input
+export const getVehicleDescriptor = async (
+ vehicleId: string
+): Promise<
+ Collections.Parts.PrintedCircuitBoardAssembly["attributes"] & undefined
+> => {};
+
+// Prettier stable
+export const getVehicleDescriptor = async (
+ vehicleId: string
+): Promise
=> {};
+
+// Prettier master
+export const getVehicleDescriptor = async (
+ vehicleId: string
+): Promise<
+ Collections.Parts.PrintedCircuitBoardAssembly["attributes"] & undefined
+> => {};
+```
diff --git a/changelog_unreleased/typescript/pr-7020.md b/changelog_unreleased/typescript/pr-7020.md
new file mode 100644
index 000000000000..76e2fabba7ae
--- /dev/null
+++ b/changelog_unreleased/typescript/pr-7020.md
@@ -0,0 +1,15 @@
+#### Print JSDoc-only types as is instead of throwing strange errors ([#7020](https://github.com/prettier/prettier/pull/7020) by [@thorn0](https://github.com/thorn0))
+
+
+```jsx
+// Input
+function fromFlow(arg: ?Maybe) {}
+
+// Prettier stable
+Error: unknown type: "TSJSDocNullableType"
+ at printPathNoParens (https://prettier.io/lib/standalone.js:26012:13)
+ at Object.genericPrint$3 [as print] (https://prettier.io/lib/standalone.js:23541:28)
+
+// Prettier master
+function fromFlow(arg: ?Maybe) {}
+```
diff --git a/cspell.json b/cspell.json
index 2dcef816911a..44bb5ded4f18 100644
--- a/cspell.json
+++ b/cspell.json
@@ -348,6 +348,7 @@
"Transloadit",
"TSAs",
"tsep",
+ "TSJS",
"Typeahead",
"typecasted",
"typeof",
diff --git a/docs/plugins.md b/docs/plugins.md
index ceee4982a7e5..4039a6997c44 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -45,6 +45,7 @@ Providing at least one path to `--plugin-search-dir`/`pluginSearchDirs` turns of
- [`@prettier/plugin-pug`](https://github.com/prettier/plugin-pug) by [**@Shinigami92**](https://github.com/Shinigami92)
- [`@prettier/plugin-ruby`](https://github.com/prettier/plugin-ruby)
- [`@prettier/plugin-swift`](https://github.com/prettier/plugin-swift)
+- [`@prettier/plugin-xml`](https://github.com/prettier/plugin-xml)
## Community Plugins
diff --git a/docs/rationale.md b/docs/rationale.md
index 67115f6798d3..1994a4047141 100644
--- a/docs/rationale.md
+++ b/docs/rationale.md
@@ -130,13 +130,11 @@ class OrderLine {
One final thing: TC39 has [not yet decided if decorators come before or after `export`](https://github.com/tc39/proposal-decorators/issues/69). In the meantime, Prettier supports both:
+
```js
-@decorator
-export class Foo {}
+@decorator export class Foo {}
-export
-@decorator
-class Foo {}
+export @decorator class Foo {}
```
### Semicolons
diff --git a/package.json b/package.json
index 007351eecfa4..d2bb0f055cfc 100644
--- a/package.json
+++ b/package.json
@@ -14,12 +14,12 @@
"node": ">=8"
},
"dependencies": {
- "@angular/compiler": "8.2.13",
+ "@angular/compiler": "8.2.14",
"@babel/code-frame": "7.5.5",
- "@babel/parser": "7.7.3",
+ "@babel/parser": "7.7.4",
"@glimmer/syntax": "0.41.0",
"@iarna/toml": "2.2.3",
- "@typescript-eslint/typescript-estree": "2.6.1",
+ "@typescript-eslint/typescript-estree": "2.9.0",
"angular-estree-parser": "1.1.5",
"angular-html-parser": "1.3.0",
"camelcase": "5.3.1",
@@ -35,7 +35,7 @@
"esutils": "2.0.3",
"find-parent-dir": "0.3.0",
"find-project-root": "1.1.1",
- "flow-parser": "0.111.3",
+ "flow-parser": "0.112.0",
"get-stream": "4.1.0",
"globby": "6.1.0",
"graphql": "14.5.8",
@@ -60,11 +60,11 @@
"postcss-media-query-parser": "0.2.3",
"postcss-scss": "2.0.0",
"postcss-selector-parser": "2.2.3",
- "postcss-values-parser": "1.5.0",
+ "postcss-values-parser": "2.0.1",
"regexp-util": "1.2.2",
"remark-math": "1.0.6",
"remark-parse": "5.0.0",
- "resolve": "1.12.0",
+ "resolve": "1.12.2",
"semver": "6.3.0",
"string-width": "4.1.0",
"typescript": "3.7.2",
@@ -75,8 +75,9 @@
},
"devDependencies": {
"@babel/core": "7.7.2",
- "@babel/preset-env": "7.7.1",
+ "@babel/preset-env": "7.7.4",
"@rollup/plugin-alias": "2.2.0",
+ "@rollup/plugin-json": "4.0.0",
"@rollup/plugin-replace": "2.2.1",
"babel-loader": "8.0.6",
"benchmark": "2.1.4",
@@ -84,12 +85,12 @@
"codecov": "3.6.1",
"cross-env": "6.0.3",
"eslint": "6.6.0",
- "eslint-config-prettier": "6.5.0",
+ "eslint-config-prettier": "6.7.0",
"eslint-formatter-friendly": "7.0.0",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-prettier": "3.1.1",
"eslint-plugin-react": "7.16.0",
- "execa": "3.2.0",
+ "execa": "3.3.0",
"jest": "23.3.0",
"jest-junit": "9.0.0",
"jest-snapshot-serializer-ansi": "1.0.0",
@@ -97,12 +98,10 @@
"jest-watch-typeahead": "0.4.2",
"mkdirp": "0.5.1",
"prettier": "1.19.1",
- "prettylint": "1.0.0",
"rimraf": "3.0.0",
- "rollup": "1.26.3",
+ "rollup": "1.27.5",
"rollup-plugin-babel": "4.3.3",
"rollup-plugin-commonjs": "10.1.0",
- "rollup-plugin-json": "4.0.0",
"rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-terser": "5.1.2",
@@ -126,7 +125,7 @@
"perf-benchmark": "yarn && yarn build && cross-env NODE_ENV=production node ./dist/bin-prettier.js --debug-benchmark --loglevel debug ${PERF_FILE:-./index.js} > /dev/null",
"check-types": "tsc",
"lint": "cross-env EFF_NO_LINK_RULES=true eslint . --format friendly",
- "lint-docs": "prettylint {.,docs,website,website/blog}/*.md",
+ "lint-docs": "prettier {.,docs,website,website/blog}/*.md --check",
"lint-dist": "eslint --no-eslintrc --no-ignore --env=browser \"dist/!(bin-prettier|index|third-party).js\"",
"build": "node --max-old-space-size=3072 ./scripts/build/build.js",
"build-docs": "node ./scripts/build-docs.js",
diff --git a/scripts/build/babel-plugins/replace-array-includes-with-indexof.js b/scripts/build/babel-plugins/replace-array-includes-with-indexof.js
index 18514344b78a..bc3700156192 100644
--- a/scripts/build/babel-plugins/replace-array-includes-with-indexof.js
+++ b/scripts/build/babel-plugins/replace-array-includes-with-indexof.js
@@ -2,14 +2,16 @@
//
// BEFORE:
-// [__something__].includes(__something__)
-// CONSTANT_CASE.includes(__something__)
+// foo.includes(bar)
//
// AFTER:
-// [__something__].indexOf(__something__) !== -1
-// CONSTANT_CASE.indexOf(__something__) !== -1
+// foo.indexOf(bar) !== -1
//
+// this plugin also replace `string.includes`,
+// filename is not changed
+// because it's temporary use for node@4 support
+
module.exports = ({ types: t }) => ({
visitor: {
CallExpression(path) {
@@ -17,11 +19,6 @@ module.exports = ({ types: t }) => ({
const callee = node.callee;
if (
t.isMemberExpression(callee, { computed: false }) &&
- (t.isArrayExpression(callee.object) ||
- (t.isIdentifier(callee.object) &&
- (/^[A-Z_]+$/.test(callee.object.name) ||
- // https://github.com/eemeli/yaml/blob/1005d01/src/Anchors.js#L45
- callee.object.name === "names"))) &&
t.isIdentifier(callee.property, { name: "includes" })
) {
callee.property.name = "indexOf";
diff --git a/scripts/build/bundler.js b/scripts/build/bundler.js
index 7cdc86387a16..b7a98e210a9b 100644
--- a/scripts/build/bundler.js
+++ b/scripts/build/bundler.js
@@ -8,7 +8,7 @@ const resolve = require("rollup-plugin-node-resolve");
const alias = require("@rollup/plugin-alias");
const commonjs = require("rollup-plugin-commonjs");
const nodeGlobals = require("rollup-plugin-node-globals");
-const json = require("rollup-plugin-json");
+const json = require("@rollup/plugin-json");
const replace = require("@rollup/plugin-replace");
const { terser } = require("rollup-plugin-terser");
const babel = require("rollup-plugin-babel");
@@ -42,6 +42,9 @@ function getBabelConfig(bundle) {
plugins: bundle.babelPlugins || [],
compact: bundle.type === "plugin" ? false : "auto"
};
+ config.plugins.push(
+ require.resolve("./babel-plugins/replace-array-includes-with-indexof")
+ );
if (bundle.type === "core") {
config.plugins.push(
require.resolve("./babel-plugins/transform-custom-require")
diff --git a/scripts/build/config.js b/scripts/build/config.js
index bacf937871f1..acfc0ef2209c 100644
--- a/scripts/build/config.js
+++ b/scripts/build/config.js
@@ -2,9 +2,6 @@
const path = require("path");
const PROJECT_ROOT = path.resolve(__dirname, "../..");
-const babelReplaceArrayIncludesWithIndexof = require.resolve(
- "./babel-plugins/replace-array-includes-with-indexof"
-);
/**
* @typedef {Object} Bundle
@@ -29,8 +26,7 @@ const babelReplaceArrayIncludesWithIndexof = require.resolve(
const parsers = [
{
input: "src/language-js/parser-babylon.js",
- target: "universal",
- babelPlugins: [babelReplaceArrayIncludesWithIndexof]
+ target: "universal"
},
{
input: "src/language-js/parser-flow.js",
@@ -40,12 +36,8 @@ const parsers = [
{
input: "src/language-js/parser-typescript.js",
target: "universal",
- babelPlugins: [babelReplaceArrayIncludesWithIndexof],
- commonjs: {
- ignore: [
- // Optional package for TypeScript that logs ETW events (a Windows-only technology).
- "@microsoft/typescript-etw"
- ]
+ replace: {
+ 'require("@microsoft/typescript-etw")': "undefined"
}
},
{
@@ -133,8 +125,7 @@ const parsers = [
replacement: require.resolve("lines-and-columns")
}
]
- },
- babelPlugins: [babelReplaceArrayIncludesWithIndexof]
+ }
}
].map(parser => {
const name = getFileOutput(parser)
diff --git a/scripts/generate-schema.js b/scripts/generate-schema.js
index e05d8db826c7..301181a01fec 100755
--- a/scripts/generate-schema.js
+++ b/scripts/generate-schema.js
@@ -18,7 +18,6 @@ function generateSchema(options) {
return {
$schema: "http://json-schema.org/draft-04/schema#",
title: "Schema for .prettierrc",
- type: "object",
definitions: {
optionsDefinition: {
type: "object",
@@ -65,9 +64,17 @@ function generateSchema(options) {
}
}
},
- allOf: [
- { $ref: "#/definitions/optionsDefinition" },
- { $ref: "#/definitions/overridesDefinition" }
+ oneOf: [
+ {
+ type: "object",
+ allOf: [
+ { $ref: "#/definitions/optionsDefinition" },
+ { $ref: "#/definitions/overridesDefinition" }
+ ]
+ },
+ {
+ type: "string"
+ }
]
};
}
diff --git a/src/language-css/clean.js b/src/language-css/clean.js
index bbfb3c8890a8..054428ce7088 100644
--- a/src/language-css/clean.js
+++ b/src/language-css/clean.js
@@ -1,7 +1,5 @@
"use strict";
-const htmlTagNames = require("html-tag-names");
-
function clean(ast, newObj, parent) {
[
"raw", // front-matter
@@ -142,10 +140,6 @@ function clean(ast, newObj, parent) {
if (ast.type === "selector-tag") {
const lowercasedValue = ast.value.toLowerCase();
- if (htmlTagNames.indexOf(lowercasedValue) !== -1) {
- newObj.value = lowercasedValue;
- }
-
if (["from", "to"].indexOf(lowercasedValue) !== -1) {
newObj.value = lowercasedValue;
}
diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js
index e67e41e14b39..b2b57ab00b65 100644
--- a/src/language-css/printer-postcss.js
+++ b/src/language-css/printer-postcss.js
@@ -36,7 +36,6 @@ const {
insideAtRuleNode,
insideURLFunctionInImportAtRuleNode,
isKeyframeAtRuleKeywords,
- isHTMLTag,
isWideKeywords,
isSCSS,
isLastNode,
@@ -341,8 +340,7 @@ function genericPrint(path, options, print) {
prevNode.type === "selector-nesting"
? node.value
: adjustNumbers(
- isHTMLTag(node.value) ||
- isKeyframeAtRuleKeywords(path, node.value)
+ isKeyframeAtRuleKeywords(path, node.value)
? node.value.toLowerCase()
: node.value
)
@@ -740,6 +738,9 @@ function genericPrint(path, options, print) {
const isSCSSMapItem = isSCSSMapItemNode(path);
+ const lastItem = node.groups[node.groups.length - 1];
+ const isLastItemComment = lastItem && lastItem.type === "value-comment";
+
return group(
concat([
node.open ? path.call(print, "open") : "",
@@ -773,7 +774,8 @@ function genericPrint(path, options, print) {
])
),
ifBreak(
- isSCSS(options.parser, options.originalText) &&
+ !isLastItemComment &&
+ isSCSS(options.parser, options.originalText) &&
isSCSSMapItem &&
shouldPrintComma(options)
? ","
diff --git a/src/language-css/utils.js b/src/language-css/utils.js
index 64174ceffb2e..a45e666caa31 100644
--- a/src/language-css/utils.js
+++ b/src/language-css/utils.js
@@ -1,7 +1,5 @@
"use strict";
-const htmlTagNames = require("html-tag-names");
-
const colorAdjusterFunctions = [
"red",
"green",
@@ -153,10 +151,6 @@ function isLastNode(path, node) {
return nodes && nodes.indexOf(node) === nodes.length - 1;
}
-function isHTMLTag(value) {
- return htmlTagNames.indexOf(value.toLowerCase()) !== -1;
-}
-
function isDetachedRulesetDeclarationNode(node) {
// If a Less file ends up being parsed with the SCSS parser, Less
// variable declarations will be parsed as atrules with names ending
@@ -400,7 +394,6 @@ module.exports = {
insideAtRuleNode,
insideURLFunctionInImportAtRuleNode,
isKeyframeAtRuleKeywords,
- isHTMLTag,
isWideKeywords,
isSCSS,
isLastNode,
diff --git a/src/language-js/clean.js b/src/language-js/clean.js
index 77b4b9f1b9d2..2801323f8a06 100644
--- a/src/language-js/clean.js
+++ b/src/language-js/clean.js
@@ -37,11 +37,6 @@ function clean(ast, newObj, parent) {
return null;
}
- // We remove unneeded parens around same-operator LogicalExpressions
- if (isUnbalancedLogicalTree(newObj)) {
- return rebalanceLogicalTree(newObj);
- }
-
// (TypeScript) Ignore `static` in `constructor(static p) {}`
// and `export` in `constructor(export p) {}`
if (
@@ -199,32 +194,4 @@ function clean(ast, newObj, parent) {
}
}
-function isUnbalancedLogicalTree(newObj) {
- return (
- newObj.type === "LogicalExpression" &&
- newObj.right.type === "LogicalExpression" &&
- newObj.operator === newObj.right.operator
- );
-}
-
-function rebalanceLogicalTree(newObj) {
- if (isUnbalancedLogicalTree(newObj)) {
- return rebalanceLogicalTree({
- type: "LogicalExpression",
- operator: newObj.operator,
- left: rebalanceLogicalTree({
- type: "LogicalExpression",
- operator: newObj.operator,
- left: newObj.left,
- right: newObj.right.left,
- loc: {}
- }),
- right: newObj.right.right,
- loc: {}
- });
- }
-
- return newObj;
-}
-
module.exports = clean;
diff --git a/src/language-js/comments.js b/src/language-js/comments.js
index 5447b7f7af9e..f5cefb375c83 100644
--- a/src/language-js/comments.js
+++ b/src/language-js/comments.js
@@ -66,7 +66,8 @@ function handleOwnLineComment(comment, text, options, ast, isLastComment) {
precedingNode,
comment,
options
- )
+ ) ||
+ handleLabeledStatementComments(enclosingNode, comment)
) {
return true;
}
diff --git a/src/language-js/loc.js b/src/language-js/loc.js
index e2d0e9586a0e..214de144cb2d 100644
--- a/src/language-js/loc.js
+++ b/src/language-js/loc.js
@@ -59,7 +59,24 @@ function locEnd(node) {
return loc;
}
+function composeLoc(startNode, endNode = startNode) {
+ const loc = {};
+ if (typeof startNode.start === "number") {
+ loc.start = startNode.start;
+ loc.end = endNode.end;
+ }
+ if (Array.isArray(startNode.range)) {
+ loc.range = [startNode.range[0], endNode.range[1]];
+ }
+ loc.loc = {
+ start: startNode.loc.start,
+ end: endNode.loc.end
+ };
+ return loc;
+}
+
module.exports = {
locStart,
- locEnd
+ locEnd,
+ composeLoc
};
diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js
index 6e92bda88e11..9ff9bba8755f 100644
--- a/src/language-js/needs-parens.js
+++ b/src/language-js/needs-parens.js
@@ -53,7 +53,7 @@ function hasClosureCompilerTypeCastComment(text, path) {
const cleaned = comment
.trim()
.split("\n")
- .map(line => line.replace(/^[\s*]+/, ""))
+ .map(line => line.replace(/^[\s*]+/, "").replace(/[\s*]+$/, ""))
.join(" ")
.trim();
if (!/^@type\s*\{[^]+\}$/.test(cleaned)) {
@@ -450,6 +450,7 @@ function needsParens(path, options) {
return false;
}
+ case "TSJSDocFunctionType":
case "TSConditionalType":
if (parent.type === "TSConditionalType" && node === parent.extendsType) {
return true;
@@ -477,7 +478,9 @@ function needsParens(path, options) {
parent.type === "TSOptionalType" ||
parent.type === "TSRestType" ||
(parent.type === "TSIndexedAccessType" && node === parent.objectType) ||
- parent.type === "TSTypeOperator"
+ parent.type === "TSTypeOperator" ||
+ (parent.type === "TSTypeAnnotation" &&
+ /^TSJSDoc/.test(path.getParentNode(1).type))
);
case "ArrayTypeAnnotation":
@@ -668,10 +671,8 @@ function needsParens(path, options) {
case "OptionalMemberExpression":
case "OptionalCallExpression":
if (
- ((parent.type === "MemberExpression" && name === "object") ||
- (parent.type === "CallExpression" && name === "callee")) &&
- // workaround for https://github.com/facebook/flow/issues/8159
- !(options.parser === "flow" && parent.range[0] === node.range[0])
+ (parent.type === "MemberExpression" && name === "object") ||
+ (parent.type === "CallExpression" && name === "callee")
) {
return true;
}
@@ -745,6 +746,7 @@ function needsParens(path, options) {
parent.type !== "AssignmentPattern" &&
parent.type !== "BinaryExpression" &&
parent.type !== "CallExpression" &&
+ parent.type !== "NewExpression" &&
parent.type !== "ConditionalExpression" &&
parent.type !== "ExpressionStatement" &&
parent.type !== "JsExpressionRoot" &&
diff --git a/src/language-js/parser-typescript.js b/src/language-js/parser-typescript.js
index 35401525d5fe..21bda1fa8563 100644
--- a/src/language-js/parser-typescript.js
+++ b/src/language-js/parser-typescript.js
@@ -30,7 +30,6 @@ function parse(text, parsers, opts) {
}
}
- delete ast.tokens;
includeShebang(text, ast);
return postprocess(ast, Object.assign({}, opts, { originalText: text }));
}
@@ -40,7 +39,6 @@ function tryParseTypeScript(text, jsx) {
return parser.parse(text, {
loc: true,
range: true,
- tokens: true,
comment: true,
useJSXTextNode: true,
jsx
diff --git a/src/language-js/postprocess.js b/src/language-js/postprocess.js
index 888140e259a7..bf4a9d178282 100644
--- a/src/language-js/postprocess.js
+++ b/src/language-js/postprocess.js
@@ -1,10 +1,18 @@
"use strict";
const { getLast } = require("../common/util");
+const { composeLoc } = require("./loc");
function postprocess(ast, options) {
visitNode(ast, node => {
switch (node.type) {
+ case "LogicalExpression": {
+ // We remove unneeded parens around same-operator LogicalExpressions
+ if (isUnbalancedLogicalTree(node)) {
+ return rebalanceLogicalTree(node);
+ }
+ break;
+ }
// fix unexpected locEnd caused by --no-semi style
case "VariableDeclaration": {
const lastDeclaration = getLast(node.declarations);
@@ -101,4 +109,40 @@ function visitNode(node, fn, parent, property) {
}
}
+function isUnbalancedLogicalTree(node) {
+ return (
+ node.type === "LogicalExpression" &&
+ node.right.type === "LogicalExpression" &&
+ node.operator === node.right.operator
+ );
+}
+
+function rebalanceLogicalTree(node) {
+ if (!isUnbalancedLogicalTree(node)) {
+ return node;
+ }
+
+ return rebalanceLogicalTree(
+ Object.assign(
+ {
+ type: "LogicalExpression",
+ operator: node.operator,
+ left: rebalanceLogicalTree(
+ Object.assign(
+ {
+ type: "LogicalExpression",
+ operator: node.operator,
+ left: node.left,
+ right: node.right.left
+ },
+ composeLoc(node.left, node.right.left)
+ )
+ ),
+ right: node.right.right
+ },
+ composeLoc(node)
+ )
+ );
+}
+
module.exports = postprocess;
diff --git a/src/language-js/preprocess.js b/src/language-js/preprocess.js
index 57489c7b7ae4..fc39070b8126 100644
--- a/src/language-js/preprocess.js
+++ b/src/language-js/preprocess.js
@@ -10,7 +10,8 @@ function preprocess(ast, options) {
return Object.assign({}, ast, {
type: options.parser.startsWith("__") ? "JsExpressionRoot" : "JsonRoot",
node: ast,
- comments: []
+ comments: [],
+ rootMarker: options.rootMarker
});
default:
return ast;
diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js
index 14a3fa9dacd1..49b4552e3182 100644
--- a/src/language-js/printer-estree.js
+++ b/src/language-js/printer-estree.js
@@ -120,6 +120,16 @@ const {
let uid = 0;
function shouldPrintComma(options, level) {
+ // angular does not allow trailing comma
+ if (
+ options.parser === "__ng_interpolation" ||
+ options.parser === "__ng_action" ||
+ options.parser === "__ng_binding" ||
+ options.parser === "__ng_directive"
+ ) {
+ return false;
+ }
+
level = level || "es5";
switch (options.trailingComma) {
@@ -599,7 +609,8 @@ function printPathNoParens(path, options, print, args) {
(parent.type === "ConditionalExpression" &&
parentParent.type !== "ReturnStatement" &&
parentParent.type !== "CallExpression" &&
- parentParent.type !== "OptionalCallExpression");
+ parentParent.type !== "OptionalCallExpression") ||
+ parent.type === "TemplateLiteral";
const shouldIndentIfInlining =
parent.type === "AssignmentExpression" ||
@@ -2471,7 +2482,11 @@ function printPathNoParens(path, options, print, args) {
(n.expressions[i].comments && n.expressions[i].comments.length) ||
n.expressions[i].type === "MemberExpression" ||
n.expressions[i].type === "OptionalMemberExpression" ||
- n.expressions[i].type === "ConditionalExpression"
+ n.expressions[i].type === "ConditionalExpression" ||
+ n.expressions[i].type === "LogicalExpression" ||
+ n.expressions[i].type === "BinaryExpression" ||
+ n.expressions[i].type === "SequenceExpression" ||
+ n.expressions[i].type === "TSAsExpression"
) {
printed = concat([indent(concat([softline, printed])), softline]);
}
@@ -3627,6 +3642,24 @@ function printPathNoParens(path, options, print, args) {
case "ArgumentPlaceholder":
return "?";
+
+ // These are not valid TypeScript. Printing them just for the sake of error recovery.
+ case "TSJSDocAllType":
+ return "*";
+ case "TSJSDocUnknownType":
+ return "?";
+ case "TSJSDocNullableType":
+ return concat(["?", path.call(print, "typeAnnotation")]);
+ case "TSJSDocNonNullableType":
+ return concat(["!", path.call(print, "typeAnnotation")]);
+ case "TSJSDocFunctionType":
+ return concat([
+ "function(",
+ // The parameters could be here, but typescript-estree doesn't convert them anyway (throws an error).
+ "): ",
+ path.call(print, "typeAnnotation")
+ ]);
+
default:
/* istanbul ignore next */
throw new Error("unknown type: " + JSON.stringify(n.type));
@@ -4573,6 +4606,7 @@ function printTypeParameters(path, options, print, paramsKey) {
}
const grandparent = path.getNode(2);
+ const greatGrandParent = path.getNode(3);
const greatGreatGrandParent = path.getNode(4);
const isParameterInTestCall = grandparent != null && isTestCall(grandparent);
@@ -4590,12 +4624,17 @@ function printTypeParameters(path, options, print, paramsKey) {
// See https://github.com/prettier/prettier/pull/6467 for the context.
(greatGreatGrandParent &&
greatGreatGrandParent.type === "VariableDeclarator" &&
- grandparent &&
grandparent.type === "TSTypeAnnotation" &&
+ greatGrandParent.type !== "ArrowFunctionExpression" &&
n[paramsKey][0].type !== "TSUnionType" &&
n[paramsKey][0].type !== "UnionTypeAnnotation" &&
+ n[paramsKey][0].type !== "TSIntersectionType" &&
+ n[paramsKey][0].type !== "IntersectionTypeAnnotation" &&
n[paramsKey][0].type !== "TSConditionalType" &&
- n[paramsKey][0].type !== "TSMappedType")));
+ n[paramsKey][0].type !== "TSMappedType" &&
+ n[paramsKey][0].type !== "TSTypeOperator" &&
+ n[paramsKey][0].type !== "TSIndexedAccessType" &&
+ n[paramsKey][0].type !== "TSArrayType")));
if (shouldInline) {
return concat(["<", join(", ", path.map(print, paramsKey)), ">"]);
@@ -5382,8 +5421,12 @@ function printJSXElement(path, options, print) {
containsMultipleAttributes ||
containsMultipleExpressions;
+ const isMdxBlock = path.getParentNode().rootMarker === "mdx";
+
const rawJsxWhitespace = options.singleQuote ? "{' '}" : '{" "}';
- const jsxWhitespace = ifBreak(concat([rawJsxWhitespace, softline]), " ");
+ const jsxWhitespace = isMdxBlock
+ ? concat([" "])
+ : ifBreak(concat([rawJsxWhitespace, softline]), " ");
const isFacebookTranslationTag =
n.openingElement &&
@@ -5503,6 +5546,10 @@ function printJSXElement(path, options, print) {
? fill(multilineChildren)
: group(concat(multilineChildren), { shouldBreak: true });
+ if (isMdxBlock) {
+ return content;
+ }
+
const multiLineElem = group(
concat([
openingLines,
diff --git a/src/language-markdown/embed.js b/src/language-markdown/embed.js
index bd53391318f8..d06de68f623a 100644
--- a/src/language-markdown/embed.js
+++ b/src/language-markdown/embed.js
@@ -57,7 +57,10 @@ function embed(path, print, textToDoc, options) {
case "importExport":
return textToDoc(node.value, { parser: "babel" });
case "jsx":
- return textToDoc(node.value, { parser: "__js_expression" });
+ return textToDoc(`<$>${node.value}$>`, {
+ parser: "__js_expression",
+ rootMarker: "mdx"
+ });
}
return null;
diff --git a/src/language-markdown/mdx.js b/src/language-markdown/mdx.js
index a725977779d7..f8bab299d4b6 100644
--- a/src/language-markdown/mdx.js
+++ b/src/language-markdown/mdx.js
@@ -26,7 +26,7 @@
const IMPORT_REGEX = /^import\s/;
const EXPORT_REGEX = /^export\s/;
-const BLOCKS_REGEX = "[a-z\\.]*(\\.){0,1}[a-z][a-z0-9\\.]*";
+const BLOCKS_REGEX = "[a-z][a-z0-9]*(\\.[a-z][a-z0-9]*)*|";
const COMMENT_REGEX = "|";
const EMPTY_NEWLINE = "\n\n";
diff --git a/src/language-markdown/parser-markdown.js b/src/language-markdown/parser-markdown.js
index 30b0b41b0335..5a33dc8a20d7 100644
--- a/src/language-markdown/parser-markdown.js
+++ b/src/language-markdown/parser-markdown.js
@@ -7,7 +7,6 @@ const parseFrontMatter = require("../utils/front-matter");
const { mapAst, INLINE_NODE_WRAPPER_TYPES } = require("./utils");
const mdx = require("./mdx");
const remarkMath = require("remark-math");
-const htmlParser = require("../language-html/parser-html").parsers.html;
/**
* based on [MDAST](https://github.com/syntax-tree/mdast) with following modifications:
@@ -60,29 +59,7 @@ function htmlToJsx() {
return node;
}
- const nodes = htmlParser.parse(node.value).children;
-
- // find out if there are adjacent JSX elements which should be allowed in mdx alike in markdown
- if (nodes.length <= 1) {
- return Object.assign({}, node, { type: "jsx" });
- }
-
- return nodes.reduce((newNodes, { sourceSpan: position, type }) => {
- const value = node.value.slice(
- position.start.offset,
- position.end.offset
- );
-
- if (value) {
- newNodes.push({
- type: type === "element" ? "jsx" : type,
- value,
- position
- });
- }
-
- return newNodes;
- }, []);
+ return Object.assign({}, node, { type: "jsx" });
});
}
diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js
index 16571274ccec..dc588f1ce7d6 100644
--- a/src/language-markdown/printer-markdown.js
+++ b/src/language-markdown/printer-markdown.js
@@ -25,7 +25,7 @@ const {
} = require("../doc");
const {
getFencedCodeBlockValue,
- getOrderedListItemInfo,
+ hasGitDiffFriendlyOrderedList,
splitText,
punctuationPattern,
INLINE_NODE_TYPES,
@@ -35,12 +35,7 @@ const { replaceEndOfLineWith } = require("../common/util");
const TRAILING_HARDLINE_NODES = ["importExport"];
const SINGLE_LINE_NODE_TYPES = ["heading", "tableCell", "link"];
-const SIBLING_NODE_TYPES = [
- "listItem",
- "definition",
- "footnoteDefinition",
- "jsx"
-];
+const SIBLING_NODE_TYPES = ["listItem", "definition", "footnoteDefinition"];
function genericPrint(path, options, print) {
const node = path.getValue();
@@ -251,11 +246,10 @@ function genericPrint(path, options, print) {
path.getParentNode()
);
- const isGitDiffFriendlyOrderedList =
- node.ordered &&
- node.children.length > 1 &&
- +getOrderedListItemInfo(node.children[1], options.originalText)
- .numberText === 1;
+ const isGitDiffFriendlyOrderedList = hasGitDiffFriendlyOrderedList(
+ node,
+ options
+ );
return printChildren(path, options, print, {
processor: (childPath, index) => {
@@ -770,55 +764,35 @@ function isPrettierIgnore(node) {
return match === null ? false : match[1] ? match[1] : "next";
}
-function isInlineNode(node) {
- return node && INLINE_NODE_TYPES.indexOf(node.type) !== -1;
-}
-
-function isEndsWithHardLine(node) {
- return node && /\n+$/.test(node.value);
-}
-
-function last(nodes) {
- return nodes && nodes[nodes.length - 1];
-}
-
-function shouldNotPrePrintHardline(node, { parentNode, parts, prevNode }) {
- const isFirstNode = parts.length === 0;
+function shouldNotPrePrintHardline(node, data) {
+ const isFirstNode = data.parts.length === 0;
+ const isInlineNode = INLINE_NODE_TYPES.indexOf(node.type) !== -1;
const isInlineHTML =
node.type === "html" &&
- INLINE_NODE_WRAPPER_TYPES.indexOf(parentNode.type) !== -1;
+ INLINE_NODE_WRAPPER_TYPES.indexOf(data.parentNode.type) !== -1;
- const isAfterHardlineNode =
- prevNode &&
- (isEndsWithHardLine(prevNode) ||
- isEndsWithHardLine(last(prevNode.children)));
-
- return (
- isFirstNode || isInlineNode(node) || isInlineHTML || isAfterHardlineNode
- );
+ return isFirstNode || isInlineNode || isInlineHTML;
}
-function shouldPrePrintDoubleHardline(node, { parentNode, prevNode }) {
- const prevNodeType = prevNode && prevNode.type;
- const nodeType = node.type;
-
- const isSequence = prevNodeType === nodeType;
+function shouldPrePrintDoubleHardline(node, data) {
+ const isSequence = (data.prevNode && data.prevNode.type) === node.type;
const isSiblingNode =
- isSequence && SIBLING_NODE_TYPES.indexOf(nodeType) !== -1;
+ isSequence && SIBLING_NODE_TYPES.indexOf(node.type) !== -1;
- const isInTightListItem = parentNode.type === "listItem" && !parentNode.loose;
- const isPrevNodeLooseListItem = prevNodeType === "listItem" && prevNode.loose;
- const isPrevNodePrettierIgnore = isPrettierIgnore(prevNode) === "next";
+ const isInTightListItem =
+ data.parentNode.type === "listItem" && !data.parentNode.loose;
- const isBlockHtmlWithoutBlankLineBetweenPrevHtml =
- nodeType === "html" &&
- prevNodeType === "html" &&
- prevNode.position.end.line + 1 === node.position.start.line;
+ const isPrevNodeLooseListItem =
+ data.prevNode && data.prevNode.type === "listItem" && data.prevNode.loose;
+
+ const isPrevNodePrettierIgnore = isPrettierIgnore(data.prevNode) === "next";
- const isJsxInlineSibling =
- (prevNodeType === "jsx" && isInlineNode(node)) ||
- (nodeType === "jsx" && isInlineNode(prevNode));
+ const isBlockHtmlWithoutBlankLineBetweenPrevHtml =
+ node.type === "html" &&
+ data.prevNode &&
+ data.prevNode.type === "html" &&
+ data.prevNode.position.end.line + 1 === node.position.start.line;
return (
isPrevNodeLooseListItem ||
@@ -826,8 +800,7 @@ function shouldPrePrintDoubleHardline(node, { parentNode, prevNode }) {
isSiblingNode ||
isInTightListItem ||
isPrevNodePrettierIgnore ||
- isBlockHtmlWithoutBlankLineBetweenPrevHtml ||
- isJsxInlineSibling
+ isBlockHtmlWithoutBlankLineBetweenPrevHtml
)
);
}
diff --git a/src/language-markdown/utils.js b/src/language-markdown/utils.js
index 702c7ccb7260..dd1f00528e2c 100644
--- a/src/language-markdown/utils.js
+++ b/src/language-markdown/utils.js
@@ -162,6 +162,34 @@ function getOrderedListItemInfo(orderListItem, originalText) {
return { numberText, marker, leadingSpaces };
}
+function hasGitDiffFriendlyOrderedList(node, options) {
+ if (!node.ordered) {
+ return false;
+ }
+
+ if (node.children.length < 2) {
+ return false;
+ }
+
+ const firstNumber = Number(
+ getOrderedListItemInfo(node.children[0], options.originalText).numberText
+ );
+
+ const secondNumber = Number(
+ getOrderedListItemInfo(node.children[1], options.originalText).numberText
+ );
+
+ if (firstNumber === 0 && node.children.length > 2) {
+ const thirdNumber = Number(
+ getOrderedListItemInfo(node.children[2], options.originalText).numberText
+ );
+
+ return secondNumber === 1 && thirdNumber === 1;
+ }
+
+ return secondNumber === 1;
+}
+
// workaround for https://github.com/remarkjs/remark/issues/351
// leading and trailing newlines are stripped by remark
function getFencedCodeBlockValue(node, originalText) {
@@ -202,21 +230,11 @@ function mapAst(ast, handler) {
return (function preorder(node, index, parentStack) {
parentStack = parentStack || [];
- let newNode = handler(node, index, parentStack);
- if (Array.isArray(newNode)) {
- return newNode;
- }
-
- newNode = Object.assign({}, newNode);
+ const newNode = Object.assign({}, handler(node, index, parentStack));
if (newNode.children) {
- newNode.children = newNode.children.reduce((nodes, child, index) => {
- let newNodes = preorder(child, index, [newNode].concat(parentStack));
- if (!Array.isArray(newNodes)) {
- newNodes = [newNodes];
- }
- nodes.push.apply(nodes, newNodes);
- return nodes;
- }, []);
+ newNode.children = newNode.children.map((child, index) => {
+ return preorder(child, index, [newNode].concat(parentStack));
+ });
}
return newNode;
@@ -229,6 +247,7 @@ module.exports = {
punctuationPattern,
getFencedCodeBlockValue,
getOrderedListItemInfo,
+ hasGitDiffFriendlyOrderedList,
INLINE_NODE_TYPES,
INLINE_NODE_WRAPPER_TYPES
};
diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap
index 6a5d630a409a..41c46208c33f 100644
--- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap
@@ -20,6 +20,48 @@ printWidth: 80
================================================================================
`;
+exports[`logical-expression.ng 2`] = `
+====================================options=====================================
+parsers: ["__ng_interpolation"]
+printWidth: 80
+trailingComma: "es5"
+ | printWidth
+=====================================input======================================
+[
+ advancedSearchService.patientInformationFieldsRow2 && advancedSearchService.patientInformationFieldsRow2.indexOf(advancedSearchService.formElementData.customFieldList[i].customFieldType) !== -1
+]
+
+=====================================output=====================================
+[
+ advancedSearchService.patientInformationFieldsRow2 &&
+ advancedSearchService.patientInformationFieldsRow2.indexOf(
+ advancedSearchService.formElementData.customFieldList[i].customFieldType
+ ) !== -1
+]
+================================================================================
+`;
+
+exports[`logical-expression.ng 3`] = `
+====================================options=====================================
+parsers: ["__ng_interpolation"]
+printWidth: 80
+trailingComma: "all"
+ | printWidth
+=====================================input======================================
+[
+ advancedSearchService.patientInformationFieldsRow2 && advancedSearchService.patientInformationFieldsRow2.indexOf(advancedSearchService.formElementData.customFieldList[i].customFieldType) !== -1
+]
+
+=====================================output=====================================
+[
+ advancedSearchService.patientInformationFieldsRow2 &&
+ advancedSearchService.patientInformationFieldsRow2.indexOf(
+ advancedSearchService.formElementData.customFieldList[i].customFieldType
+ ) !== -1
+]
+================================================================================
+`;
+
exports[`pipe-expression.ng 1`] = `
====================================options=====================================
parsers: ["__ng_interpolation"]
@@ -85,3 +127,137 @@ printWidth: 80
]
================================================================================
`;
+
+exports[`pipe-expression.ng 2`] = `
+====================================options=====================================
+parsers: ["__ng_interpolation"]
+printWidth: 80
+trailingComma: "es5"
+ | printWidth
+=====================================input======================================
+[
+ a ? (b | c : d) : (e | f : g),
+ a | b | c | d,
+ ((a | b) | c) | d,
+ a | b:(c | d),
+ { a: b | c },
+ (a + b) | c,
+ (a | b) + c,
+ fn(a | b),
+ a?.b(c | d),
+ a[b | c],
+ ($students | async).items,
+ ($students | async)(),
+ myData | myPipe:'arg1':'arg2':'arg3',
+ value
+ | pipeA: {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ } : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ | aaa,
+ (hideLinqPanel ? "ReportSelection.HideShowLabel_Show.String" : "ReportSelection.HideShowLabel_Hide.String") | localize:(localizationSection)
+]
+
+=====================================output=====================================
+[
+ a ? (b | c: d) : (e | f: g),
+ a | b | c | d,
+ a | b | c | d,
+ a | b: (c | d),
+ { a: b | c },
+ a + b | c,
+ (a | b) + c,
+ fn(a | b),
+ a?.b(c | d),
+ a[b | c],
+ ($students | async).items,
+ ($students | async)(),
+ myData | myPipe: "arg1":"arg2":"arg3",
+ value
+ | pipeA
+ : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ | aaa,
+ (hideLinqPanel
+ ? "ReportSelection.HideShowLabel_Show.String"
+ : "ReportSelection.HideShowLabel_Hide.String"
+ ) | localize: localizationSection
+]
+================================================================================
+`;
+
+exports[`pipe-expression.ng 3`] = `
+====================================options=====================================
+parsers: ["__ng_interpolation"]
+printWidth: 80
+trailingComma: "all"
+ | printWidth
+=====================================input======================================
+[
+ a ? (b | c : d) : (e | f : g),
+ a | b | c | d,
+ ((a | b) | c) | d,
+ a | b:(c | d),
+ { a: b | c },
+ (a + b) | c,
+ (a | b) + c,
+ fn(a | b),
+ a?.b(c | d),
+ a[b | c],
+ ($students | async).items,
+ ($students | async)(),
+ myData | myPipe:'arg1':'arg2':'arg3',
+ value
+ | pipeA: {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ } : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ | aaa,
+ (hideLinqPanel ? "ReportSelection.HideShowLabel_Show.String" : "ReportSelection.HideShowLabel_Hide.String") | localize:(localizationSection)
+]
+
+=====================================output=====================================
+[
+ a ? (b | c: d) : (e | f: g),
+ a | b | c | d,
+ a | b | c | d,
+ a | b: (c | d),
+ { a: b | c },
+ a + b | c,
+ (a | b) + c,
+ fn(a | b),
+ a?.b(c | d),
+ a[b | c],
+ ($students | async).items,
+ ($students | async)(),
+ myData | myPipe: "arg1":"arg2":"arg3",
+ value
+ | pipeA
+ : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ : {
+ keyA: reallySuperLongValue,
+ keyB: shortValue | pipeB | pipeC: valueToPipeC
+ }
+ | aaa,
+ (hideLinqPanel
+ ? "ReportSelection.HideShowLabel_Show.String"
+ : "ReportSelection.HideShowLabel_Hide.String"
+ ) | localize: localizationSection
+]
+================================================================================
+`;
diff --git a/tests/angular_interpolation/jsfmt.spec.js b/tests/angular_interpolation/jsfmt.spec.js
index 09a639b7b7f2..509a66203789 100644
--- a/tests/angular_interpolation/jsfmt.spec.js
+++ b/tests/angular_interpolation/jsfmt.spec.js
@@ -1 +1,3 @@
run_spec(__dirname, ["__ng_interpolation"]);
+run_spec(__dirname, ["__ng_interpolation"], { trailingComma: "es5" });
+run_spec(__dirname, ["__ng_interpolation"], { trailingComma: "all" });
diff --git a/tests/comments_closure_typecast/__snapshots__/jsfmt.spec.js.snap b/tests/comments_closure_typecast/__snapshots__/jsfmt.spec.js.snap
index 109e446fe308..e0650b287e5a 100644
--- a/tests/comments_closure_typecast/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/comments_closure_typecast/__snapshots__/jsfmt.spec.js.snap
@@ -156,3 +156,31 @@ const v8 = /**@type{string} */ (value);
================================================================================
`;
+
+exports[`extra-spaces-and-asterisks.js 1`] = `
+====================================options=====================================
+parsers: ["babel"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+const foo1 = /** @type {!Foo} */(bar);
+const foo2 = /** @type {!Foo} **/(bar);
+const foo3 = /** @type {!Foo} * */(bar);
+const foo4 = /** @type {!Foo} ***/(bar);
+const foo5 = /** @type {!Foo} * * */(bar);
+const foo6 = /** @type {!Foo} *****/(bar);
+const foo7 = /** @type {!Foo} * * * * */(bar);
+const foo8 = /** @type {!Foo} ** * * */(bar);
+
+=====================================output=====================================
+const foo1 = /** @type {!Foo} */ (bar);
+const foo2 = /** @type {!Foo} **/ (bar);
+const foo3 = /** @type {!Foo} * */ (bar);
+const foo4 = /** @type {!Foo} ***/ (bar);
+const foo5 = /** @type {!Foo} * * */ (bar);
+const foo6 = /** @type {!Foo} *****/ (bar);
+const foo7 = /** @type {!Foo} * * * * */ (bar);
+const foo8 = /** @type {!Foo} ** * * */ (bar);
+
+================================================================================
+`;
diff --git a/tests/comments_closure_typecast/extra-spaces-and-asterisks.js b/tests/comments_closure_typecast/extra-spaces-and-asterisks.js
new file mode 100644
index 000000000000..45572417a5b1
--- /dev/null
+++ b/tests/comments_closure_typecast/extra-spaces-and-asterisks.js
@@ -0,0 +1,8 @@
+const foo1 = /** @type {!Foo} */(bar);
+const foo2 = /** @type {!Foo} **/(bar);
+const foo3 = /** @type {!Foo} * */(bar);
+const foo4 = /** @type {!Foo} ***/(bar);
+const foo5 = /** @type {!Foo} * * */(bar);
+const foo6 = /** @type {!Foo} *****/(bar);
+const foo7 = /** @type {!Foo} * * * * */(bar);
+const foo8 = /** @type {!Foo} ** * * */(bar);
diff --git a/tests/css_case/__snapshots__/jsfmt.spec.js.snap b/tests/css_case/__snapshots__/jsfmt.spec.js.snap
index a70a18a56933..75cef87b0149 100644
--- a/tests/css_case/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/css_case/__snapshots__/jsfmt.spec.js.snap
@@ -94,7 +94,7 @@ a:after {
background-color: orange;
}
-table {
+TABLE {
}
/* apply a dashed border to all unresolved elements */
@@ -298,7 +298,7 @@ TABLE {}
@import Keep;
-html#KeepId.KeepClass,
+HTML#KeepId.KeepClass,
a[HREF="KeepAttrValue"]:hover::first-letter,
svg[viewBox] linearGradient,
:not(:nth-child(2n + 1)) {
@@ -358,7 +358,7 @@ $KeepScssVar: val;
prop: val;
};
- &Keep & element {
+ &Keep & Element {
prop: val;
}
@@ -438,7 +438,7 @@ a:after {
background-color: orange;
}
-table {
+TABLE {
}
.foo {
@@ -616,7 +616,7 @@ TABLE {}
@import Keep;
-html#KeepId.KeepClass,
+HTML#KeepId.KeepClass,
a[HREF="KeepAttrValue"]:hover::first-letter,
svg[viewBox] linearGradient,
:not(:nth-child(2n + 1)) {
@@ -680,7 +680,7 @@ $KeepTopLevelVar: val;
prop: val;
}
- &Keep & element {
+ &Keep & Element {
prop: val;
}
@@ -755,7 +755,7 @@ a:after {
background-color: orange;
}
-table {
+TABLE {
}
.foo {
diff --git a/tests/css_scss/__snapshots__/jsfmt.spec.js.snap b/tests/css_scss/__snapshots__/jsfmt.spec.js.snap
index 954b2644213d..fc75d517c053 100644
--- a/tests/css_scss/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/css_scss/__snapshots__/jsfmt.spec.js.snap
@@ -14,6 +14,21 @@ printWidth: 80
================================================================================
`;
+exports[`import_comma.scss 2`] = `
+====================================options=====================================
+parsers: ["scss"]
+printWidth: 80
+trailingComma: "es5"
+ | printWidth
+=====================================input======================================
+@import "rounded-corners", "text-shadow";
+
+=====================================output=====================================
+@import "rounded-corners", "text-shadow";
+
+================================================================================
+`;
+
exports[`scss.scss 1`] = `
====================================options=====================================
parsers: ["scss"]
@@ -2035,3 +2050,2026 @@ label {
================================================================================
`;
+
+exports[`scss.scss 2`] = `
+====================================options=====================================
+parsers: ["scss"]
+printWidth: 80
+trailingComma: "es5"
+ | printWidth
+=====================================input======================================
+@media #{$g-breakpoint-tiny} {}
+.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
+a {height: calc(#{$foo} + 1);}
+div {
+ background: {
+ size: auto 60%;
+ position: bottom 2px left;
+ }
+}
+a { margin: 0 { left: 10px; } }
+
+$default: #111111 !default;
+$default: #111111 !default;
+$default: #111111
+!default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value" !default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value" !default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value"
+!default;
+
+$global: #111111 !global;
+$global: #111111 !global;
+$global: #111111
+!global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value" !global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value" !global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value"
+!global;
+
+$map: (key: value, other-key: other-value);
+$map: (key: value, other-key: other-value) !default;
+$map: (key: value, other-key: other-value) !default;
+$map: (key: value, other-key: other-value)
+!default;
+$map:
+(key: value, other-key: other-value)
+!default;
+$map: ( key : value , other-key : other-value);
+$map: ( key : value , other-key : other-value );
+$map: (
+ key: value,
+ other-key: other-value
+);
+$map: (
+key: value,
+other-key: other-value
+);
+$map: (
+key
+:
+value,
+other-key
+:
+other-value
+);
+$map: (
+key
+:
+value
+,
+other-key
+:
+other-value
+);
+$map: (very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value, very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value);
+$map: ( very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key : very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value , very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key : very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value );
+$map: ( very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key : very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value , very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value );
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value
+);
+$map: (
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key: very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value
+);
+$map:
+(
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key
+:
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value
+,
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key
+:
+very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value
+);
+$map: (
+ key: (#d82d2d, #666),
+ other-key: (#52bf4a, #fff),
+ other-other-key: (#c23435, #fff)
+);
+$map: (
+key: (#d82d2d, #666),
+other-key: (#52bf4a, #fff),
+other-other-key: (#c23435, #fff)
+);
+$map: (
+ key : ( #d82d2d , #666 ),
+ other-key : ( #52bf4a , #fff ),
+ other-other-key : ( #c23435 , #fff )
+);
+$map: (
+ key : ( #d82d2d , #666 ) ,
+ other-key : ( #52bf4a , #fff ),
+ other-other-key : ( #c23435 , #fff )
+);
+$map: (
+key
+:
+(
+#d82d2d,
+#666
+)
+,
+other-key
+:
+(
+#52bf4a,
+#fff
+)
+,
+other-other-key
+:
+(
+#c23435
+,
+#fff
+)
+);
+$map: map-merge($map, ($key: $value));
+$map: map-merge( $map , ( $key : $value ) );
+$map: map-merge( $map , ( $key : $value ) );
+$map: map-merge(
+ $map,
+ ($key: $value)
+);
+$map: map-merge(
+$map,
+($key: $value)
+);
+$map:
+map-merge(
+$map
+,
+(
+$key
+:
+$value
+)
+);
+
+$longVariable: (
+(mobile $mobile) (tablet $tablet) (desktop $desktop) (wide $wide)
+);
+
+$list-space: "item-1" "item-2" "item-3";
+$list-space:"item-1""item-2""item-3";
+$list-space: "item-1" "item-2" "item-3" ;
+$list-space: "item-1"
+ "item-2"
+ "item-3";
+$list-space
+:
+"item-1"
+"item-2"
+"item-3"
+;
+$list-space
+
+:
+
+"item-1"
+
+"item-2"
+
+"item-3"
+
+;
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma:"item-1","item-2","item-3";
+$list-comma: "item-1" , "item-2" , "item-3" ;
+$list-comma: "item-1",
+ "item-2",
+ "item-3";
+$list-comma
+:
+"item-1"
+,
+"item-2"
+,
+"item-3"
+;
+$list-comma
+
+:
+
+"item-1"
+
+,
+
+"item-2"
+
+,
+
+"item-3"
+
+;
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3", "item-3.1" "item-3.2" "item-3.3";
+$list:"item-1.1""item-1.2""item-1.3","item-2.1""item-2.2""item-2.3","item-3.1""item-3.2""item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3" , "item-2.1" "item-2.2" "item-2.3" , "item-3.1" "item-3.2" "item-3.3" ;
+$list: "item-1.1" "item-1.2" "item-1.3",
+ "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list
+:
+"item-1.1"
+"item-1.2"
+"item-1.3"
+,
+"item-2.1"
+"item-2.2"
+"item-2.3"
+,
+"item-3.1"
+"item-3.2"
+"item-3.3"
+;
+$list
+
+:
+
+"item-1.1"
+
+"item-1.2"
+
+"item-1.3"
+
+,
+
+"item-2.1"
+
+"item-2.2"
+
+"item-2.3"
+
+,
+
+"item-3.1"
+
+"item-3.2"
+
+"item-3.3"
+
+;
+$list: (("item-1.1", "item-1.2", "item-1.3"), ("item-2.1", "item-2.2", "item-2.3"), ("item-3.1", "item-3.2", "item-3.3"));
+$list:(("item-1.1","item-1.2","item-1.3"),("item-2.1","item-2.2","item-2.3"),("item-3.1","item-3.2","item-3.3"));
+$list: ( ( "item-1.1" , "item-1.2" , "item-1.3" ) , ( "item-2.1" , "item-2.2" , "item-2.3" ) , ( "item-3.1" , "item-3.2" , "item-3.3" ) ) ;
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list
+:
+(
+(
+"item-1.1"
+,
+"item-1.2"
+,
+"item-1.3"
+)
+,
+(
+"item-2.1"
+,
+"item-2.2"
+,
+"item-2.3"
+)
+,
+(
+"item-3.1"
+,
+"item-3.2"
+,
+"item-3.3"
+)
+)
+;
+$list
+
+:
+
+(
+
+(
+
+"item-1.1"
+
+,
+
+"item-1.2"
+
+,
+
+"item-1.3"
+
+)
+
+,
+
+(
+
+"item-2.1"
+
+,
+
+"item-2.2"
+
+,
+
+"item-2.3"
+
+)
+
+,
+
+(
+
+"item-3.1"
+
+,
+
+"item-3.2"
+
+,
+
+"item-3.3"
+
+)
+
+)
+
+;
+
+$var: (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0);
+$space-scale: (0, "0") (0.25, "0-25") (0.5, "0-5") (0.75, "0-75") (1, "1") (1.25, "1-25") (1.5, "1-5") (1.75, "1-75") (2, "2") (2.25, "2-25") (2.5, "2-5") (2.75, "2-75") (3, "3") (3.25, "3-25") (3.5, "3-5") (3.75, "3-75") (4, "4");
+
+.card-column-simple {
+ @include breakpoint( getBp( md ) ) {
+ padding: $spacing_content-sm $spacing_content-md;
+ }
+
+ @include breakpoint (getBp(md)) {
+ &:nth-child(2n + 3) {
+ clear: both;
+ }
+ }
+
+ @include breakpoint (getBp(xl)) {
+ &:nth-child(2n + 3) {
+ clear: none;
+ }
+ &:nth-child(3n + 4) {
+ clear: both;
+ }
+ }
+}
+
+@warn "Warn (#{$message}).";
+@warn "Warn (#{$message}).";
+@warn "Warn (#{$message}).";
+@warn #{$message};
+@warn "Very long long long long long long long long long long long long long line (#{$message}).";
+@warn
+ "Very long long long long long long long long long long long long long line (#{$message}).";
+@error "Error (#{$message}).";
+@error "Error (#{$message}).";
+@error "Error (#{$message}).";
+@error #{$message};
+@error "Very long long long long long long long long long long long long long line Error (#{$message}).";
+@error
+ "Very long long long long long long long long long long long long long line Error (#{$message}).";
+
+$buttonConfig: "save" 50px, 'cancel' 50px, "help" 100PX;
+
+$locale: "en_us";
+html[lang=#{$locale}] {
+ font-size: 10px;
+}
+$alertClass: "error";
+p.message-#{$alertClass} {
+ color: red;
+}
+$mediumBreakpoint: 768px;
+@media (max-width: #{$mediumBreakpoint}) {
+ a {
+ font-size: 18px;
+ }
+}
+
+p {
+ @media (max-width: 768px) {
+ font-size: 150%;
+
+ @media (orientation: landscape) {
+ line-height: 75%;
+ }
+ }
+}
+
+.popularAnimal {
+ background: gray;
+}
+.GoodBoy {
+ color: green;
+}
+.dog {
+ @extend .popularAnimal;
+ @extend .GoodBoy;
+ color: white;
+}
+
+%animal {
+ background: gray;
+}
+.cat {
+ @extend %animal;
+ color: white;
+}
+.dog {
+ @extend %animal;
+ color: black;
+}
+
+%mfw-standing-out {
+ font-size: 150%;
+ font-style: italic;
+ padding: 25px;
+}
+%mfwSlightlyShadowed {
+ @include box-shadow(black 2px 2px 10px); // from Compass
+}
+%MFWRounded {
+ @include border-radius(25px); // from Compass
+}
+#join-button {
+ @extend %mfw-standing-out;
+ @extend %mfwSlightlyShadowed;
+ @extend %MFWRounded;
+ background: green;
+ color: white;
+}
+
+a {
+ &:hover {
+ color: red;
+ }
+}
+p {
+ body.no-touch & {
+ display: none;
+ }
+}
+.foo.bar .baz.bang, .bip.qux {
+ $selector: &;
+}
+@mixin does-parent-exist {
+ @if & {
+ &:hover {
+ color: red;
+ }
+ } @else {
+ a {
+ color: red;
+ }
+ }
+}
+
+p {
+ @if 1 + 1 == 2 {
+ border: 1px solid;
+ }
+ @if 5 < 3 {
+ border: 2px dotted;
+ }
+ @if null {
+ border: 3px double;
+ }
+}
+
+$mosterType: monster;
+p {
+ @if $mosterType == ocean {
+ color: blue;
+ } @else if $mosterType == matador {
+ color: red;
+ } @else if $mosterType == monster {
+ color: green;
+ } @else if $mosterType == nightKing {
+ color: green;
+ } @else if $mosterType == VeryWickedWolf {
+ color: green;
+ } @else {
+ color: black;
+ }
+}
+
+@for $i from 1 through 3 {
+ .item-#{$i} {
+ width: 2em * $i;
+ }
+}
+
+@each $animal in puma, sea-slug, cheerfulDog, BigSalamander, "string", 'another-string', "camelCaseString", "PascalCaseString" {
+ .#{$animal}-icon {
+ background-image: url('/images/#{$animal}.png');
+ }
+}
+
+$i: 6;
+@while $i > 0 {
+ .item-#{$i} {
+ width: 2em * $i;
+ }
+ $i: $i - 2;
+}
+
+@mixin cool-border($width: 10px, $coolStyle: 'solid', $AwesomeColor: "black") {
+ border: $width $coolStyle $AwesomeColor;
+}
+
+p {
+ @include cool-border(1px, "solid", $fff);
+}
+p {
+ @include cool-border($width: 1px, $coolStyle: 'solid', $AwesomeColor: #fff);
+}
+p {
+ @include coolBorder();
+}
+
+@mixin coolBorder() {
+ border: 10px solid #fff;
+}
+p {
+ @include coolBorder(1px, "solid", $fff);
+}
+
+@mixin CoolBorder() {
+ border: 10px solid #fff;
+}
+p {
+ @include CoolBorder(1px, "solid", $fff);
+}
+
+@mixin box-shadow($shadows...) {
+ -moz-box-shadow: $shadows;
+ -webkit-box-shadow: $shadows;
+ box-shadow: $shadows;
+}
+.shadows {
+ @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
+}
+
+@mixin apply-to-ie6-only {
+ * html {
+ @content;
+ }
+}
+@include apply-to-ie6-only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin applyToIe6Only {
+ * html {
+ @content;
+ }
+}
+@include applyToIe6Only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin ApplyToIe6Only {
+ * html {
+ @content;
+ }
+}
+@include ApplyToIe6Only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin config-icon-colors($prefix, $colors...) {
+ @each $i in $colors {
+ .#{$prefix}#{nth($i, 1)} {
+ color: nth($i, 2);
+ }
+ }
+}
+@include config-icon-colors(
+ "icon-",
+ "save" green,
+ "cancel" gray,
+ "delete" red,
+ 'wait' blue
+);
+
+@function my-calculation-function($some-number, $anotherNumber, $BigNumber){
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function myCalculationFunction($some-number, $anotherNumber, $BigNumber){
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function AnotherMyCalculationFunction($some-number, $anotherNumber, $BigNumber: 100px){
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function border($borders...) {
+ @return $borders;
+}
+.foo {
+ padding: my-calculation-function(10px, 5px, 100px);
+ margin: myCalculationFunction($some-number: 10px, $anotherNumber: 5px, $BigNumber: 100px);
+ width: AnotherMyCalculationFunction(10px, 5px);
+ border: border(25px, 35px);
+}
+
+$sm-only: '(min-width: 768px) and (max-width: 991px)';
+$lg-and-up: '(min-width: 1200px)';
+
+@media screen and #{$sm-only, $lg-and-up} {
+ color: #000;
+}
+
+.class-#{$var} {
+ #{$var}: #7b3d66;
+ #{$attr}-color: blue;
+ #{$prop}-#{$side}: $value;
+ background-#{$var}: #7b3d66;
+ animation-name: #{var};
+ line-height: #{strip-unit($line-height)}em;
+ height: 1#{$var};
+ width: calc(100% - #{$sidebar-width});
+ max-width: calc(#{$m*100}vw #{$sign} #{$b});
+ font: #{$font-size}/#{$line-height};
+ content: "I have #{8 + 2} books on SASS!";
+ border: #{$var} #{$var} #{$var};
+ filter: #{$var}#{$var}#{$var};
+ prop: #{ $var + $var } #{ $var + $var } #{ $var + $var };
+ prop2:
+ #{
+ $var
+ +
+ $var
+ }
+
+ #{
+ $var
+ +
+ $var
+ }
+
+ #{
+ $var
+ +
+ $var
+ }
+ ;
+ prop3:
+
+ #{
+
+ $var
+
+ +
+
+ $var
+
+ }
+
+ #{
+
+ $var
+
+ +
+
+ $var
+
+ }
+
+ #{
+
+ $var
+
+ +
+
+ $var
+
+ }
+ ;
+ prop4: -#{$loader-icon-duration};
+ prop5: +#{$loader-icon-duration};
+ prop6: calc(-#{$loader-icon-duration} + 10);
+ prop7: calc(10 + -#{$loader-icon-duration});
+}
+
+/* Framework version for the generated CSS is #{$version}. */
+
+.selector {
+ foo: bar;
+ #{$active} {
+ baz: qux;
+ }
+}
+
+.el:nth-of-type(#{$i}) {}
+
+@media #{$value} {}
+
+@import url(#{$foundation-dir}/foundation/components/grid);
+
+@keyframes loader {
+ 0% {
+ transform: translate3d(0, 0, 0);
+ }
+
+ #{50% - $loader-icon-duration} {
+ transform: translate3d(0, $bounce-height, 0);
+ }
+
+ 50% {
+ transform: translate3d(0, $bounce-height, 0) scale($loader-bounce-horizontal-expansion, $loader-bounce-vertical-compression);
+ }
+}
+
+$icons: wifi "\\600", wifi-hotspot "\\601", weather "\\602";
+
+@each $icon in $icons {
+ .icon-#{nth($icon, 1)}, %icon-#{nth($icon, 1)} {
+ content: "#{nth($icon, 2)}";
+ }
+}
+
+.foo {
+ prop: -($grid-gutter-width / 2);
+ prop1: -( $grid-gutter-width / 2 );
+ prop2: -$grid-gutter-width / 2;
+ prop3: +($grid-gutter-width / 2);
+ prop4: 10px/8px; /* Plain CSS, no division */
+ prop5: $width / 2; /* Uses a variable, does division */
+ prop6: round(1.5) / 2; /* Uses a function, does division */
+ prop7: (500px / 2); /* Uses parentheses, does division */
+ prop8: 5px + 8px / 2px; //* Uses +, does division */
+ prop9: (italic bold 10px/8px); /* In a list, parentheses don't count */
+ prop10: #010203 + #040506;
+ prop11: #010203 * 2;
+ prop12: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
+ prop13: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}');
+ prop14: e + -resize;
+ prop15: sans- + "serif";
+ prop16: 1em + (2em * 3);
+ prop17: rotate(-2deg);
+ prop18: rotate( -2deg ) ;
+ _:_;
+ prop19: 10 - ($grid-gutter-width / 2);
+ prop20: 10 + -($grid-gutter-width / 2);
+ prop21: 10 + - ( $grid-gutter-width / 2 ) ;
+ prop22: - ( $grid-gutter-width / 2 ) ;
+ prop23: - ( $grid-gutter-width / 2 ) ;
+ prop24: -$grid-gutter-width;
+ prop25: + ( $grid-gutter-width / 2 ) ;
+ prop26: + ( $grid-gutter-width / 2 ) ;
+ prop27: +$grid-gutter-width;
+ prop28: --($grid-gutter-width / 2);
+ prop28: ++($grid-gutter-width / 2);
+ prop29: rotate( - 2deg ) ;
+}
+
+$last:nth($juggler,length($juggler));
+$x:if($last%2==0,1/2,3/2);
+$new:pow($last,$x);
+$sequence:1,1 1,2 1,1 2 1 1, 1 1 1 2 2 1;
+$new-entry:();
+$new-entry : ( ) ;
+$new-entry : ( ) ;
+$new-entry
+:
+(
+)
+;
+
+body:before {
+ content: quote(to-string(fibonacci(100), ' \\A '));
+ white-space: pre-wrap;
+}
+
+width: ((100% - (($numPerRow - 1) * $margin)) / $numPerRow);
+width
+:
+(
+(
+100%
+-
+(
+(
+$numPerRow
+-
+1
+)
+*
+$margin
+)
+)
+/
+$numPerRow
+)
+;
+
+a:nth-child(#{$numPerRow}n) {
+ margin-right: 0;
+ margin-bottom: 0;
+}
+
+@function em($pixels, $context: $browser-context) {
+ @return #{ $pixels / $context }em
+}
+
+.navigation {
+ @extend %updated-#{$flag};
+ @extend .selected-#{$flag};
+ @extend %#{$item};
+}
+
+.icon-#{$icon-name} {
+ background-image: '/images/#{$icon-name}.svg';
+}
+
+$extmods:(eot:"?",svg:"#" + str-replace($name," ","_"));
+
+@mixin keyframes {@-moz-keyframes{@content;}@-webkit-keyframes{@content;}}
+
+@function gcd($a,$b){
+ // From: http://rosettacode.org/wiki/Greatest_common_divisor#JavaScript
+ @if ($b != 0) {
+ @return gcd($b,$a % $b);
+ }@else{
+ @return abs($a);
+ }
+}
+
+$colors: (
+primary: (
+base: #00abc9,
+light: #daf1f6,
+dark: #12799a
+),
+secondary: (
+base: #424d55,
+light: #ccc,
+lightest: #efefef,
+dark: #404247
+),
+success: (
+base: #bbd33e,
+light: #eaf0c6
+)
+);
+
+@function color($color, $tone: "base") {
+@return map-get(map-get($colors, $color), $tone);
+}
+
+@media only screen and (max-width: 767px) {
+ @include widths(2 3 4, \\@small);
+}
+
+$widths-breakpoint-separator: \\@small;
+
+a {
+ transition-timing-function: func1(
+ func2(
+ func3(
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ ),
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ ),
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ func3(
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue"
+ )
+ );
+}
+
+$empty-map: ();
+$empty-nested-map: (
+nested-key: (empty-key: (color: red)),
+empty-key: (),
+empty-key: (),
+empty-key: ()
+);
+
+$o-grid-default-config: (
+columns: 12,
+gutter: 10px,
+min-width: 240px,
+max-width: 1330px,
+layouts: (
+S: 370px,
+M: 610px,
+L: 850px,
+XL: 1090px
+),
+fluid: true,
+debug: false,
+fixed-layout: M,
+enhanced-experience: true
+);
+
+$a: ();
+$b: unquote('');
+$c: null;
+$d: (null);
+
+$threads-properties: map-merge($threads-properties, ($border-label: ()));
+$o-grid-default-config: (layouts: (S: 370px));
+
+$map: (
+key: (value),
+other-key: (key: other-other-value)
+);
+
+a {
+ content: "#{".5"}";
+ content: my-fn("_");
+ content: "#{my-fn("_")}";
+ content: my-fn("-");
+ content: "#{my-fn("-")}";
+ content: my-fn("-a");
+ content: "#{my-fn("-a")}";
+ content: my-fn("a-");
+ content: "#{my-fn("a-")}";
+ content: my-fn("foo");
+ content: "#{my-fn("foo")}";
+ content: 1 "#{my-fn("foo")}" 2;
+ content: foo "#{my-fn("foo")}" bar;
+ content: "foo #{$description} bar";
+
+ content: "#{my-fn("foo","bar")}";
+ content: "#{my-fn( "foo" , "bar" )}";
+ content: "#{my-fn( "foo" , "bar" )}";
+
+ content: '#{my-fn("foo")}';
+ content: '#{my-fn('foo')}';
+ content: "#{my-fn('foo')}";
+ content: "#{my-fn("foo")}";
+}
+
+mixin theme($css-property, $css-value, $theme-classes: t) {
+ @each $selector in & {
+ @each $class in $theme-classes {
+ @each $theme, $theme-properties in c(themes) {
+ $value: $css-value;
+
+ @each $theme-name, $theme-value in $theme-properties {
+ $rgba-value: "rgba(#{red($theme-value)}, #{green($theme-value)}, #{blue($theme-value)}";
+ $value: str-replace($value, "rgba(\${#{$theme-name}}", $rgba-value);
+ $value: str-replace($value, "\${#{$theme-name}}", $theme-value);
+ }
+
+ @at-root .#{$class}-#{join($theme, $selector)} {
+ #{$css-property}: unquote($value);
+ }
+ }
+ }
+ }
+}
+
+.foo,
+// Comment
+.bar {
+ // Comment
+ color: red; // Comment
+}
+
+$my-list:
+ 'foo', // Comment
+ 'bar'; // Comment
+
+$my-map: (
+ 'foo': 1, // Comment
+ 'bar': 2, // Comment
+);
+
+[href]:hover &, // Comment
+[href]:focus &, // Comment
+[href]:active & {
+ .tooltip {
+ opacity: 1;
+ }
+}
+
+@import
+ // Comment
+ 'mixins',
+ 'variables',
+ // Comment
+ 'reset',
+ 'scaffolding',
+ 'type',
+ // Comment
+ 'bar',
+ 'tabs';
+
+@mixin placeholder {
+ &::placeholder {@content}
+}
+
+.container {
+ @include placeholder {
+ color: $color-silver;
+ }
+}
+
+.something {
+ grid-template-columns: 1 2fr (3 + 4);
+}
+
+// Ignore escape "\\" in SCSS mixins
+@mixin margin-bottom-1\\/3 {
+ margin-bottom: 0.8rem;
+}
+
+label {
+ @include margin-bottom-1\\/3;
+}
+
+=====================================output=====================================
+@media #{$g-breakpoint-tiny} {
+}
+.#{$fa-css-prefix}-glass:before {
+ content: $fa-var-glass;
+}
+a {
+ height: calc(#{$foo} + 1);
+}
+div {
+ background: {
+ size: auto 60%;
+ position: bottom 2px left;
+ }
+}
+a {
+ margin: 0 {
+ left: 10px;
+ }
+}
+
+$default: #111111 !default;
+$default: #111111 !default;
+$default: #111111 !default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value" !default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value" !default;
+$default: "very-long-long-long-long-long-long-long-long-long-long-long-value" !default;
+
+$global: #111111 !global;
+$global: #111111 !global;
+$global: #111111 !global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value" !global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value" !global;
+$global: "very-long-long-long-long-long-long-long-long-long-long-long-value" !global;
+
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+) !default;
+$map: (
+ key: value,
+ other-key: other-value,
+) !default;
+$map: (
+ key: value,
+ other-key: other-value,
+) !default;
+$map: (
+ key: value,
+ other-key: other-value,
+) !default;
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ key: value,
+ other-key: other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-value,
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-key:
+ very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-verylong-other-value,
+);
+$map: (
+ key: (
+ #d82d2d,
+ #666,
+ ),
+ other-key: (
+ #52bf4a,
+ #fff,
+ ),
+ other-other-key: (
+ #c23435,
+ #fff,
+ ),
+);
+$map: (
+ key: (
+ #d82d2d,
+ #666,
+ ),
+ other-key: (
+ #52bf4a,
+ #fff,
+ ),
+ other-other-key: (
+ #c23435,
+ #fff,
+ ),
+);
+$map: (
+ key: (
+ #d82d2d,
+ #666,
+ ),
+ other-key: (
+ #52bf4a,
+ #fff,
+ ),
+ other-other-key: (
+ #c23435,
+ #fff,
+ ),
+);
+$map: (
+ key: (
+ #d82d2d,
+ #666,
+ ),
+ other-key: (
+ #52bf4a,
+ #fff,
+ ),
+ other-other-key: (
+ #c23435,
+ #fff,
+ ),
+);
+$map: (
+ key: (
+ #d82d2d,
+ #666,
+ ),
+ other-key: (
+ #52bf4a,
+ #fff,
+ ),
+ other-other-key: (
+ #c23435,
+ #fff,
+ ),
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+$map: map-merge(
+ $map,
+ (
+ $key: $value,
+ )
+);
+
+$longVariable: (
+ (mobile $mobile) (tablet $tablet) (desktop $desktop) (wide $wide)
+);
+
+$list-space: "item-1" "item-2" "item-3";
+$list-space: "item-1" "item-2" "item-3";
+$list-space: "item-1" "item-2" "item-3";
+$list-space: "item-1" "item-2" "item-3";
+$list-space: "item-1" "item-2" "item-3";
+$list-space: "item-1" "item-2" "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list-comma: "item-1", "item-2", "item-3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: "item-1.1" "item-1.2" "item-1.3", "item-2.1" "item-2.2" "item-2.3",
+ "item-3.1" "item-3.2" "item-3.3";
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+$list: (
+ ("item-1.1", "item-1.2", "item-1.3"),
+ ("item-2.1", "item-2.2", "item-2.3"),
+ ("item-3.1", "item-3.2", "item-3.3")
+);
+
+$var: (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0)
+ (0 0) (0 0);
+$space-scale: (0, "0") (0.25, "0-25") (0.5, "0-5") (0.75, "0-75") (1, "1")
+ (1.25, "1-25") (1.5, "1-5") (1.75, "1-75") (2, "2") (2.25, "2-25")
+ (2.5, "2-5") (2.75, "2-75") (3, "3") (3.25, "3-25") (3.5, "3-5")
+ (3.75, "3-75") (4, "4");
+
+.card-column-simple {
+ @include breakpoint(getBp(md)) {
+ padding: $spacing_content-sm $spacing_content-md;
+ }
+
+ @include breakpoint(getBp(md)) {
+ &:nth-child(2n + 3) {
+ clear: both;
+ }
+ }
+
+ @include breakpoint(getBp(xl)) {
+ &:nth-child(2n + 3) {
+ clear: none;
+ }
+ &:nth-child(3n + 4) {
+ clear: both;
+ }
+ }
+}
+
+@warn "Warn (#{$message}).";
+@warn "Warn (#{$message}).";
+@warn "Warn (#{$message}).";
+@warn #{$message};
+@warn "Very long long long long long long long long long long long long long line (#{$message}).";
+@warn "Very long long long long long long long long long long long long long line (#{$message}).";
+@error "Error (#{$message}).";
+@error "Error (#{$message}).";
+@error "Error (#{$message}).";
+@error #{$message};
+@error "Very long long long long long long long long long long long long long line Error (#{$message}).";
+@error "Very long long long long long long long long long long long long long line Error (#{$message}).";
+
+$buttonConfig: "save" 50px, "cancel" 50px, "help" 100px;
+
+$locale: "en_us";
+html[lang="#{$locale}"] {
+ font-size: 10px;
+}
+$alertClass: "error";
+p.message-#{$alertClass} {
+ color: red;
+}
+$mediumBreakpoint: 768px;
+@media (max-width: #{$mediumBreakpoint}) {
+ a {
+ font-size: 18px;
+ }
+}
+
+p {
+ @media (max-width: 768px) {
+ font-size: 150%;
+
+ @media (orientation: landscape) {
+ line-height: 75%;
+ }
+ }
+}
+
+.popularAnimal {
+ background: gray;
+}
+.GoodBoy {
+ color: green;
+}
+.dog {
+ @extend .popularAnimal;
+ @extend .GoodBoy;
+ color: white;
+}
+
+%animal {
+ background: gray;
+}
+.cat {
+ @extend %animal;
+ color: white;
+}
+.dog {
+ @extend %animal;
+ color: black;
+}
+
+%mfw-standing-out {
+ font-size: 150%;
+ font-style: italic;
+ padding: 25px;
+}
+%mfwSlightlyShadowed {
+ @include box-shadow(black 2px 2px 10px); // from Compass
+}
+%MFWRounded {
+ @include border-radius(25px); // from Compass
+}
+#join-button {
+ @extend %mfw-standing-out;
+ @extend %mfwSlightlyShadowed;
+ @extend %MFWRounded;
+ background: green;
+ color: white;
+}
+
+a {
+ &:hover {
+ color: red;
+ }
+}
+p {
+ body.no-touch & {
+ display: none;
+ }
+}
+.foo.bar .baz.bang,
+.bip.qux {
+ $selector: &;
+}
+@mixin does-parent-exist {
+ @if & {
+ &:hover {
+ color: red;
+ }
+ } @else {
+ a {
+ color: red;
+ }
+ }
+}
+
+p {
+ @if 1 + 1 == 2 {
+ border: 1px solid;
+ }
+ @if 5 < 3 {
+ border: 2px dotted;
+ }
+ @if null {
+ border: 3px double;
+ }
+}
+
+$mosterType: monster;
+p {
+ @if $mosterType == ocean {
+ color: blue;
+ } @else if $mosterType == matador {
+ color: red;
+ } @else if $mosterType == monster {
+ color: green;
+ } @else if $mosterType == nightKing {
+ color: green;
+ } @else if $mosterType == VeryWickedWolf {
+ color: green;
+ } @else {
+ color: black;
+ }
+}
+
+@for $i from 1 through 3 {
+ .item-#{$i} {
+ width: 2em * $i;
+ }
+}
+
+@each $animal in puma, sea-slug, cheerfulDog, BigSalamander, "string",
+ "another-string", "camelCaseString", "PascalCaseString"
+{
+ .#{$animal}-icon {
+ background-image: url("/images/#{$animal}.png");
+ }
+}
+
+$i: 6;
+@while $i > 0 {
+ .item-#{$i} {
+ width: 2em * $i;
+ }
+ $i: $i - 2;
+}
+
+@mixin cool-border($width: 10px, $coolStyle: "solid", $AwesomeColor: "black") {
+ border: $width $coolStyle $AwesomeColor;
+}
+
+p {
+ @include cool-border(1px, "solid", $fff);
+}
+p {
+ @include cool-border($width: 1px, $coolStyle: "solid", $AwesomeColor: #fff);
+}
+p {
+ @include coolBorder();
+}
+
+@mixin coolBorder() {
+ border: 10px solid #fff;
+}
+p {
+ @include coolBorder(1px, "solid", $fff);
+}
+
+@mixin CoolBorder() {
+ border: 10px solid #fff;
+}
+p {
+ @include CoolBorder(1px, "solid", $fff);
+}
+
+@mixin box-shadow($shadows...) {
+ -moz-box-shadow: $shadows;
+ -webkit-box-shadow: $shadows;
+ box-shadow: $shadows;
+}
+.shadows {
+ @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
+}
+
+@mixin apply-to-ie6-only {
+ * html {
+ @content;
+ }
+}
+@include apply-to-ie6-only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin applyToIe6Only {
+ * html {
+ @content;
+ }
+}
+@include applyToIe6Only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin ApplyToIe6Only {
+ * html {
+ @content;
+ }
+}
+@include ApplyToIe6Only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+
+@mixin config-icon-colors($prefix, $colors...) {
+ @each $i in $colors {
+ .#{$prefix}#{nth($i, 1)} {
+ color: nth($i, 2);
+ }
+ }
+}
+@include config-icon-colors(
+ "icon-",
+ "save" green,
+ "cancel" gray,
+ "delete" red,
+ "wait" blue
+);
+
+@function my-calculation-function($some-number, $anotherNumber, $BigNumber) {
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function myCalculationFunction($some-number, $anotherNumber, $BigNumber) {
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function AnotherMyCalculationFunction(
+ $some-number,
+ $anotherNumber,
+ $BigNumber: 100px
+) {
+ @return $some-number + $anotherNumber + $BigNumber;
+}
+@function border($borders...) {
+ @return $borders;
+}
+.foo {
+ padding: my-calculation-function(10px, 5px, 100px);
+ margin: myCalculationFunction(
+ $some-number: 10px,
+ $anotherNumber: 5px,
+ $BigNumber: 100px
+ );
+ width: AnotherMyCalculationFunction(10px, 5px);
+ border: border(25px, 35px);
+}
+
+$sm-only: "(min-width: 768px) and (max-width: 991px)";
+$lg-and-up: "(min-width: 1200px)";
+
+@media screen and #{$sm-only, $lg-and-up} {
+ color: #000;
+}
+
+.class-#{$var} {
+ #{$var}: #7b3d66;
+ #{$attr}-color: blue;
+ #{$prop}-#{$side}: $value;
+ background-#{$var}: #7b3d66;
+ animation-name: #{var};
+ line-height: #{strip-unit($line-height)}em;
+ height: 1#{$var};
+ width: calc(100% - #{$sidebar-width});
+ max-width: calc(#{$m * 100}vw #{$sign} #{$b});
+ font: #{$font-size}/#{$line-height};
+ content: "I have #{8 + 2} books on SASS!";
+ border: #{$var} #{$var} #{$var};
+ filter: #{$var}#{$var}#{$var};
+ prop: #{$var + $var} #{$var + $var} #{$var + $var};
+ prop2: #{$var + $var} #{$var + $var} #{$var + $var};
+ prop3: #{$var + $var} #{$var + $var} #{$var + $var};
+ prop4: -#{$loader-icon-duration};
+ prop5: +#{$loader-icon-duration};
+ prop6: calc(-#{$loader-icon-duration} + 10);
+ prop7: calc(10 + -#{$loader-icon-duration});
+}
+
+/* Framework version for the generated CSS is #{$version}. */
+
+.selector {
+ foo: bar;
+ #{$active} {
+ baz: qux;
+ }
+}
+
+.el:nth-of-type(#{$i}) {
+}
+
+@media #{$value} {
+}
+
+@import url(#{$foundation-dir}/foundation/components/grid);
+
+@keyframes loader {
+ 0% {
+ transform: translate3d(0, 0, 0);
+ }
+
+ #{50% - $loader-icon-duration} {
+ transform: translate3d(0, $bounce-height, 0);
+ }
+
+ 50% {
+ transform: translate3d(0, $bounce-height, 0)
+ scale(
+ $loader-bounce-horizontal-expansion,
+ $loader-bounce-vertical-compression
+ );
+ }
+}
+
+$icons: wifi "\\600", wifi-hotspot "\\601", weather "\\602";
+
+@each $icon in $icons {
+ .icon-#{nth($icon, 1)},
+ %icon-#{nth($icon, 1)} {
+ content: "#{nth($icon, 2)}";
+ }
+}
+
+.foo {
+ prop: -($grid-gutter-width / 2);
+ prop1: -($grid-gutter-width / 2);
+ prop2: -$grid-gutter-width / 2;
+ prop3: +($grid-gutter-width / 2);
+ prop4: 10px/8px; /* Plain CSS, no division */
+ prop5: $width / 2; /* Uses a variable, does division */
+ prop6: round(1.5) / 2; /* Uses a function, does division */
+ prop7: (500px / 2); /* Uses parentheses, does division */
+ prop8: 5px + 8px / 2px; //* Uses +, does division */
+ prop9: (italic bold 10px/8px); /* In a list, parentheses don't count */
+ prop10: #010203 + #040506;
+ prop11: #010203 * 2;
+ prop12: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
+ prop13: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}');
+ prop14: e + -resize;
+ prop15: sans- + "serif";
+ prop16: 1em + (2em * 3);
+ prop17: rotate(-2deg);
+ prop18: rotate(-2deg);
+ _: _;
+ prop19: 10 - ($grid-gutter-width / 2);
+ prop20: 10 + -($grid-gutter-width / 2);
+ prop21: 10 + -($grid-gutter-width / 2);
+ prop22: -($grid-gutter-width / 2);
+ prop23: -($grid-gutter-width / 2);
+ prop24: -$grid-gutter-width;
+ prop25: +($grid-gutter-width / 2);
+ prop26: +($grid-gutter-width / 2);
+ prop27: +$grid-gutter-width;
+ prop28: --($grid-gutter-width / 2);
+ prop28: ++($grid-gutter-width / 2);
+ prop29: rotate(-2deg);
+}
+
+$last: nth($juggler, length($juggler));
+$x: if($last%2==0, 1/2, 3/2);
+$new: pow($last, $x);
+$sequence: 1, 1 1, 2 1, 1 2 1 1, 1 1 1 2 2 1;
+$new-entry: ();
+$new-entry: ();
+$new-entry: ();
+$new-entry: ();
+
+body:before {
+ content: quote(to-string(fibonacci(100), " \\A "));
+ white-space: pre-wrap;
+}
+
+width: ((100% - (($numPerRow - 1) * $margin)) / $numPerRow);
+width: ((100% - (($numPerRow - 1) * $margin)) / $numPerRow);
+
+a:nth-child(#{$numPerRow}n) {
+ margin-right: 0;
+ margin-bottom: 0;
+}
+
+@function em($pixels, $context: $browser-context) {
+ @return #{$pixels / $context}em;
+}
+
+.navigation {
+ @extend %updated-#{$flag};
+ @extend .selected-#{$flag};
+ @extend %#{$item};
+}
+
+.icon-#{$icon-name} {
+ background-image: "/images/#{$icon-name}.svg";
+}
+
+$extmods: (
+ eot: "?",
+ svg: "#" + str-replace($name, " ", "_"),
+);
+
+@mixin keyframes {
+ @-moz-keyframes {
+ @content;
+ }
+ @-webkit-keyframes {
+ @content;
+ }
+}
+
+@function gcd($a, $b) {
+ // From: http://rosettacode.org/wiki/Greatest_common_divisor#JavaScript
+ @if ($b != 0) {
+ @return gcd($b, $a % $b);
+ } @else {
+ @return abs($a);
+ }
+}
+
+$colors: (
+ primary: (
+ base: #00abc9,
+ light: #daf1f6,
+ dark: #12799a,
+ ),
+ secondary: (
+ base: #424d55,
+ light: #ccc,
+ lightest: #efefef,
+ dark: #404247,
+ ),
+ success: (
+ base: #bbd33e,
+ light: #eaf0c6,
+ ),
+);
+
+@function color($color, $tone: "base") {
+ @return map-get(map-get($colors, $color), $tone);
+}
+
+@media only screen and (max-width: 767px) {
+ @include widths(2 3 4, \\@small);
+}
+
+$widths-breakpoint-separator: \\@small;
+
+a {
+ transition-timing-function: func1(
+ func2(
+ func3(
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue"
+ ),
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue"
+ ),
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ func3(
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue",
+ "veryVeryVeryVeryVeryLongValue"
+ )
+ );
+}
+
+$empty-map: ();
+$empty-nested-map: (
+ nested-key: (
+ empty-key: (
+ color: red,
+ ),
+ ),
+ empty-key: (),
+ empty-key: (),
+ empty-key: (),
+);
+
+$o-grid-default-config: (
+ columns: 12,
+ gutter: 10px,
+ min-width: 240px,
+ max-width: 1330px,
+ layouts: (
+ S: 370px,
+ M: 610px,
+ L: 850px,
+ XL: 1090px,
+ ),
+ fluid: true,
+ debug: false,
+ fixed-layout: M,
+ enhanced-experience: true,
+);
+
+$a: ();
+$b: unquote("");
+$c: null;
+$d: (null);
+
+$threads-properties: map-merge(
+ $threads-properties,
+ (
+ $border-label: (),
+ )
+);
+$o-grid-default-config: (
+ layouts: (
+ S: 370px,
+ ),
+);
+
+$map: (
+ key: (
+ value,
+ ),
+ other-key: (
+ key: other-other-value,
+ ),
+);
+
+a {
+ content: "#{"0.5"}";
+ content: my-fn("_");
+ content: "#{my-fn("_")}";
+ content: my-fn("-");
+ content: "#{my-fn("-")}";
+ content: my-fn("-a");
+ content: "#{my-fn("-a")}";
+ content: my-fn("a-");
+ content: "#{my-fn("a-")}";
+ content: my-fn("foo");
+ content: "#{my-fn("foo")}";
+ content: 1 "#{my-fn("foo")}" 2;
+ content: foo "#{my-fn("foo")}" bar;
+ content: "foo #{$description} bar";
+
+ content: "#{my-fn("foo","bar")}";
+ content: "#{my-fn( "foo" , "bar" )}";
+ content: "#{my-fn( "foo" , "bar" )}";
+
+ content: '#{my-fn("foo")}';
+ content: "#{my-fn("foo")}";
+ content: "#{my-fn('foo')}";
+ content: "#{my-fn("foo")}";
+}
+
+mixin theme($css-property, $css-value, $theme-classes: t) {
+ @each $selector in & {
+ @each $class in $theme-classes {
+ @each $theme, $theme-properties in c(themes) {
+ $value: $css-value;
+
+ @each $theme-name, $theme-value in $theme-properties {
+ $rgba-value: "rgba(#{red($theme-value)}, #{green($theme-value)}, #{blue($theme-value)}";
+ $value: str-replace($value, "rgba(\${#{$theme-name}}", $rgba-value);
+ $value: str-replace($value, "\${#{$theme-name}}", $theme-value);
+ }
+
+ @at-root .#{$class}-#{join($theme, $selector)} {
+ #{$css-property}: unquote($value);
+ }
+ }
+ }
+ }
+}
+
+.foo,
+// Comment
+.bar {
+ // Comment
+ color: red; // Comment
+}
+
+$my-list: "foo",
+ // Comment
+ "bar"; // Comment
+
+$my-map: (
+ "foo": 1,
+ // Comment
+ "bar": 2,
+ // Comment
+);
+
+[href]:hover &, // Comment
+[href]:focus &, // Comment
+[href]:active & {
+ .tooltip {
+ opacity: 1;
+ }
+}
+
+@import // Comment
+ "mixins",
+ "variables",
+ // Comment
+ "reset",
+ "scaffolding", "type",
+ // Comment
+ "bar",
+ "tabs";
+
+@mixin placeholder {
+ &::placeholder {
+ @content;
+ }
+}
+
+.container {
+ @include placeholder {
+ color: $color-silver;
+ }
+}
+
+.something {
+ grid-template-columns: 1 2fr (3 + 4);
+}
+
+// Ignore escape "\\" in SCSS mixins
+@mixin margin-bottom-1\\/3 {
+ margin-bottom: 0.8rem;
+}
+
+label {
+ @include margin-bottom-1\\/3;
+}
+
+================================================================================
+`;
diff --git a/tests/css_scss/jsfmt.spec.js b/tests/css_scss/jsfmt.spec.js
index 539bde0869da..548d429d8390 100644
--- a/tests/css_scss/jsfmt.spec.js
+++ b/tests/css_scss/jsfmt.spec.js
@@ -1 +1,2 @@
run_spec(__dirname, ["scss"]);
+run_spec(__dirname, ["scss"], { trailingComma: "es5" });
diff --git a/tests/css_selector_list/__snapshots__/jsfmt.spec.js.snap b/tests/css_selector_list/__snapshots__/jsfmt.spec.js.snap
index b4b12fe86110..0a5ff7b41dcf 100644
--- a/tests/css_selector_list/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/css_selector_list/__snapshots__/jsfmt.spec.js.snap
@@ -695,7 +695,7 @@ svg|a {
*|a {
}
-|b {
+|B {
}
ns|* {
diff --git a/tests/handlebars-whitespace/__snapshots__/jsfmt.spec.js.snap b/tests/handlebars-whitespace/__snapshots__/jsfmt.spec.js.snap
index 3ebddb6cc831..7f21fe231789 100644
--- a/tests/handlebars-whitespace/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/handlebars-whitespace/__snapshots__/jsfmt.spec.js.snap
@@ -355,6 +355,98 @@ printWidth: 40
================================================================================
`;
+exports[`preserved-spaces-and-breaks.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 40
+ | printWidth
+=====================================input======================================
+
+{{name}}
+
+
+
+Some sentence with {{dynamic}} expressions.
+
+sometimes{{nogaps}}areimportant
+
+
+{{name}} is your name
+
+
+{{#block}}
+{{/block}}
+
+
+{{#block}}
+ some {{text}}
+{{/block}}
+
+{{#block}}
+
+ some {{text}}
+{{/block}}
+
+
+
+
+
+ some {{text}}
+
+
+
+
+ some {{text}}
+
+
+
+
+
+
+
+
+
+=====================================output=====================================
+
+{{name}}
+
+Some sentence with {{dynamic
+}} expressions.
+
+sometimes{{nogaps
+}}areimportant
+
+
+{{name}} is your name
+
+{{#block}}{{/block}}
+
+{{#block}}
+ some {{text}}
+{{/block}}
+
+{{#block}}
+ some {{text}}
+{{/block}}
+
+
+
+
+ some {{text}}
+
+
+
+ some {{text}}
+
+
+
+
+
+
+
+================================================================================
+`;
+
exports[`punctuation.hbs 1`] = `
====================================options=====================================
parsers: ["glimmer"]
diff --git a/tests/glimmer/preserved-spaces-and-breaks.hbs b/tests/handlebars-whitespace/preserved-spaces-and-breaks.hbs
similarity index 100%
rename from tests/glimmer/preserved-spaces-and-breaks.hbs
rename to tests/handlebars-whitespace/preserved-spaces-and-breaks.hbs
diff --git a/tests/jsx/__snapshots__/jsfmt.spec.js.snap b/tests/jsx/__snapshots__/jsfmt.spec.js.snap
index 31cb9d86fb60..bb0fb27bf273 100644
--- a/tests/jsx/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/jsx/__snapshots__/jsfmt.spec.js.snap
@@ -4097,6 +4097,9 @@ f?.();
()();
()?.();
+new Foo();
+new Foo(())
+
=====================================output=====================================
a = [
);
()();
()?.();
+new Foo();
+new Foo();
+
================================================================================
`;
@@ -4143,6 +4149,9 @@ f?.();
()();
()?.();
+new Foo();
+new Foo(())
+
=====================================output=====================================
a = [
);
()();
()?.();
+new Foo();
+new Foo();
+
================================================================================
`;
@@ -4189,6 +4201,9 @@ f?.();
()();
()?.();
+new Foo();
+new Foo(())
+
=====================================output=====================================
a = [
);
()();
()?.();
+new Foo();
+new Foo();
+
================================================================================
`;
@@ -4235,6 +4253,9 @@ f?.();
()();
()?.();
+new Foo();
+new Foo(())
+
=====================================output=====================================
a = [
);
()();
()?.();
+new Foo();
+new Foo();
+
================================================================================
`;
diff --git a/tests/jsx/parens.js b/tests/jsx/parens.js
index aacd7379728b..b5b4a5bc490b 100644
--- a/tests/jsx/parens.js
+++ b/tests/jsx/parens.js
@@ -14,3 +14,6 @@ a = [
f?.();
()();
()?.();
+
+new Foo();
+new Foo(())
diff --git a/tests/label/__snapshots__/jsfmt.spec.js.snap b/tests/label/__snapshots__/jsfmt.spec.js.snap
index 556522ec87d9..e83d3fee33bf 100644
--- a/tests/label/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/label/__snapshots__/jsfmt.spec.js.snap
@@ -10,12 +10,21 @@ printWidth: 80
inf_leave: // goto emulation
for (;;) {}
}
+{
+ inf_leave:
+ // goto emulation
+ for (; ;) { }
+}
=====================================output=====================================
{
// goto emulation
inf_leave: for (;;) {}
}
+{
+ // goto emulation
+ inf_leave: for (;;) {}
+}
================================================================================
`;
diff --git a/tests/label/comment.js b/tests/label/comment.js
index 45e9363f1c2c..2659e3978210 100644
--- a/tests/label/comment.js
+++ b/tests/label/comment.js
@@ -2,3 +2,8 @@
inf_leave: // goto emulation
for (;;) {}
}
+{
+ inf_leave:
+ // goto emulation
+ for (; ;) { }
+}
diff --git a/tests/line_suffix_boundary/__snapshots__/jsfmt.spec.js.snap b/tests/line_suffix_boundary/__snapshots__/jsfmt.spec.js.snap
index 583f31c1d3f7..475d1d817e90 100644
--- a/tests/line_suffix_boundary/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/line_suffix_boundary/__snapshots__/jsfmt.spec.js.snap
@@ -32,7 +32,8 @@ ExampleStory.getFragment('story')}
;
=====================================output=====================================
-\`\${a + a // a
+\`\${
+ a + a // a
}
\${
diff --git a/tests/logical_expressions/__snapshots__/jsfmt.spec.js.snap b/tests/logical_expressions/__snapshots__/jsfmt.spec.js.snap
index 4feb449407ae..714f2f726a3d 100644
--- a/tests/logical_expressions/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/logical_expressions/__snapshots__/jsfmt.spec.js.snap
@@ -1,5 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`issue-7024.js 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+const radioSelectedAttr =
+ (isAnyValueSelected &&
+ node.getAttribute(radioAttr.toLowerCase()) === radioValue) ||
+ ((!isAnyValueSelected && values[a].default === true) || a === 0);
+
+=====================================output=====================================
+const radioSelectedAttr =
+ (isAnyValueSelected &&
+ node.getAttribute(radioAttr.toLowerCase()) === radioValue) ||
+ (!isAnyValueSelected && values[a].default === true) ||
+ a === 0;
+
+================================================================================
+`;
+
exports[`logical_expression_operators.js 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
diff --git a/tests/logical_expressions/issue-7024.js b/tests/logical_expressions/issue-7024.js
new file mode 100644
index 000000000000..fa8e8ff1e907
--- /dev/null
+++ b/tests/logical_expressions/issue-7024.js
@@ -0,0 +1,4 @@
+const radioSelectedAttr =
+ (isAnyValueSelected &&
+ node.getAttribute(radioAttr.toLowerCase()) === radioValue) ||
+ ((!isAnyValueSelected && values[a].default === true) || a === 0);
diff --git a/tests/markdown_list/__snapshots__/jsfmt.spec.js.snap b/tests/markdown_list/__snapshots__/jsfmt.spec.js.snap
index a483b07f4588..492abaeceba0 100644
--- a/tests/markdown_list/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/markdown_list/__snapshots__/jsfmt.spec.js.snap
@@ -2458,11 +2458,200 @@ proseWrap: "always"
6. def
7. ghi
+---
+
+0. abc
+0. def
+0. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+2. def
+2. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+145. def
+69. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+2. def
+
=====================================output=====================================
5. abc
6. def
7. ghi
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+1000. def
+1001. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+1000. def
+
================================================================================
`;
@@ -2478,11 +2667,200 @@ tabWidth: 4
6. def
7. ghi
+---
+
+0. abc
+0. def
+0. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+2. def
+2. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+145. def
+69. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+2. def
+
=====================================output=====================================
5. abc
6. def
7. ghi
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+1000. def
+1001. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+1000. def
+
================================================================================
`;
@@ -2498,11 +2876,200 @@ tabWidth: 999
6. def
7. ghi
+---
+
+0. abc
+0. def
+0. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+2. def
+2. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+145. def
+69. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+2. def
+
=====================================output=====================================
5. abc
6. def
7. ghi
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+1000. def
+1001. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+1000. def
+
================================================================================
`;
@@ -2518,10 +3085,199 @@ tabWidth: 0
6. def
7. ghi
+---
+
+0. abc
+0. def
+0. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+2. def
+2. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+145. def
+69. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+2. def
+
=====================================output=====================================
5. abc
6. def
7. ghi
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+1000. def
+1001. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+1000. def
+
================================================================================
`;
diff --git a/tests/markdown_list/start.md b/tests/markdown_list/start.md
index 49db6cfcc6fd..b58f3551fa88 100644
--- a/tests/markdown_list/start.md
+++ b/tests/markdown_list/start.md
@@ -1,3 +1,98 @@
5. abc
6. def
7. ghi
+
+---
+
+0. abc
+0. def
+0. ghi
+
+---
+
+1. abc
+1. def
+1. ghi
+
+---
+
+2. abc
+2. def
+2. ghi
+
+---
+
+0. abc
+1. def
+2. ghi
+
+---
+
+0. abc
+1. def
+1. ghi
+
+---
+
+1. abc
+2. def
+3. ghi
+
+---
+
+2. abc
+3. def
+4. ghi
+
+---
+
+999. abc
+145. def
+69. ghi
+
+---
+
+0. abc
+
+---
+
+1. abc
+
+---
+
+2. abc
+
+---
+
+999. abc
+
+---
+
+0. abc
+1. def
+
+---
+
+1. abc
+2. def
+
+---
+
+
+1. abc
+1. def
+
+---
+
+2. abc
+3. def
+
+---
+
+999. abc
+1. def
+
+---
+
+999. abc
+2. def
diff --git a/tests/mdx/__snapshots__/jsfmt.spec.js.snap b/tests/mdx/__snapshots__/jsfmt.spec.js.snap
index 942f1e22aa1e..d15f9aed2801 100644
--- a/tests/mdx/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/mdx/__snapshots__/jsfmt.spec.js.snap
@@ -265,6 +265,12 @@ printWidth: 80
---
+<>
+ test