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

Build: add support for native TypeScript #28879

Merged
merged 5 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 26 additions & 14 deletions bin/api-docs/update-api-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ const DATA_DOCS_DIR = resolve(
'docs/designers-developers/developers/data'
);

/**
* Default path to use if the token doesn't include one.
*
* @see TOKEN_PATTERN
*/
const DEFAULT_PATH = 'src/index.js';

/**
* Pattern matching start token of a README file.
*
Expand All @@ -64,7 +57,6 @@ const DEFAULT_PATH = 'src/index.js';
* <!-- END TOKEN(Autogenerated actions|src/actions.js) -->
*
* @type {RegExp}
* @see DEFAULT_PATH
*/
const TOKEN_PATTERN = /<!-- START TOKEN\((.+?(?:\|(.+?))?)\) -->/g;

Expand Down Expand Up @@ -169,7 +161,7 @@ const filterTokenTransform = new Transform( {
const tokens = [];

for ( const match of content.matchAll( TOKEN_PATTERN ) ) {
const [ , token, path = DEFAULT_PATH ] = match;
const [ , token, path ] = match;
tokens.push( [ token, path ] );
}

Expand All @@ -182,6 +174,23 @@ const filterTokenTransform = new Transform( {
},
} );

/**
* Find default source file (`src/index.{js,ts,tsx}`) in a specified package directory
*
* @param {string} dir Package directory to search in
* @return {string} Name of matching file
*/
function findDefaultSourcePath( dir ) {
const defaultPathMatches = glob.sync( 'src/index.{js,ts,tsx}', {
cwd: dir,
} );
if ( ! defaultPathMatches.length ) {
throw new Error( `Cannot find default source file in ${ dir }` );
}
// @ts-ignore
return defaultPathMatches[ 0 ];
}

/**
* Optional process arguments for which to generate documentation.
*
Expand All @@ -202,8 +211,11 @@ glob.stream( [
// represented by tokens. The docgen script updates one token at a time,
// so the tokens must be replaced in sequence to prevent the processes
// from overriding each other.
for ( const [ token, path ] of tokens ) {
try {
try {
for ( const [
token,
path = findDefaultSourcePath( dirname( file ) ),
] of tokens ) {
await execa(
`"${ join(
__dirname,
Expand All @@ -222,9 +234,9 @@ glob.stream( [
],
{ shell: true }
);
} catch ( error ) {
console.error( error );
process.exit( 1 );
}
} catch ( error ) {
console.error( error );
process.exit( 1 );
}
} );
7 changes: 6 additions & 1 deletion bin/packages/build-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ async function buildJS( file ) {
for ( const [ environment, buildDir ] of Object.entries(
JS_ENVIRONMENTS
) ) {
const destPath = getBuildPath( file, buildDir );
const destPath = getBuildPath(
file.replace( /\.tsx?$/, '.js' ),
buildDir
);
const babelOptions = getBabelConfig(
environment,
file.replace( PACKAGES_DIR, '@wordpress' )
Expand Down Expand Up @@ -171,6 +174,8 @@ async function buildJS( file ) {
const BUILD_TASK_BY_EXTENSION = {
'.scss': buildCSS,
'.js': buildJS,
'.ts': buildJS,
'.tsx': buildJS,
};

module.exports = async ( file, callback ) => {
Expand Down
2 changes: 1 addition & 1 deletion bin/packages/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ if ( files.length ) {

stream = glob.stream(
[
`${ PACKAGES_DIR }/*/src/**/*.js`,
`${ PACKAGES_DIR }/*/src/**/*.{js,ts,tsx}`,
`${ PACKAGES_DIR }/*/src/*.scss`,
`${ PACKAGES_DIR }/block-library/src/**/*.js`,
`${ PACKAGES_DIR }/block-library/src/*/style.scss`,
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 16 additions & 10 deletions packages/babel-plugin-makepot/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ describe( 'babel-plugin', () => {
describe( '.getExtractedComment()', () => {
function getCommentFromString( string ) {
let comment;
traverse( transformSync( string, { ast: true } ).ast, {
CallExpression( path ) {
comment = getExtractedComment( path );
},
} );
traverse(
transformSync( string, { ast: true, filename: 'test.js' } ).ast,
{
CallExpression( path ) {
comment = getExtractedComment( path );
},
}
);

return comment;
}
Expand Down Expand Up @@ -107,11 +110,14 @@ describe( 'babel-plugin', () => {
describe( '.getNodeAsString()', () => {
function getNodeAsStringFromArgument( source ) {
let string;
traverse( transformSync( source, { ast: true } ).ast, {
CallExpression( path ) {
string = getNodeAsString( path.node.arguments[ 0 ] );
},
} );
traverse(
transformSync( source, { ast: true, filename: 'test.js' } ).ast,
{
CallExpression( path ) {
string = getNodeAsString( path.node.arguments[ 0 ] );
},
}
);

return string;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/babel-preset-default/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### New Features

- Added `@babel/preset-typescript` so that the preset can by default transpile TypeScript files, too.

## 5.0.0 (2021-01-21)

### Breaking Changes
Expand Down
5 changes: 4 additions & 1 deletion packages/babel-preset-default/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ module.exports = ( api ) => {
};

return {
presets: [ getPresetEnv() ],
presets: [
getPresetEnv(),
require.resolve( '@babel/preset-typescript' ),
],
plugins: [
require.resolve( '@wordpress/warning/babel-plugin' ),
[
Expand Down
1 change: 1 addition & 0 deletions packages/babel-preset-default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@babel/plugin-transform-react-jsx": "^7.12.7",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.7",
"@babel/preset-typescript": "^7.12.7",
"@babel/runtime": "^7.12.5",
"@wordpress/babel-plugin-import-jsx-pragma": "file:../babel-plugin-import-jsx-pragma",
"@wordpress/browserslist-config": "file:../browserslist-config",
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-preset-default/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import babelPresetDefault from '../';

describe( 'Babel preset default', () => {
test( 'transpilation works properly', () => {
const input = readFileSync(
path.join( __dirname, '/fixtures/input.js' )
);
const filename = path.join( __dirname, '/fixtures/input.js' );
const input = readFileSync( filename );

const output = transform( input, {
filename,
configFile: false,
envName: 'production',
presets: [ babelPresetDefault ],
Expand Down
29 changes: 12 additions & 17 deletions packages/docgen/src/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
* External dependencies
*/
const babel = require( '@babel/core' );
const { flatten } = require( 'lodash' );

/**
* Internal dependencies
*/
const getIntermediateRepresentation = require( './get-intermediate-representation' );

const getAST = ( source ) => {
return babel.parse( source || '' ).program;
const getAST = ( source, filename ) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the issue description I gather we use this to signal the babel-preset-typescript babel is processing a tsx file, but I haven't found info about that here or here. Just curiosity, but it'd be nice to have some pointers to this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we're not using the @babel/parser module directly, but indirectly through the @babel/core module which exports a parse function. @babel/core loads the Babel config will all the plugins and presets, and then exposes a configured parser.

This parse method is documented here and the filename option is documented here.

If the filename option is not present, the parsing will fail with error:

Error: [BABEL] unknown: Preset /* your preset */ requires a filename to be set when babel is called directly,

babel.transform(code, { filename: 'file.ts', presets: [/* your preset */] });

See https://babeljs.io/docs/en/options#filename for more information.
at validateIfOptionNeedsFilename (/Users/jsnajdr/src/gutenberg/node_modules/@babel/core/lib/config/full.js:286:11)

return babel.parse( source, { filename } ).program;
};

const getExportTokens = ( ast ) =>
Expand All @@ -19,25 +18,21 @@ const getExportTokens = ( ast ) =>
'ExportNamedDeclaration',
'ExportDefaultDeclaration',
'ExportAllDeclaration',
].some( ( declaration ) => declaration === node.type )
].includes( node.type )
);

const engine = ( path, code, getIRFromPath = () => {} ) => {
const result = {};
result.ast = getAST( code );
result.tokens = getExportTokens( result.ast );
result.ir = flatten(
result.tokens.map( ( token ) =>
getIntermediateRepresentation(
path,
token,
result.ast,
getIRFromPath
)
)
if ( ! path || ! code ) {
return { ast: null, tokens: null, ir: [] };
}

const ast = getAST( code, path );
const tokens = getExportTokens( ast );
const ir = tokens.flatMap( ( token ) =>
getIntermediateRepresentation( path, token, ast, getIRFromPath )
);

return result;
return { ast, tokens, ir };
};

/**
Expand Down