Skip to content

Instantly share code, notes, and snippets.

@zthxxx
Last active July 27, 2022 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zthxxx/6306cab0615df6c0545bbc4fb07179dc to your computer and use it in GitHub Desktop.
Save zthxxx/6306cab0615df6c0545bbc4fb07179dc to your computer and use it in GitHub Desktop.
梳理代码依赖项
/**
* download command:
* curl -O https://gist.githubusercontent.com/zthxxx/6306cab0615df6c0545bbc4fb07179dc/raw/comb-import.mts
*/
import path from 'path'
import os from 'os'
import { $, argv, fs } from 'zx'
$.env.FORCE_COLOR = '1'
const [, selfPath]: string[] = process.argv
const [dependenciesFile]: string[] = argv._
const step: `${number}` | `${number}-${number}` | undefined = argv.step === undefined
? undefined
: String(argv.step)
const isPrint: boolean = argv.print
if (!dependenciesFile || !step || !await fs.pathExists(dependenciesFile)) {
console.error(`
comb imports, sort / distinct / merge import
usage:
$ ts-node ${path.relative(process.cwd(), selfPath)} <imports file> --step <1 | 2 | 3 | ... | 1-5>
`)
process.exit(1)
}
const run = async () => {
if (!step) return
const steps: `${number}`[] = parseSteps(step)
await handleSteps({
file: dependenciesFile,
steps,
})
}
const parseSteps = (
step: `${number}` | `${number}-${number}`,
): `${number}`[] => {
if (!step) return []
const steps: `${number}`[] = []
if (step.length === 1) {
steps.push(step)
} else if (step.length === 3) {
const [start, end] = step.split('-')
if (start && end) {
for (let i = start; i <= end; i++) {
steps.push(i)
}
}
}
return steps
}
const handleSteps = async ({ file, steps }: {
file: string;
steps: `${number}`[];
}) => {
const tempFile = path.join(os.tmpdir(), file)
await fs.copy(file, tempFile)
let modified: string | null = null
for (let step of steps) {
const modify = stepHandlerMap[step]
modified = await modify(tempFile)
await fs.writeFile(tempFile, modified, { flag: 'w', encoding: 'utf-8' })
}
if (modified === null) return
if (isPrint) {
process.stdout.write(modified)
} else {
await fs.writeFile(file, modified, { flag: 'w', encoding: 'utf-8' })
}
}
const step1 = async (file: string) => {
const content = await fs.readFile(file, { encoding: 'utf-8' })
return content
.replace(/^((?! from ).)*$/gm, '')
.replace(/^ +\d+: /gm, '')
.replace(/\n+/g, '\n')
.replace(/^\n/g, '')
}
const step2 = async (file: string) => {
const content = await fs.readFile(file, { encoding: 'utf-8' })
return uniq(content)
}
/**
* need patch in `node_modules/@babel/parser/lib/index.js`
* change `checkIdentifier` method to `checkIdentifier() { return }`
*/
const step3 = async (file: string) => {
const jsFile = `${file}.js`
await fs.copy(file, jsFile)
/**
* codeshift-duplicate-import.ts -> https://gist.github.com/zthxxx/234d9849309273970282ced5459374ef
*/
await $`npx jscodeshift --extensions=js,ts -t scripts/maintain/codeshift-duplicate-import.ts ${jsFile}`
const result = await fs.readFile(jsFile, { encoding: 'utf-8' })
return result
}
const step4 = async (file: string) => {
const content = await fs.readFile(file, { encoding: 'utf-8' })
return content
.replace(/;/g, '')
.replace(/,\n /g, ', ')
.replace(/\{\n /g, '{ ')
.replace(/,\n\}/g, ' }')
}
const step5 = async (file: string) => {
const content = await fs.readFile(file, { encoding: 'utf-8' })
return sortBy({
content,
separator: ' from ',
sortColumn: 2,
})
}
const stepHandlerMap: Record<
string,
(file: string) => Promise<string | null>
> = {
1: step1,
2: step2,
3: step3,
4: step4,
5: step5,
}
const uniq = (content: string) => {
const set = new Set<string>()
const lines = content.split('\n')
const distinct: string[] = lines.filter(line => {
if (set.has(line)) return false
set.add(line)
return true
})
return distinct.join('\n')
}
const sortBy = ({ content, separator, sortColumn }: {
content: string;
separator: string;
/** start at 1 */
sortColumn: number;
}) => {
const lines: string[][] = content
.split('\n')
.filter(Boolean)
.map(line => line.split(separator))
lines.sort((a, b) => (
a[sortColumn - 1] >= b[sortColumn - 1]
? 1
: -1
))
return lines.map(line => line.join(separator)).join('\n') + '\n'
}
run()
### step 1
# search ` from 'src/(?!pages/vScreen)` and copy to vscreen-external-dependencies.log
# search `^((?! from ).)*$` and replace to ''
# search `^ +\d+: ` and replace to ''
# search `\n+` and replace to '\n'
### step 2
cat vscreen-external-dependencies.log | sort | uniq | pbcopy
cp -f vscreen-external-dependencies.log vscreen-external-dependencies.log.ts
### step 3
# using https://gist.github.com/zthxxx/234d9849309273970282ced5459374ef#file-codeshift-duplicate-import-ts
# patch `node_modules/@babel/parser/lib/index.js` `checkIdentifier` method to `checkIdentifier() { return }`
npx jscodeshift --extensions=js,jsx,ts,tsx --ignore-config=.gitignore -t scripts/maintain/codeshift-duplicate-import.ts vscreen-external-dependencies.log.ts
### step 4
# search `;` to ''
# search `,\n ` to ', '
# search `\{\n ` to '{ '
# search `,\n\}` to ' }'
cp -f vscreen-external-dependencies.log.ts vscreen-external-dependencies.log
### step 5
# search ` from ` and replace to ' : '
# ## search `^import (.*?) : '(.*?)';?$` and replace to '$2 : $1'
cat vscreen-external-dependencies.log | sort -k 2 -t ':' | pbcopy
# search ` : ` and replace to ' from '
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment