Skip to content

Commit

Permalink
docs: S2 migration docs and codemod setup (adobe#6828)
Browse files Browse the repository at this point in the history
* initialize migration docs

* more docs for Item updates

* move upgrade-cli to codemods package

* improve rendered diffs

* setup codemod entry

* update yarn.lock

* fix component index path resolving

* update package.json

* update yarn.lock

* move to src

* update component index path

* update lock file

* fix ts

* update command in docs

* fix --components option for providing a subset of components to upgrade

* update docs to not collapse manual guide

* update index to use parseArgs and pass args into codemod functions

* just rely on require.resolve to get S2 index path

* remove commander dep

* move use-monopackages codemod into new package

* update @react-spectrum/s2 dep

* update yarn.lock

* fix types and update use-monopackages readme

* try removing main from package.json

* use path module

* use moduleResolution in tsconfig

* remove module.exports

* try renaming transformer functions

* Revert "try renaming transformer functions"

This reverts commit b2177f7.

* try targets: main: false in package.json

* move to packages/dev

* update docs

* add anchor links

* update yarn.lock

* fix anchor links in built docs

---------

Co-authored-by: Robert Snow <[email protected]>
  • Loading branch information
reidbarber and snowystinger authored Aug 15, 2024
1 parent e2bf18a commit 6932a9f
Show file tree
Hide file tree
Showing 145 changed files with 1,128 additions and 163 deletions.
779 changes: 779 additions & 0 deletions .storybook-s2/docs/Migrating.jsx

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions .storybook-s2/docs/Migrating.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {Migrating} from './Migrating.jsx';
import {H3} from './typography';

<Migrating />
37 changes: 33 additions & 4 deletions .storybook-s2/docs/typography.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
import { style } from '../../packages/@react-spectrum/s2/style/spectrum-theme' with {type: 'macro'};
import {Link} from '@react-spectrum/s2';
import {useFocusRing, useHover} from 'react-aria';

function AnchorLink({id, isHovered}) {
let { isFocusVisible, focusProps } = useFocusRing({within: true});
const url = `${location.origin}${location.pathname.replace('iframe', 'index')}${location.search.replace('viewMode=docs&id=', 'path=/docs/')}#${id}`;
return (
<span {...focusProps} style={{opacity: isHovered || isFocusVisible ? 1 : 0}}>
<Link href={url}>#</Link>
</span>
);
}

export function H2({children}) {
let id = anchorId(children);
return <h2 className={style({font: 'heading-xl', marginTop: 48, marginBottom: 24})} id={id}>{children}</h2>
let {hoverProps, isHovered} = useHover({});
return (
<h2 className={style({font: 'heading-xl', marginTop: 48, marginBottom: 24, display: 'flex', alignItems: 'center', gap: 8})} id={id} {...hoverProps}>
{children}
<AnchorLink id={id} isHovered={isHovered} />
</h2>
)
}

export function H3({children}) {
let id = anchorId(children);
return <h3 className={style({font: 'heading', marginTop: 32, marginBottom: 16})} id={anchorId(children)}>{children}</h3>
let {hoverProps, isHovered} = useHover({});
return (
<h3 className={style({font: 'heading', marginTop: 32, marginBottom: 16, display: 'flex', alignItems: 'center', gap: 8})} id={id} {...hoverProps}>
{children}
<AnchorLink id={id} isHovered={isHovered} />
</h3>
);
}

export function H4({children}) {
let id = anchorId(children);
return <h4 className={style({font: 'heading-sm', marginTop: 32, marginBottom: 8})} id={anchorId(children)}>{children}</h4>
let {hoverProps, isHovered} = useHover({});
return (
<h4 className={style({font: 'heading-sm', marginTop: 32, marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8})} id={id} {...hoverProps}>
{children}
<AnchorLink id={id} isHovered={isHovered} />
</h4>
);
}

export function P({children}) {
return <p className={style({font: 'body-lg', marginTop: 0, marginBottom: 24})}>{children}</p>
}

export function Code({children}) {
return <code className={style({font: 'code-sm', backgroundColor: 'layer-1', paddingX: 4, borderWidth: 1, borderColor: 'gray-100', borderStyle: 'solid', borderRadius: 'sm'})}>{children}</code>;
return <code className={style({font: 'code-sm', backgroundColor: 'layer-1', paddingX: 4, borderWidth: 1, borderColor: 'gray-100', borderStyle: 'solid', borderRadius: 'sm', whiteSpace: 'pre-wrap'})}>{children}</code>;
}

export function Strong({children}) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"name": "@react-spectrum/upgrade-cli",
"name": "@react-spectrum/codemods",
"version": "0.0.1",
"private": true,
"source": "src/index.ts",
"main": "dist/index.js",
"bin": {
"upgrade-react-spectrum": "./dist/index.js"
"source": "src/index.ts",
"bin": "dist/index.js",
"targets": {
"main": false
},
"scripts": {
"start": "node --loader=ts-node/esm src/index.ts"
"build": "tsc",
"prepublishOnly": "yarn build"
},
"files": [
"dist"
Expand All @@ -23,12 +25,12 @@
"@babel/parser": "^7.24.5",
"@babel/traverse": "^7.24.5",
"@babel/types": "^7.24.5",
"@react-spectrum/s2": "^0.2.0",
"@react-types/shared": "^3.24.0",
"@types/node": "^20",
"boxen": "^5.1.2",
"build": "^0.1.4",
"chalk": "^4.0.0",
"commander": "^12.0.0",
"execa": "^5.1.1",
"jscodeshift": "^0.15.2",
"ts-node": "^10.9.2",
Expand Down
100 changes: 100 additions & 0 deletions packages/dev/codemods/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const {parseArgs} = require('node:util');
import {s1_to_s2} from './s1-to-s2/src';
import {use_monopackages} from './use-monopackages/src';

interface JSCodeshiftOptions {
/**
* The parser for jscodeshift to use for parsing the source files: https://github.com/facebook/jscodeshift?tab=readme-ov-file#parser.
*
* @default 'tsx'
*/
parser?: 'babel' | 'babylon' | 'flow' | 'ts' |' tsx',
/**
* A glob pattern of files to ignore: https://github.com/facebook/jscodeshift?tab=readme-ov-file#ignoring-files-and-directories.
*
* @default '*\*\/node_modules/*\*\'
*/
ignorePattern?: string,
/**
* Whether to run the codemod in dry mode, which will not write any changes to disk.
*
* @default false
*/
dry?: boolean,
/**
* The path to the directory to run the codemod in.
*
* @default '.'
*/
path?: string
}

export interface S1ToS2CodemodOptions extends JSCodeshiftOptions {
/**
* An optional subset of components to have the s1-to-s2 codemod apply to.
* Provide a comma-separated list of component names.
*/
components?: string
}

export interface UseMonopackagesCodemodOptions extends JSCodeshiftOptions {
/**
* The packages to apply the use-monopackages codemod to.
*/
packages?: string
}

const codemods: Record<string, (options: S1ToS2CodemodOptions | UseMonopackagesCodemodOptions) => void> = {
's1-to-s2': s1_to_s2,
'use-monopackages': use_monopackages
};

// https://github.com/facebook/jscodeshift?tab=readme-ov-file#usage-cli
const options = {
'parser': {
type: 'string'
},
'ignore-pattern': {
type: 'string'
},
'dry': {
type: 'boolean',
short: 'd'
},
'path': {
type: 'string'
},
'components': {
type: 'string'
}
};

const {values, positionals} = parseArgs({
options,
allowPositionals: true
});

if (positionals.length < 1) {
console.error('Please specify a codemod to run. Available codemods: ', Object.keys(codemods).join(', '));
process.exit(1);
}

const codemodName = positionals[0];
const codemodFunction = codemods[codemodName];

if (!codemodFunction) {
console.error(`Unknown codemod: ${codemodName}, available codemods: ${Object.keys(codemods).join(', ')}`);
process.exit(1);
}

try {
codemodFunction({
parser: 'tsx',
ignorePattern: '**/node_modules/**',
path: '.',
...values
});
} catch (error) {
console.error(`Error running codemod: ${error}`);
process.exit(1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A CLI tool for upgrading React Spectrum components to Spectrum 2.

## Usage

Run `npx @react-spectrum/upgrade-cli` from the directory you want to upgrade.
Run `npx @react-spectrum/codemods s1-to-s2` from the directory you want to upgrade.

### Options

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ Note that `[PENDING]` indicates that future changes will occur before the final
- Remove `isReadOnly` (it is no longer supported)
- Remove `validationState` (it is no longer supported)
- Remove `validationBehavior` (it is no longer supported)
- TODO: Clarify/verify the above

## Grid
- Update `Grid` to be a `div` and apply grid styles using the style macro
Expand Down Expand Up @@ -357,8 +356,8 @@ Dimension values should be converted to pixel values. Use the following mappings
| `'static-size-0'` | `0` |
| `'static-size-10'` | `1` |
| `'static-size-25'` | `2` |
| `'static-size-50'` | `4` |
| `'static-size-40'` | `3` |
| `'static-size-50'` | `4` |
| `'static-size-65'` | `5` |
| `'static-size-100'` | `8` |
| `'static-size-115'` | `9` |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Dynamic - Renames Item to ComboboxItem 1`] = `
exports[`Dynamic - Renames Item to ComboBoxItem 1`] = `
"import { ComboBoxItem, ComboBox } from "@react-spectrum/s2";
import { Item } from '@adobe/react-spectrum';
let options = [
Expand Down Expand Up @@ -140,7 +140,7 @@ let props = {menuWidth: 'size-10'};
</div>"
`;

exports[`Static - Renames Item to ComboboxItem 1`] = `
exports[`Static - Renames Item to ComboBoxItem 1`] = `
"import { ComboBoxItem, ComboBox } from "@react-spectrum/s2";
import { Item } from '@adobe/react-spectrum';
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Should not update components that are not provided to --components option 1`] = `
"import {Button, TextArea} from '@adobe/react-spectrum';
<div>
<Button variant="cta">Test</Button>
<Button variant="overBackground">Test</Button>
<TextArea isQuiet />
</div>"
`;

exports[`Should only update components provided to --components option 1`] = `
"import { TextArea } from '@adobe/react-spectrum';
import { Button } from "@react-spectrum/s2";
<div>
<Button variant="accent">Test</Button>
<Button variant="primary" staticColor="white">Test</Button>
<TextArea isQuiet />
</div>"
`;

exports[`Should update multiple components provided to --components option 1`] = `
"import { Button, TextArea } from "@react-spectrum/s2";
<div>
<Button variant="accent">Test</Button>
<Button variant="primary" staticColor="white">Test</Button>
<TextArea />
</div>"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const test = (name: string, input: string) => {
defineSnapshotTest(transform, {}, input, name);
};

test('Static - Renames Item to ComboboxItem', `
test('Static - Renames Item to ComboBoxItem', `
import {ComboBox, Item} from '@adobe/react-spectrum';
<div>
<ComboBox label="Favorite Animal">
Expand All @@ -27,7 +27,7 @@ let externalKey = 'travel';
</div>
`);

test('Dynamic - Renames Item to ComboboxItem', `
test('Dynamic - Renames Item to ComboBoxItem', `
import {ComboBox, Item} from '@adobe/react-spectrum';
let options = [
{id: 1, name: 'Aerospace'},
Expand Down
37 changes: 37 additions & 0 deletions packages/dev/codemods/src/s1-to-s2/__tests__/subset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @ts-ignore
import {defineSnapshotTest} from 'jscodeshift/dist/testUtils';
import transform from '../src/codemods/codemod';

const testSubset = (name: string, input: string, components: string) => {
defineSnapshotTest(transform, {components}, input, name);
};

testSubset('Should update multiple components provided to --components option', `
import {Button, TextArea} from '@adobe/react-spectrum';
<div>
<Button variant="cta">Test</Button>
<Button variant="overBackground">Test</Button>
<TextArea isQuiet />
</div>
`, 'Button,TextArea');

testSubset('Should only update components provided to --components option', `
import {Button, TextArea} from '@adobe/react-spectrum';
<div>
<Button variant="cta">Test</Button>
<Button variant="overBackground">Test</Button>
<TextArea isQuiet />
</div>
`, 'Button');

testSubset('Should not update components that are not provided to --components option', `
import {Button, TextArea} from '@adobe/react-spectrum';
<div>
<Button variant="cta">Test</Button>
<Button variant="overBackground">Test</Button>
<TextArea isQuiet />
</div>
`, 'TableView');
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ function getStylePropValue(prop: string, value: t.ObjectProperty['value'], eleme
let values: string[] = [];
for (let element of value.elements) {
if (element?.type === 'StringLiteral' || element?.type === 'NumericLiteral') {
values.push(convertGridTrack(element.value));
values.push(convertGridTrack(element.value) as string);
} else if (element?.type === 'CallExpression') {
// TODO: match to import using scope
if (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {parse} from '@babel/parser';
const path = require('path');
import {readFileSync} from 'fs';
import traverse from '@babel/traverse';

export function getComponents() {
export function getComponents(): Set<string> {
// Determine list of available components in S2 from index.ts
let availableComponents = new Set();
// TODO: this won't work once we publish the upgrade-cli (dir structure will be different).
let index = parse(readFileSync(__dirname + '/../../s2/src/index.ts', 'utf8'), {sourceType: 'module', plugins: ['typescript']});
let availableComponents = new Set<string>();
const packagePath = require.resolve('@react-spectrum/s2');
const indexPath = path.join(path.dirname(packagePath), 'src/index.ts');
let index = parse(readFileSync(indexPath, 'utf8'), {sourceType: 'module', plugins: ['typescript']});
traverse(index, {
ExportNamedDeclaration(path) {
if (path.node.exportKind === 'value') {
Expand Down
Loading

0 comments on commit 6932a9f

Please sign in to comment.