Skip to content

Commit

Permalink
helps to actually add the files 🤦
Browse files Browse the repository at this point in the history
  • Loading branch information
etrepum committed May 1, 2024
1 parent d4f2423 commit b5c18c6
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 0 deletions.
107 changes: 107 additions & 0 deletions scripts/www/__tests__/unit/transformFlowFileContents.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
// @ts-check
'use strict';

const transformFlowFileContents = require('../../transformFlowFileContents');

const HEADER_BEFORE =
`
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/
`.trim() + '\n';

const HEADER_AFTER =
`
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @generated
* @oncall lexical_web_text_editor
*/
`.trim() + '\n';

const IMPORTS_BEFORE =
`
import type {Doc, RelativePosition, UndoManager, XmlText} from 'yjs';
import type {
DecoratorNode,
EditorState,
ElementNode,
LexicalCommand,
LexicalEditor,
LexicalNode,
LineBreakNode,
NodeMap,
NodeKey,
TextNode,
} from 'lexical';
`.trim() + '\n';

const IMPORTS_AFTER =
`
import type {Doc, RelativePosition, UndoManager, XmlText} from 'yjs';
import type {
DecoratorNode,
EditorState,
ElementNode,
LexicalCommand,
LexicalEditor,
LexicalNode,
LineBreakNode,
NodeMap,
NodeKey,
TextNode,
} from 'Lexical';
`.trim() + '\n';

const EXTRA_BLOCK_COMMENT =
`
/**
* LexicalDevToolsCore
*/
`.trim() + '\n';

describe('transformFlowFileContents', () => {
[
{
input: [HEADER_BEFORE, IMPORTS_BEFORE, EXTRA_BLOCK_COMMENT].join('\n'),
output: [HEADER_AFTER, IMPORTS_AFTER, EXTRA_BLOCK_COMMENT].join('\n'),
title: 'header-imports-comment',
},
{
input: [HEADER_BEFORE, EXTRA_BLOCK_COMMENT].join('\n'),
output: [HEADER_AFTER, EXTRA_BLOCK_COMMENT].join('\n'),
title: 'header-comment',
},
{
input: [HEADER_BEFORE, IMPORTS_BEFORE].join('\n'),
output: [HEADER_AFTER, IMPORTS_AFTER].join('\n'),
title: 'header-imports',
},
{
input: [HEADER_BEFORE].join('\n'),
output: [HEADER_AFTER].join('\n'),
title: 'header',
},
].forEach(({input, output, title}) => {
it(`transforms ${title}`, async () => {
expect(await transformFlowFileContents(input)).toBe(output);
});
});
});
90 changes: 90 additions & 0 deletions scripts/www/transformFlowFileContents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

'use strict';

const {packagesManager} = require('../shared/packagesManager');
const npmToWwwName = require('./npmToWwwName');
const {t, transform} = require('hermes-transform');
const prettier = require('prettier');

const wwwMappings = Object.fromEntries(
packagesManager
.getPublicPackages()
.flatMap((pkg) =>
pkg.getExportedNpmModuleNames().map((npm) => [npm, npmToWwwName(npm)]),
),
);

const prettierConfig = prettier.resolveConfig('./').then((cfg) => cfg || {});

/**
* Add a statement to the end of the code so the comments don't
* disappear. This is a workaround for a hermes transform issue.
*
* @param {string} code
*/
function wrapCode(code) {
return [code, 'export {};\n'].join('\n');
}

/**
* The inverse transform of wrapCode, removes the added statement.
*
* @param {string} code
*/
function unwrapCode(code) {
return code.replace(/\n+export {};\n?$/, '\n');
}

/**
* It would be nice to use jscodeshift for this but the flow sources are using
* ast features that are not supported in ast-types (as of 2024-04-11) so it's
* not possible to traverse the tree and replace the imports & comments.
*
* It might be possible going straight to flow-parser, but it was a slew of
* hardcoded regexps before and now it's at least automated based on the
* exports.
*
* @param {string} source
* @returns {Promise<string>} transformed source
*/
module.exports = async function transformFlowFileContents(source) {
return unwrapCode(
await transform(
wrapCode(source),
(context) => ({
ImportDeclaration(node) {
const value = wwwMappings[node.source.value];
if (value) {
context.replaceNode(node.source, t.StringLiteral({value}));
}
},
Program(node) {
if (
node.docblock &&
node.docblock.comment &&
node.docblock.comment.value.includes('@flow strict')
) {
// This is mutated in-place because I couldn't find a mutation that
// did not fail for replacing the Program node.
node.docblock.comment.value = node.docblock.comment.value.replace(
/ \* @flow strict/g,
' * @flow strict\n * @generated\n * @oncall lexical_web_text_editor',
);
// We need the mutations array to be non-empty, so remove something
// that is not there. The AST traversals use object identity in a
// Set so we don't have to worry about some other line changing.
context.removeComments(t.LineComment({value: ''}));
}
},
}),
await prettierConfig,
),
);
};

0 comments on commit b5c18c6

Please sign in to comment.