-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Tooling]
yarn splash
(beta) (#2113)
* First iteration of the observer CLI * Load .ts files too * Add graph script * Enable compilation of .ts files * Remove tinycolor2 dependency * Make filter more portable across environments * Add scoping to getGitStagedFiles * Try to use functions from treebuilder.ts * Add types * Fix filter * Formatting * Remove absolute part of the path * Plug data from git status and improve listing * Rename script to yarn splash, add watcher mode * Align summary text to the right * Change filtering * Add temporary workaround to the skipIndexFile function * Move treebuilder.ts to scripts/splash * Remove skipIndexFile * Add docs * Add changelog item * Add mention that the watcher is still alpha * Remove unused type dependency * Add missing space * Add missing space * Verifies the index file is in a component folder * Account for .ts files * Show utils.tsx files again * Handle loading status properly * Stop filtering index.ts files out * Integrate with storybook * Make component grid layout responsive * Delete watch mode * Update useEffects flow * enum * Revert "enum" This reverts commit 7eeba2a. * Revert "Update useEffects flow" This reverts commit 7dd8e0a.
- Loading branch information
Showing
9 changed files
with
539 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"rules": { | ||
"jsx-a11y/accessible-emoji": "off", | ||
"shopify/jsx-no-hardcoded-content": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# `yarn splash` (beta) | ||
|
||
`yarn splash` is a command-line interface to observe the splash zone of a change across the component library. | ||
|
||
It answers the question: | ||
|
||
> When I modify a component, what parts of the system did that also touch (also known as the change’s “splash zone”)? | ||
## How to use `yarn splash` | ||
|
||
1. Edit files in `src/`, such as components 🧩 and style sheets 🎨 | ||
2. Run `yarn splash` to see the splash zone of your changes in the working directory | ||
|
||
💡 Tip: <kbd>command</kbd> + click a file path to open it in your text editor | ||
|
||
## Feedback and bug reports | ||
|
||
Found an issue or want to share feedback? | ||
|
||
Reach out on Slack in [#polaris-tooling](https://shopify.slack.com/messages/CCNUS0FML). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
import path from 'path'; | ||
import React, {useState, useEffect} from 'react'; | ||
import {Box, Text, Color, render} from 'ink'; | ||
import sortBy from 'lodash/sortBy'; | ||
import {getGitStagedFiles, getDependencies} from './treebuilder'; | ||
|
||
const excludedFileNames = (fileName) => | ||
!fileName.includes('test') && !fileName.includes('types'); | ||
|
||
const getEmojiForExtension = (extension) => { | ||
switch (extension) { | ||
case '.tsx': | ||
case '.ts': | ||
return '🧩'; | ||
case '.scss': | ||
return '🎨'; | ||
default: | ||
return '❔'; | ||
} | ||
}; | ||
|
||
const formatDependencies = (dependencies) => | ||
dependencies | ||
.filter(({fileName}) => excludedFileNames(fileName)) | ||
.map((dependency) => ({ | ||
pathname: `${path.dirname(dependency.fileName)}/`, | ||
filename: path.basename(dependency.fileName), | ||
dependencies: sortBy( | ||
dependency.dependencies.filter(excludedFileNames).map((dependency) => ({ | ||
pathname: `${path.dirname(dependency)}/`, | ||
filename: path.basename(dependency), | ||
componentName: path | ||
.dirname(dependency) | ||
.replace('src/components/', '') | ||
.split('/')[0], | ||
})), | ||
['pathname', 'filename'], | ||
), | ||
})); | ||
|
||
const Component = ({pathname, filename, dependencies}) => ( | ||
<Box marginBottom={1} flexDirection="column"> | ||
<Box> | ||
<Box width={3}>{getEmojiForExtension(path.extname(filename))}</Box> | ||
<Text bold> | ||
<Color greenBright> | ||
{pathname} | ||
{filename} | ||
</Color> | ||
</Text> | ||
</Box> | ||
<Box marginLeft={3}> | ||
<Box width={23}>Component name</Box> | ||
Files potentially affected (total: {dependencies.length}) | ||
</Box> | ||
{dependencies.map(({pathname, filename, componentName}) => ( | ||
<Box | ||
marginLeft={3} | ||
key={pathname + filename} | ||
flexDirection={process.stdout.columns > 80 ? 'row' : 'column'} | ||
> | ||
<Box width={23}> | ||
<Color dim>{'<'}</Color> | ||
<Color>{componentName}</Color> | ||
<Color dim>{' />'}</Color> | ||
</Box> | ||
<Box textWrap="wrap"> | ||
<Color dim>{pathname}</Color> | ||
{filename} | ||
</Box> | ||
</Box> | ||
))} | ||
</Box> | ||
); | ||
|
||
const Components = ({components, status}) => ( | ||
<React.Fragment> | ||
{status === 'loading' && ( | ||
<Box marginLeft={4} marginBottom={1}> | ||
⏳{' '}Please wait during compilation… Beep boop beep 🤖 | ||
</Box> | ||
)} | ||
|
||
{status === 'loaded' && | ||
components.map(({pathname, filename, dependencies}) => ( | ||
<Component | ||
key={pathname + filename} | ||
pathname={pathname} | ||
filename={filename} | ||
dependencies={dependencies} | ||
/> | ||
))} | ||
</React.Fragment> | ||
); | ||
|
||
const Summary = ({ | ||
componentsModified, | ||
dependencies, | ||
status, | ||
}: { | ||
componentsModified: number; | ||
dependencies: number; | ||
status: string; | ||
}) => ( | ||
<Box flexDirection="column"> | ||
<Box> | ||
<Box width={30}> | ||
<Text>Files modified:</Text> | ||
</Box> | ||
<Box justifyContent="flex-end" width={3}> | ||
{componentsModified} | ||
</Box> | ||
</Box> | ||
<Box> | ||
<Box width={30}> | ||
<Text>Files potentially affected:</Text> | ||
</Box> | ||
<Box justifyContent="flex-end" width={3}> | ||
{status === 'loading' ? '⏳' : dependencies} | ||
</Box> | ||
</Box> | ||
</Box> | ||
); | ||
|
||
const App = () => { | ||
const [stagedFiles, setStagedFiles] = useState([]); | ||
const [data, setData] = useState([]); | ||
const [dataStatus, setDataStatus] = useState('loading'); | ||
|
||
useEffect(() => { | ||
const getStagedFiles = async () => { | ||
const staged = (await getGitStagedFiles('src/')) as string[]; | ||
setStagedFiles(staged); | ||
|
||
if (staged.length === 0) { | ||
setDataStatus('loaded'); | ||
} | ||
}; | ||
getStagedFiles(); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (stagedFiles.length > 0) { | ||
const dependencies = getDependencies( | ||
'src/**/*.tsx', | ||
'*.test.tsx', | ||
stagedFiles, | ||
); | ||
setData(formatDependencies(dependencies)); | ||
setDataStatus('loaded'); | ||
} | ||
}, [setData, stagedFiles]); | ||
|
||
return ( | ||
<React.Fragment> | ||
<Box marginBottom={1} flexDirection="column"> | ||
<Box> | ||
<Box width={3}>💦</Box> | ||
<Box> | ||
<Text bold>yarn splash</Text>: Observe the splash zone of a change | ||
across the entire library | ||
</Box> | ||
</Box> | ||
</Box> | ||
<Components components={data} status={dataStatus} /> | ||
<Summary | ||
componentsModified={stagedFiles.length} | ||
status={dataStatus} | ||
dependencies={ | ||
new Map([ | ||
...data.map(({pathname, filename}) => [ | ||
pathname, | ||
pathname + filename, | ||
]), | ||
...data.reduce( | ||
(val, curr) => | ||
val.concat( | ||
curr.dependencies.map(({pathname}) => [ | ||
pathname, | ||
curr.pathname + curr.filename, | ||
]), | ||
), | ||
[], | ||
), | ||
]).size | ||
} | ||
/> | ||
<Box marginTop={1}> | ||
<Color dim> | ||
<Box width={3}>💡</Box> | ||
<Box> | ||
Tip: command + click a file path to open it in your text editor | ||
</Box> | ||
</Color> | ||
</Box> | ||
</React.Fragment> | ||
); | ||
}; | ||
|
||
render(<App />); |
Oops, something went wrong.