Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS SourceMaps #4440

Merged
merged 11 commits into from Apr 15, 2020
24 changes: 14 additions & 10 deletions flow-libs/postcss.js.flow
Expand Up @@ -4,7 +4,8 @@
// Derived from the PostCSS docs available at
// http://api.postcss.org/postcss.html.

import type {SourceMapGenerator} from 'source-map';
// eslint-disable-next-line import/no-extraneous-dependencies
import typeof {SourceMapGenerator} from 'source-map';

declare module 'postcss' {
declare type NodeCallback = (Node, number) => false | void;
Expand All @@ -23,20 +24,23 @@ declare module 'postcss' {
declare interface Root extends Container {}

declare class Processor {
process(css: string | Result, opts?: processOptions): Promise<Result>;
process(
css: string | Result | Root,
opts?: ProcessOptions,
): Promise<Result>;
}

declare type ProcessOptions = {|
from?: string,
to?: string,
map?: MapOptions,
parser?: parser,
stringifier?: stringifier,
syntax?: {|
declare type ProcessOptions = $Shape<{|
from: string,
to: string,
map: MapOptions,
parser: parser,
stringifier: stringifier,
syntax: {|
parser: parser,
stringifier: stringifier,
|},
|};
|}>;

declare type MapOptions = {|
inline?: boolean,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/cache/src/Cache.js
Expand Up @@ -8,7 +8,7 @@ import type {FileSystem} from '@parcel/fs';
import path from 'path';
import logger from '@parcel/logger';
import {serialize, deserialize, registerSerializableClass} from '@parcel/core';
// $FlowFixMe this is untyped
// flowlint-next-line untyped-import:off
import packageJson from '../package.json';

export default class Cache {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/core/src/utils.js
Expand Up @@ -10,7 +10,7 @@ import Graph from './Graph';
import ParcelConfig from './ParcelConfig';
import {RequestGraph} from './RequestTracker';
import Config from './public/Config';
// $FlowFixMe this is untyped
// flowlint-next-line untyped-import:off
import packageJson from '../package.json';

export function getBundleGroupId(bundleGroup: BundleGroup): string {
Expand Down
35 changes: 30 additions & 5 deletions packages/core/integration-tests/test/css.js
Expand Up @@ -264,6 +264,7 @@ describe('css', () => {
path.join(__dirname, '/integration/cssnano/index.js'),
{
minify: true,
sourceMaps: false,
},
);

Expand All @@ -275,19 +276,43 @@ describe('css', () => {
assert(css.includes('.local'));
assert(css.includes('.index'));

// TODO: Make this `2` when a `sourceMappingURL` is added
assert.equal(css.split('\n').length, 1);
});

it('should produce a sourcemap when sourceMaps are used', async function() {
await bundle(path.join(__dirname, '/integration/cssnano/index.js'), {
minify: true,
});

let css = await outputFS.readFile(path.join(distDir, 'index.css'), 'utf8');
assert(css.includes('.local'));
assert(css.includes('.index'));

let lines = css.trim().split('\n');
assert.equal(lines.length, 2);
assert.equal(lines[1], '/*# sourceMappingURL=index.css.map */');

let map = JSON.parse(
await outputFS.readFile(path.join(distDir, 'index.css.map'), 'utf8'),
);
assert.equal(map.file, 'index.css.map');
assert.equal(map.mappings, 'AAAA,OACA,WACA,CCFA,OACA,SACA');
assert.deepEqual(map.sources, [
'integration/cssnano/local.css',
'integration/cssnano/index.css',
]);
});

it('should inline data-urls for text-encoded files', async () => {
await bundle(path.join(__dirname, '/integration/data-url/text.css'));
await bundle(path.join(__dirname, '/integration/data-url/text.css'), {
sourceMaps: false,
});
let css = await outputFS.readFile(path.join(distDir, 'text.css'), 'utf8');
assert.equal(
css,
css.trim(),
`.svg-img {
background-image: url('data:image/svg+xml,%3Csvg%3E%0A%0A%3C%2Fsvg%3E%0A');
}
`,
}`,
);
});

Expand Down
18 changes: 11 additions & 7 deletions packages/core/integration-tests/test/html.js
Expand Up @@ -329,8 +329,8 @@ describe('html', function() {

// mergeStyles
assert(
html.includes(
'<style>h1{color:red}div{font-size:20px}</style><style media="print">div{color:#00f}</style>',
html.match(
/<style>h1{color:red}div{font-size:20px}\n\/\*# sourceMappingURL=.*\*\/<\/style><style media="print">div{color:#00f}\n\/\*# sourceMappingURL=.*\*\/<\/style>/,
),
);

Expand Down Expand Up @@ -834,7 +834,11 @@ describe('html', function() {
path.join(distDir, 'index.html'),
'utf8',
);
assert(html.includes('<style>.index{color:#00f}</style>'));
assert(
html.match(
/<style>.index{color:#00f}\n\/\*# sourceMappingURL=.*<\/style>/,
),
);
});

it('should process inline non-js scripts', async function() {
Expand Down Expand Up @@ -1159,8 +1163,8 @@ describe('html', function() {
path.join(distDir, html.match(/\/a\.[a-z0-9]+\.css/)[0]),
'utf8',
);
assert(css.includes('.a'));
assert(!css.includes('.b'));
assert(css.includes('.a {'));
assert(!css.includes('.b {'));

// b.html should point to a CSS bundle containing only b.css
// It should not point to the bundle containing a.css from a.html
Expand All @@ -1178,8 +1182,8 @@ describe('html', function() {
path.join(distDir, html.match(/\/b\.[a-z0-9]+\.css/)[0]),
'utf8',
);
assert(!css.includes('.a'));
assert(css.includes('.b'));
assert(!css.includes('.a {'));
assert(css.includes('.b {'));
});

it('should invalidate parent bundle when inline bundles change', async function() {
Expand Down
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
Empty file.
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
@@ -0,0 +1,6 @@
{
"name": "parcel-sourcemap-integration-test",
"version": "1.0.0",
"license": "MIT",
"private": true
}
10 changes: 6 additions & 4 deletions packages/core/integration-tests/test/javascript.js
Expand Up @@ -2099,15 +2099,17 @@ describe('javascript', function() {
path.join(__dirname, '/integration/bundle-text/index.js'),
);

assert.equal(
(await run(b)).default,
`body {
assert(
(await run(b)).default.startsWith(
`body {
background-color: #000000;
}

.svg-img {
background-image: url("data:image/svg+xml,%3Csvg%3E%0A%0A%3C%2Fsvg%3E%0A");
}`,
}
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,`,
),
);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/core/integration-tests/test/less.js
Expand Up @@ -108,7 +108,7 @@ describe('less', function() {
assert.equal(output(), 2);

let css = await outputFS.readFile(path.join(distDir, 'index.css'), 'utf8');
assert.equal(css, '');
assert.equal(css.trim(), '/*# sourceMappingURL=index.css.map */');
});

it('should support linking to assets with url() from less', async function() {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/integration-tests/test/sass.js
Expand Up @@ -101,7 +101,7 @@ describe('sass', function() {
assert.equal(output(), 2);

let css = await outputFS.readFile(path.join(distDir, 'index.css'), 'utf8');
assert.equal(css, '');
assert.equal(css.trim(), '/*# sourceMappingURL=index.css.map */');
});

it('should support linking to assets with url() from scss', async function() {
Expand Down