Skip to content

Commit

Permalink
First-class MDX support (#10064)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett authored Jan 5, 2025
1 parent 4f3bcaa commit 337c31c
Show file tree
Hide file tree
Showing 28 changed files with 1,610 additions and 1,217 deletions.
226 changes: 118 additions & 108 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ napi = ["dep:napi", "dep:napi-derive", "dep:crossbeam-channel"]

[dependencies]
indexmap = "1.9.2"
swc_core = { version = "6.0.1", features = [
swc_core = { version = "9", features = [
"common",
"common_ahash",
"common_sourcemap",
Expand Down
2 changes: 1 addition & 1 deletion crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ pub enum JsValue {
}

pub struct Evaluator<'a> {
constants: HashMap<Id, Result<JsValue, Span>>,
pub constants: HashMap<Id, Result<JsValue, Span>>,
source_map: &'a SourceMap,
}

Expand Down
8 changes: 7 additions & 1 deletion packages/configs/default/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"@parcel/transformer-worklet",
"..."
],
"*.mdx": [
// For backward compatibility, include the old transformer
// so it is used if already installed in the project.
// Otherwise, the JS transformer will handle MDX.
"@parcel/transformer-mdx",
"@parcel/transformer-js"
],
"*.{js,mjs,jsm,jsx,es6,cjs,ts,tsx}": [
"@parcel/transformer-babel",
"@parcel/transformer-js",
Expand All @@ -33,7 +40,6 @@
"*.pug": ["@parcel/transformer-pug"],
"*.coffee": ["@parcel/transformer-coffeescript"],
"*.elm": ["@parcel/transformer-elm"],
"*.mdx": ["@parcel/transformer-mdx"],
"*.vue": ["@parcel/transformer-vue"],
"template:*.vue": ["@parcel/transformer-vue"],
"script:*.vue": ["@parcel/transformer-vue"],
Expand Down
4 changes: 3 additions & 1 deletion packages/configs/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
"@parcel/transformer-inline-string": "2.13.3",
"@parcel/transformer-jsonld": "2.13.3",
"@parcel/transformer-less": "2.13.3",
"@parcel/transformer-mdx": "2.13.3",
"@parcel/transformer-pug": "2.13.3",
"@parcel/transformer-sass": "2.13.3",
"@parcel/transformer-stylus": "2.13.3",
Expand All @@ -76,6 +75,9 @@
"@parcel/transformer-xml": "2.13.3",
"@parcel/transformer-yaml": "2.13.3"
},
"optionalParcelDependencies": [
"@parcel/transformer-mdx"
],
"peerDependencies": {
"@parcel/core": "^2.13.3"
}
Expand Down
7 changes: 6 additions & 1 deletion packages/configs/default/test/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import assert from 'assert';

import config from '../';
import packageJson from '../package.json';
import json5 from 'json5';
import fs from 'fs';

describe('@parcel/config-default', () => {
let packageJsonDependencyNames: Set<string>;
Expand All @@ -13,7 +14,11 @@ describe('@parcel/config-default', () => {
packageJsonDependencyNames = new Set([
...Object.keys(packageJson.dependencies || {}),
...Object.keys(packageJson.parcelDependencies || {}),
...packageJson.optionalParcelDependencies,
]);
let config = json5.parse(
fs.readFileSync(__dirname + '/../index.json', 'utf8'),
);
configPackageReferences = collectConfigPackageReferences(config);
});

Expand Down
18 changes: 12 additions & 6 deletions packages/core/core/src/ParcelConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import ThrowableDiagnostic, {
generateJSONCodeHighlights,
} from '@parcel/diagnostic';
import json5 from 'json5';
import nullthrows from 'nullthrows';

import {globToRegex} from '@parcel/utils';
import {basename} from 'path';
Expand Down Expand Up @@ -121,7 +122,7 @@ export default class ParcelConfig {
version: Semver,
resolveFrom: ProjectPath,
range: ?SemverRange,
|}> {
|} | null> {
let plugin = this.pluginCache.get(node.packageName);
if (plugin) {
return plugin;
Expand All @@ -138,8 +139,11 @@ export default class ParcelConfig {
return plugin;
}

async loadPlugin<T>(node: ParcelPluginNode): Promise<LoadedPlugin<T>> {
async loadPlugin<T>(node: ParcelPluginNode): Promise<LoadedPlugin<T> | null> {
let plugin = await this._loadPlugin(node);
if (!plugin) {
return null;
}
return {
...plugin,
name: node.packageName,
Expand All @@ -151,10 +155,12 @@ export default class ParcelConfig {
this.pluginCache.delete(packageName);
}

loadPlugins<T>(
async loadPlugins<T>(
plugins: PureParcelConfigPipeline,
): Promise<Array<LoadedPlugin<T>>> {
return Promise.all(plugins.map(p => this.loadPlugin<T>(p)));
return (await Promise.all(plugins.map(p => this.loadPlugin<T>(p)))).filter(
Boolean,
);
}

async getResolvers(): Promise<Array<LoadedPlugin<Resolver<mixed>>>> {
Expand Down Expand Up @@ -228,7 +234,7 @@ export default class ParcelConfig {
);
}

return this.loadPlugin<Bundler<mixed>>(this.bundler);
return nullthrows(await this.loadPlugin<Bundler<mixed>>(this.bundler));
}

async getNamers(): Promise<Array<LoadedPlugin<Namer<mixed>>>> {
Expand Down Expand Up @@ -265,7 +271,7 @@ export default class ParcelConfig {
'/packagers',
);
}
return this.loadPlugin<Packager<mixed, mixed>>(packager);
return nullthrows(await this.loadPlugin<Packager<mixed, mixed>>(packager));
}

_getOptimizerNodes(
Expand Down
5 changes: 5 additions & 0 deletions packages/core/core/src/Transformation.js
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,11 @@ export default class Transformation {
configKeyPath?: string,
parcelConfig: ParcelConfig,
): Promise<$ReadOnlyArray<TransformerResult | UncommittedAsset>> {
if (asset.transformers.has(transformerName)) {
return [asset];
}
asset.transformers.add(transformerName);

const logger = new PluginLogger({origin: transformerName});
const tracer = new PluginTracer({
origin: transformerName,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/core/src/UncommittedAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default class UncommittedAsset {
idBase: ?string;
invalidations: Invalidations;
generate: ?() => Promise<GenerateOutput>;
transformers: Set<string>;

constructor({
value,
Expand All @@ -74,6 +75,7 @@ export default class UncommittedAsset {
this.isASTDirty = isASTDirty || false;
this.idBase = idBase;
this.invalidations = invalidations || createInvalidations();
this.transformers = new Set();
}

/*
Expand Down
16 changes: 9 additions & 7 deletions packages/core/core/src/assetUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,16 @@ async function _generateFromAST(asset: CommittedAsset | UncommittedAsset) {
}

let pluginName = nullthrows(asset.value.plugin);
let {plugin} = await loadPlugin<Transformer<mixed>>(
pluginName,
fromProjectPath(
asset.options.projectRoot,
nullthrows(asset.value.configPath),
let {plugin} = nullthrows(
await loadPlugin<Transformer<mixed>>(
pluginName,
fromProjectPath(
asset.options.projectRoot,
nullthrows(asset.value.configPath),
),
nullthrows(asset.value.configKeyPath),
asset.options,
),
nullthrows(asset.value.configKeyPath),
asset.options,
);
let generate = plugin.generate?.bind(plugin);
if (!generate) {
Expand Down
20 changes: 16 additions & 4 deletions packages/core/core/src/loadParcelPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ export default async function loadPlugin<T>(
version: Semver,
resolveFrom: ProjectPath,
range: ?SemverRange,
|}> {
|} | null> {
let resolveFrom = configPath;
let range;
if (resolveFrom.includes(NODE_MODULES)) {
let isOptional = false;
if (
resolveFrom.includes(NODE_MODULES) ||
(process.env.PARCEL_BUILD_ENV !== 'production' &&
/packages[/\\]configs/.test(resolveFrom))
) {
// Config packages can reference plugins, but cannot contain other plugins within them.
// This forces every published plugin to be published separately so they can be mixed and matched if needed.
if (pluginName.startsWith('.')) {
Expand Down Expand Up @@ -75,8 +80,11 @@ export default async function loadPlugin<T>(
// If not in the config's dependencies, the plugin will be auto installed with
// the version declared in "parcelDependencies".
range = configPkg.config.parcelDependencies?.[pluginName];
isOptional =
Array.isArray(configPkg.config.optionalParcelDependencies) &&
configPkg.config.optionalParcelDependencies.includes(pluginName);

if (range == null) {
if (range == null && !isOptional) {
let contents = await options.inputFS.readFile(
configPkg.files[0].filePath,
'utf8',
Expand Down Expand Up @@ -122,7 +130,7 @@ export default async function loadPlugin<T>(
pluginName,
resolveFrom,
{
shouldAutoInstall: options.shouldAutoInstall,
shouldAutoInstall: options.shouldAutoInstall && !isOptional,
range,
},
));
Expand All @@ -131,6 +139,10 @@ export default async function loadPlugin<T>(
throw err;
}

if (isOptional) {
return null;
}

let configContents = await options.inputFS.readFile(configPath, 'utf8');
let alternatives = await findAlternativeNodeModules(
options.inputFS,
Expand Down
13 changes: 8 additions & 5 deletions packages/core/core/test/ParcelConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {inputFS} from '@parcel/test-utils';
import {parseAndProcessConfig} from '../src/requests/ParcelConfigRequest';
import {DEFAULT_OPTIONS} from './test-utils';
import {toProjectPath} from '../src/projectPath';
import nullthrows from 'nullthrows';

const PARCELRC_PATH = toProjectPath('/', '/.parcelrc');

Expand Down Expand Up @@ -148,11 +149,13 @@ describe('ParcelConfig', () => {
);

let warnStub = sinon.stub(logger, 'warn');
let {plugin} = await config.loadPlugin({
packageName: 'parcel-transformer-no-engines',
resolveFrom: configFilePath,
keyPath: '/transformers/*.js/0',
});
let {plugin} = nullthrows(
await config.loadPlugin({
packageName: 'parcel-transformer-no-engines',
resolveFrom: configFilePath,
keyPath: '/transformers/*.js/0',
}),
);
assert(plugin);
assert.equal(typeof plugin.transform, 'function');
assert(warnStub.calledOnce);
Expand Down
4 changes: 3 additions & 1 deletion packages/core/core/test/ParcelConfigRequest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
import {validatePackageName} from '../src/ParcelConfig.schema';
import {DEFAULT_OPTIONS, relative} from './test-utils';
import {toProjectPath} from '../src/projectPath';
import json5 from 'json5';
import fs from 'fs';

describe('ParcelConfigRequest', () => {
describe('validatePackageName', () => {
Expand Down Expand Up @@ -696,7 +698,7 @@ describe('ParcelConfigRequest', () => {
let defaultConfigPath = require.resolve('@parcel/config-default');
let defaultConfig = await processConfig(
{
...require('@parcel/config-default'),
...json5.parse(fs.readFileSync(defaultConfigPath, 'utf8')),
filePath: defaultConfigPath,
},
DEFAULT_OPTIONS,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"dependencies": {
"react": "*"
"react": "^19"
}
}
Loading

0 comments on commit 337c31c

Please sign in to comment.