2import * as _ from 'lodash-es' 3import { fileURLToPath } from 'url' 6import { execSync } from 'child_process' 18// Find markdown files that reference the given pt-relative paths (for updating links when files move) 19const getMdReferencers = (importeePathA: string[]) => { 20 const rgPattern = importeePathA.map(p => p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') 22 const result = execSync( 23 `rg -l --glob '*.md' '(${rgPattern})' .`, 24 { encoding: 'utf8', cwd: ptDir, maxBuffer: 10 * 1024 * 1024 } 26 return result.trim().split('\n').filter(Boolean).map(p => p.replace(/^\.\//, '')) 28 if (e.status === 1) return [] 33export const getPathBinJsScriptPaths = async () => { 34 const pathBinDir = ptDir + '/' + pathBinDirname 36 return _.filter(allFiles, (filePath) => { 37 const firstLine = fs.readFileSync(filePath, 'utf8').split('\n')[0] 38 return _.includes(jsShebangA, firstLine) 44export const getAllPtCodePaths = async (props?: {importMetaUrl?: string}): Promise<absFileDirPath[]> => { 45 const ctxStore = importMetaUrlCtx.getStore() as {importMetaUrl?: string} | undefined 46 const importMetaUrl = props?.importMetaUrl || ctxStore?.importMetaUrl 50 const excludePath = fileURLToPath(importMetaUrl) 51 allPtFiles = allPtFiles.filter(f => f !== excludePath) 54 const codeExtPaths = _.filter(allPtFiles, isPtCodeFileExt) as absFileDirPath[] 55 const pathBinJsPaths = await getPathBinJsScriptPaths() 56 return [...codeExtPaths, ...pathBinJsPaths] 59const getSubmodulePrefixes = (): string[] => { 60 if (!fs.existsSync(`${ptDir}/.gitmodules`)) return [] 62 const out = execSync(`git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$'`, {cwd: ptDir, encoding: 'utf8'}) 63 return out.trim().split('\n').filter(Boolean).map(line => line.split(' ')[1] + '/') 67export const getMdPathsReferencingWord = (word: string): absFileDirPath[] => { 69 const result = execSync(`rg -l --glob '*.md' -w ${JSON.stringify(word)} .`, {encoding: 'utf8', cwd: ptDir, maxBuffer: 10 * 1024 * 1024}) 70 const relA = result.trim().split('\n').filter(Boolean).map(p => p.replace(/^\.\//, '')) 71 const excludePrefixes = [`${tmpDirName}/`, ...getSubmodulePrefixes()] 73 } catch (e: any) { if (e.status === 1) return []; throw e } 76const getImporterCandidatesRg = (importeePathA: string[]) => { 77 const patterns = _.chain(importeePathA).flatMap((importeePath) => { 78 const basename = path.basename(importeePath) 79 const basenameNoExt = basename.replace(/\.[^.]+$/, '') 80 return [basename, basenameNoExt] 83 const rgPattern = patterns.join('|') 85 const runRg = (globArg: string) => { 87 const result = execSync( 88 `rg -l --hidden '(${rgPattern})' ${globArg} .`, 89 { encoding: 'utf8', cwd: ptDir, maxBuffer: 10 * 1024 * 1024 } 91 return result.trim().split('\n').filter(Boolean).map(p => p.replace(/^\.\//, '')) 93 if (e.status === 1) return [] 98 const extMatches = runRg(`--glob '*.{${ptFileExtA.join(',')}}'`) 103export const getPathsThatImport = async ({importeePath, importeePathA: importeePathA_}: {importeePath?: string, importeePathA?: string[]}) => { 104 const importeePathA = importeePathA_ || [importeePath!] 106 const candidatePaths = getImporterCandidatesRg(importeePathA) 107 const depH: Record<string, string[]> = await ptMadge(candidatePaths) 109 const unregMadgeLeafExts = _.chain(depH).map((importedPathA) => importedPathA).flatten().map((p) => { 110 return '.' + _.chain(p).split('.').last().value() 113 const importedByPathsA = _.chain(depH).map((importedPathA, importerPath) => { 114 if (_.intersection(importedPathA, importeePathA).length == 0) return null 120 const mdReferencersA = getMdReferencers(importeePathA) 122 return {importedByPathsA: _.uniq([...importedByPathsA, ...shellInvokersA, ...anchorIncludersA, ...mdReferencersA]), depH, unregMadgeLeafExts}