Skip to content

Commit

Permalink
feat: [transformers] add example formatting + compatible parsers (#586)
Browse files Browse the repository at this point in the history
This adds two new configuration options for transformers:
- compatibleParserIDs
- formatCodeExample

compatibleParserIDs is used in SELECT_TRANSFORMER as an alternative to
always resetting the parser when changing the transformer or turning it
on. If we are already on a compatible parser, we won't change.

formatCodeExample supports custom formatting/templating for code
examples - in the case of jscodeshift, this is used to set the
module.exports.parser based on current parser.

In combination, this supports a workflows like:
- Copy in a typescript file contents
- Change the parser to typescript
- Turn on the transform for jscodeshift
  • Loading branch information
ehzhang authored Aug 16, 2021
1 parent a8c7d5f commit 93d778e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// jscodeshift can take a parser, like "babel", "babylon", "flow", "ts", or "tsx"
// Read more: https://github.com/facebook/jscodeshift#parser
export const parser = '{{parser}}'

// Press ctrl+space for code completion
export default function transformer(file, api) {
const j = api.jscodeshift;
Expand Down
22 changes: 22 additions & 0 deletions website/src/parsers/js/transformers/jscodeshift/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,35 @@ const ID = 'jscodeshift';

const sessionMethods = new Set();

// https://github.com/facebook/jscodeshift#parser
const getJscodeshiftParser = (parser, parserSettings) => {
if (parser === 'typescript') {
if (parserSettings.typescript && parserSettings.typescript.jsx === false) {
return 'ts'
}
return 'tsx'
}
if (parser === 'flow') {
return 'flow'
}
return 'babel'
}

export default {
id: ID,
displayName: ID,
version: pkg.version,
homepage: pkg.homepage || 'https://github.com/facebook/jscodeshift',

defaultParserID: 'recast',
compatibleParserIDs: new Set([
'typescript',
'flow',
]),

formatCodeExample(codeExample, { parser, parserSettings }) {
return codeExample.replace('{{parser}}', `${getJscodeshiftParser(parser, parserSettings)}`)
},

loadTransformer(callback) {
require(['../../../transpilers/babel', 'jscodeshift'], (transpile, jscodeshift) => {
Expand Down
34 changes: 29 additions & 5 deletions website/src/store/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ function format(state=initialState.enableFormatting, action) {
return state;
}

function getDefaultTransform(transformer, workbenchState) {
if (typeof transformer.formatCodeExample === 'function') {
return transformer.formatCodeExample(
transformer.defaultTransform,
{
parser: workbenchState.parser,
parserSettings: workbenchState.parserSettings || {},
},
)
}
return transformer.defaultTransform
}

function workbench(state=initialState.workbench, action, fullState) {
function parserFromCategory(category) {
const parser = fullState.parserPerCategory[category.id] ||
Expand Down Expand Up @@ -143,15 +156,26 @@ function workbench(state=initialState.workbench, action, fullState) {
// Update parser settings
newState.parserSettings =
fullState.parserSettings[action.parser.id] || null;

// Check if we might want to reformat the code example
const transformer = getTransformerByID(state.transform.transformer)
if (transformer && state.transform.code === getDefaultTransform(transformer, state)) {
newState.transform = {
...state.transform,
code: getDefaultTransform(transformer, newState),
}
}
}
return newState;
}
case actions.SET_CODE:
return {...state, code: action.code};
case actions.SELECT_TRANSFORMER:
{
const parserIsCompatible =
action.transformer.compatibleParserIDs && action.transformer.compatibleParserIDs.has(state.parser)
const differentParser =
action.transformer.defaultParserID !== state.parser;
action.transformer.defaultParserID !== state.parser && !parserIsCompatible;
const differentTransformer =
action.transformer.id !== state.transform.transformer ;

Expand All @@ -176,10 +200,10 @@ function workbench(state=initialState.workbench, action, fullState) {
transformResult: null,
code: snippetHasDifferentTransform ?
state.transform.code :
action.transformer.defaultTransform,
getDefaultTransform(action.transformer, state),
initialCode: snippetHasDifferentTransform ?
fullState.activeRevision.getTransformCode() :
action.transformer.defaultTransform,
getDefaultTransform(action.transformer, state),
};
}

Expand Down Expand Up @@ -237,8 +261,8 @@ function workbench(state=initialState.workbench, action, fullState) {
const transformer = getTransformerByID(state.transform.transformer);
newState.transform = {
...state.transform,
code: transformer.defaultTransform,
initialCode: transformer.defaultTransform,
code: getDefaultTransform(transformer, state),
initialCode: getDefaultTransform(transformer, state),
};
}
return newState;
Expand Down

0 comments on commit 93d778e

Please sign in to comment.