feat(sass): Enable client-side sass compiling (#16747)
This commit is contained in:
committed by
Quincy Larson
parent
3131c55782
commit
1a5cab57a1
@ -95,7 +95,7 @@ export function concactHtml(required, template) {
|
|||||||
|
|
||||||
const body = source
|
const body = source
|
||||||
.flatMap(file => file.reduce((body, file) => {
|
.flatMap(file => file.reduce((body, file) => {
|
||||||
return body + file.contents + htmlCatch;
|
return body + file.contents + file.tail + htmlCatch;
|
||||||
}, ''))
|
}, ''))
|
||||||
.map(source => ({ source }))
|
.map(source => ({ source }))
|
||||||
.map(createBody);
|
.map(createBody);
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
import _ from 'lodash';
|
import {
|
||||||
|
cond,
|
||||||
|
flow,
|
||||||
|
identity,
|
||||||
|
matchesProperty,
|
||||||
|
overEvery,
|
||||||
|
overSome,
|
||||||
|
partial,
|
||||||
|
stubTrue
|
||||||
|
} from 'lodash';
|
||||||
|
|
||||||
import * as babel from 'babel-core';
|
import * as babel from 'babel-core';
|
||||||
import presetEs2015 from 'babel-preset-es2015';
|
import presetEs2015 from 'babel-preset-es2015';
|
||||||
@ -24,15 +33,34 @@ function loopProtectHit(line) {
|
|||||||
const console$logReg = /(?:\b)console(\.log\S+)/g;
|
const console$logReg = /(?:\b)console(\.log\S+)/g;
|
||||||
const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
|
const NBSPReg = new RegExp(String.fromCharCode(160), 'g');
|
||||||
|
|
||||||
const isJS = _.matchesProperty('ext', 'js');
|
const isJS = matchesProperty('ext', 'js');
|
||||||
const testHTMLJS = _.overSome(isJS, _.matchesProperty('ext', 'html'));
|
const testHTMLJS = overSome(isJS, matchesProperty('ext', 'html'));
|
||||||
const testJS$JSX = _.overSome(isJS, _.matchesProperty('ext', 'jsx'));
|
const testJS$JSX = overSome(isJS, matchesProperty('ext', 'jsx'));
|
||||||
|
|
||||||
|
// work around the absence of multi-flile editing
|
||||||
|
// this can be replaced with `matchesProperty('ext', 'sass')`
|
||||||
|
// when the time comes
|
||||||
|
const testSASS = file => (/type='text\/sass'/i).test(file.contents);
|
||||||
|
// This can be done in the transformer when we have multi-file editing
|
||||||
|
const browserSassCompiler = `
|
||||||
|
<script>
|
||||||
|
var styleTags = [ ...document.querySelectorAll('style') ];
|
||||||
|
[].slice.call(styleTags, 1).forEach(
|
||||||
|
function compileSass(tag) {
|
||||||
|
var scss = tag.innerHTML;
|
||||||
|
Sass.compile(scss, function(result) {
|
||||||
|
tag.type = 'text/css';
|
||||||
|
tag.innerHTML = result.text;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
`;
|
||||||
// if shouldProxyConsole then we change instances of console log
|
// if shouldProxyConsole then we change instances of console log
|
||||||
// to `window.__console.log`
|
// to `window.__console.log`
|
||||||
// this let's us tap into logging into the console.
|
// this let's us tap into logging into the console.
|
||||||
// currently we only do this to the main window and not the test window
|
// currently we only do this to the main window and not the test window
|
||||||
export const proxyLoggerTransformer = _.partial(
|
export const proxyLoggerTransformer = partial(
|
||||||
vinyl.transformHeadTailAndContents,
|
vinyl.transformHeadTailAndContents,
|
||||||
source => (
|
source => (
|
||||||
source.replace(console$logReg, (match, methodCall) => {
|
source.replace(console$logReg, (match, methodCall) => {
|
||||||
@ -40,7 +68,7 @@ export const proxyLoggerTransformer = _.partial(
|
|||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
const addLoopProtect = _.partial(
|
const addLoopProtect = partial(
|
||||||
vinyl.transformContents,
|
vinyl.transformContents,
|
||||||
contents => {
|
contents => {
|
||||||
/* eslint-disable import/no-unresolved */
|
/* eslint-disable import/no-unresolved */
|
||||||
@ -51,11 +79,11 @@ const addLoopProtect = _.partial(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const addLoopProtectHtmlJsJsx = _.cond([
|
export const addLoopProtectHtmlJsJsx = cond([
|
||||||
[
|
[
|
||||||
_.overEvery(
|
overEvery(
|
||||||
testHTMLJS,
|
testHTMLJS,
|
||||||
_.partial(
|
partial(
|
||||||
vinyl.testContents,
|
vinyl.testContents,
|
||||||
contents => contents.toLowerCase().includes('<script>')
|
contents => contents.toLowerCase().includes('<script>')
|
||||||
)
|
)
|
||||||
@ -63,38 +91,50 @@ export const addLoopProtectHtmlJsJsx = _.cond([
|
|||||||
addLoopProtect
|
addLoopProtect
|
||||||
],
|
],
|
||||||
[ testJS$JSX, addLoopProtect ],
|
[ testJS$JSX, addLoopProtect ],
|
||||||
[ _.stubTrue, _.identity ]
|
[ stubTrue, identity ]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const replaceNBSP = _.cond([
|
export const replaceNBSP = cond([
|
||||||
[
|
[
|
||||||
testHTMLJS,
|
testHTMLJS,
|
||||||
_.partial(
|
partial(
|
||||||
vinyl.transformContents,
|
vinyl.transformContents,
|
||||||
contents => contents.replace(NBSPReg, ' ')
|
contents => contents.replace(NBSPReg, ' ')
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
[ _.stubTrue, _.identity ]
|
[ stubTrue, identity ]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const babelTransformer = _.cond([
|
export const babelTransformer = cond([
|
||||||
[
|
[
|
||||||
testJS$JSX,
|
testJS$JSX,
|
||||||
_.flow(
|
flow(
|
||||||
_.partial(
|
partial(
|
||||||
vinyl.transformHeadTailAndContents,
|
vinyl.transformHeadTailAndContents,
|
||||||
babelTransformCode
|
babelTransformCode
|
||||||
),
|
),
|
||||||
_.partial(vinyl.setExt, 'js')
|
partial(vinyl.setExt, 'js')
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
[ _.stubTrue, _.identity ]
|
[ stubTrue, identity ]
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const sassTransformer = cond([
|
||||||
|
[
|
||||||
|
testSASS,
|
||||||
|
partial(
|
||||||
|
vinyl.appendToTail,
|
||||||
|
browserSassCompiler
|
||||||
|
)
|
||||||
|
],
|
||||||
|
[ stubTrue, identity ]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const _transformers = [
|
export const _transformers = [
|
||||||
addLoopProtectHtmlJsJsx,
|
addLoopProtectHtmlJsJsx,
|
||||||
replaceNBSP,
|
replaceNBSP,
|
||||||
babelTransformer
|
babelTransformer,
|
||||||
|
sassTransformer
|
||||||
];
|
];
|
||||||
|
|
||||||
export function applyTransformers(file, transformers = _transformers) {
|
export function applyTransformers(file, transformers = _transformers) {
|
||||||
|
@ -166,6 +166,14 @@ export function clearHeadTail(poly) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function appendToTail(tail, poly) {
|
||||||
|
checkPoly(poly);
|
||||||
|
return {
|
||||||
|
...poly,
|
||||||
|
tail: poly.tail.concat(tail)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// compileHeadTail(contents: String, poly: PolyVinyl) => PolyVinyl
|
// compileHeadTail(contents: String, poly: PolyVinyl) => PolyVinyl
|
||||||
export function compileHeadTail(padding = '', poly) {
|
export function compileHeadTail(padding = '', poly) {
|
||||||
return clearHeadTail(transformContents(
|
return clearHeadTail(transformContents(
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
"title": "Store Data with Sass Variables",
|
"title": "Store Data with Sass Variables",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -42,13 +42,13 @@
|
|||||||
"Create a variable <code>$text-color</code> and set it to red. Then change the value of the <code>color</code> property for the <code>.blog-post</code> and <code>h2</code> to the <code>$text-color</code> variable."
|
"Create a variable <code>$text-color</code> and set it to red. Then change the value of the <code>color</code> property for the <code>.blog-post</code> and <code>h2</code> to the <code>$text-color</code> variable."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" .header{",
|
" .header{",
|
||||||
" text-align: center;",
|
" text-align: center;",
|
||||||
" }",
|
" }",
|
||||||
" .blog-post h2 {",
|
" .blog-post, h2 {",
|
||||||
" color: red;",
|
" color: red;",
|
||||||
" }",
|
" }",
|
||||||
"</style>",
|
"</style>",
|
||||||
@ -85,7 +85,7 @@
|
|||||||
"title": "Nest CSS with Sass",
|
"title": "Nest CSS with Sass",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"Use the <code>nesting</code> technique shown above to re-organize the CSS rules for both children of <code>.blog-post</code> element. For testing purposes, the <code>h1</code> should come before the <code>p</code> element."
|
"Use the <code>nesting</code> technique shown above to re-organize the CSS rules for both children of <code>.blog-post</code> element. For testing purposes, the <code>h1</code> should come before the <code>p</code> element."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" .blog-post {",
|
" .blog-post {",
|
||||||
" ",
|
" ",
|
||||||
" }",
|
" }",
|
||||||
@ -132,7 +132,7 @@
|
|||||||
"title": "Create Reusable CSS with Mixins",
|
"title": "Create Reusable CSS with Mixins",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -150,7 +150,7 @@
|
|||||||
"Write a <code>mixin</code> for <code>border-radius</code> and give it a <code>$radius</code> parameter. It should use all the vendor prefixes from the example. Then use the <code>border-radius</code> <code>mixin</code> to give the <code>#awesome</code> element a border radius of 15px."
|
"Write a <code>mixin</code> for <code>border-radius</code> and give it a <code>$radius</code> parameter. It should use all the vendor prefixes from the example. Then use the <code>border-radius</code> <code>mixin</code> to give the <code>#awesome</code> element a border radius of 15px."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
@ -185,7 +185,7 @@
|
|||||||
"title": "Use @if and @else to Add Logic To Your Styles",
|
"title": "Use @if and @else to Add Logic To Your Styles",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -199,7 +199,7 @@
|
|||||||
"<blockquote>light - 1px solid black<br>medium - 3px solid black<br>heavy - 6px solid black<br>none - no border</blockquote>"
|
"<blockquote>light - 1px solid black<br>medium - 3px solid black<br>heavy - 6px solid black<br>none - no border</blockquote>"
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
@ -232,7 +232,7 @@
|
|||||||
"title": "Use @for to Create a Sass Loop",
|
"title": "Use @for to Create a Sass Loop",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -249,7 +249,7 @@
|
|||||||
"It should create 5 classes called <code>.text-1</code> to <code>.text-5</code> where each has a <code>font-size</code> set to 10px multiplied by the index."
|
"It should create 5 classes called <code>.text-1</code> to <code>.text-5</code> where each has a <code>font-size</code> set to 10px multiplied by the index."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
@ -281,7 +281,7 @@
|
|||||||
"title": "Use @each to Map Over Items in a List",
|
"title": "Use @each to Map Over Items in a List",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -299,7 +299,7 @@
|
|||||||
"Each class should set the <code>background-color</code> the respective color."
|
"Each class should set the <code>background-color</code> the respective color."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
@ -331,7 +331,7 @@
|
|||||||
"title": "Apply a Style Until a Condition is Met with @while",
|
"title": "Apply a Style Until a Condition is Met with @while",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -346,7 +346,7 @@
|
|||||||
"There should be 10 different classes from <code>text-1</code> to <code>text-10</code>. Then set <code>font-size</code> to 5px multiplied by the current index number. Make sure to avoid an infinite loop!"
|
"There should be 10 different classes from <code>text-1</code> to <code>text-10</code>. Then set <code>font-size</code> to 5px multiplied by the current index number. Make sure to avoid an infinite loop!"
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
@ -390,7 +390,7 @@
|
|||||||
"title": "Split Your Styles into Smaller Chunks with Partials",
|
"title": "Split Your Styles into Smaller Chunks with Partials",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -425,7 +425,7 @@
|
|||||||
"title": "Extend One Set of CSS Styles to Another Element",
|
"title": "Extend One Set of CSS Styles to Another Element",
|
||||||
"required": [
|
"required": [
|
||||||
{
|
{
|
||||||
"link": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.9.13/sass.min.js",
|
"src": "https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.9/sass.sync.min.js",
|
||||||
"raw": true
|
"raw": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -442,7 +442,7 @@
|
|||||||
"Make a class <code>.info-important</code> that extends <code>.info</code> and also has a <code>background-color</code> set to magenta."
|
"Make a class <code>.info-important</code> that extends <code>.info</code> and also has a <code>background-color</code> set to magenta."
|
||||||
],
|
],
|
||||||
"challengeSeed": [
|
"challengeSeed": [
|
||||||
"<style>",
|
"<style type='text/sass'>",
|
||||||
" h3{",
|
" h3{",
|
||||||
" text-align: center;",
|
" text-align: center;",
|
||||||
" }",
|
" }",
|
||||||
|
Reference in New Issue
Block a user