Skip to content

Commit

Permalink
feat: watch derived ts files changes (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktsn authored Feb 5, 2018
1 parent 07ea9f6 commit b03c2af
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 30 deletions.
4 changes: 4 additions & 0 deletions src/lib/language-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class LanguageService {
this.files.updateFile(fileName)
}

getHostVueFilePaths (fileName: string): string[] {
return this.files.getHostVueFilePaths(fileName)
}

getDts (fileName: string): Result<string> {
fileName = normalize(fileName)

Expand Down
54 changes: 44 additions & 10 deletions src/lib/ts-file-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { readFileSync, exists } from './file-util'

export interface TsFile {
rawFileName: string
srcPath: string | undefined
version: number
text: string | undefined
}
Expand Down Expand Up @@ -39,6 +40,24 @@ export class TsFileMap {
return file.text
}

/**
* Collect host vue file paths of input ts file.
* If the input is a vue file, just return it.
*/
getHostVueFilePaths (fileName: string): string[] {
if (/\.vue$/.test(fileName)) {
return [fileName]
}

const entries = Array.from(this.files.entries())
return entries
.filter(([key, file]) => {
return !/\.vue$/.test(key)
&& file.srcPath === fileName
})
.map(([_, file]) => file.rawFileName)
}

getVersion (fileName: string): string | undefined {
const file = this.getFile(fileName)
return file && file.version.toString()
Expand All @@ -57,13 +76,16 @@ export class TsFileMap {
const rawFileName = getRawFileName(fileName)
const file = this.getFile(fileName) || {
rawFileName,
srcPath: undefined,
version: 0,
text: undefined
}

let src = readFileSync(rawFileName)
if (src && isVueFile(rawFileName)) {
src = extractCode(src, fileName)
const extracted = extractCode(src, fileName)
src = extracted.content
file.srcPath = extracted.srcPath
}

if (src !== file.text) {
Expand Down Expand Up @@ -103,23 +125,35 @@ export class TsFileMap {
* Extract TS code from single file component
* If there are no TS code, return undefined
*/
function extractCode (src: string, fileName: string): string | undefined {
function extractCode (
src: string,
fileName: string
): {
content: string | undefined,
srcPath: string | undefined
} {
const script = vueCompiler.parseComponent(src, { pad: true }).script
if (script == null) {
return undefined

if (script == null || script.lang !== 'ts') {
return {
content: undefined,
srcPath: undefined
}
}

// Load an external TS file if it referred via src attribute.
if (script.src && isSupportedFile(script.src)) {
const srcFileName = path.resolve(path.dirname(fileName), script.src)
return readFileSync(srcFileName)
const srcPath = path.resolve(path.dirname(fileName), script.src)
return {
content: readFileSync(srcPath),
srcPath
}
}

if (script.lang !== 'ts') {
return undefined
return {
content: script.content,
srcPath: undefined
}

return script.content
}

function isSupportedFile (fileName: string): boolean {
Expand Down
36 changes: 18 additions & 18 deletions src/lib/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@ export function watch (
})

watcher
.on('add', onlyVue(file => {
service.updateFile(file)
saveDts(file, service)
}))
.on('change', onlyVue(file => {
service.updateFile(file)
saveDts(file, service)
}))
.on('unlink', onlyVue(file => {
service.updateFile(file)
removeDts(file)
}))
.on('add', rawFile => {
service.getHostVueFilePaths(rawFile).forEach(file => {
service.updateFile(file)
saveDts(file, service)
})
})
.on('change', rawFile => {
service.getHostVueFilePaths(rawFile).forEach(file => {
service.updateFile(file)
saveDts(file, service)
})
})
.on('unlink', rawFile => {
service.getHostVueFilePaths(rawFile).forEach(file => {
service.updateFile(file)
removeDts(file)
})
})

return watcher
}
Expand Down Expand Up @@ -62,9 +68,3 @@ function removeDts (fileName: string): void {
)
}

function onlyVue (fn: (fileName: string) => void): (fileName: string) => void {
return fileName => {
if (!/\.vue$/.test(fileName)) return
fn(fileName)
}
}
35 changes: 33 additions & 2 deletions test/specs/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,31 @@ describe('watch', () => {

fs.writeFile(p('test.vue'), vue('export declare let b: boolean'), noop)
})

it('watches addition of derived ts file via .vue file', done => {
fs.writeFileSync(p('test.vue'), vue('', { src: 'test-src.ts' }))

watcher.on('add', once(() => {
test(p('test.vue.d.ts'), 'export declare const test: string;')
done()
}))

fs.writeFileSync(p('test-src.ts'), 'export const test: string = ""')
})

it('watches changes of derived ts file via .vue file', done => {
fs.writeFileSync(p('test.vue'), vue('', { src: 'test-src.ts' }))
fs.writeFileSync(p('test-src.ts'), 'export const a: number = 123')

watcher.on('add', once(() => {
fs.writeFile(p('test-src.ts'), 'export const b: string = ""', noop)
}))

watcher.on('change', once(() => {
test(p('test.vue.d.ts'), 'export declare const b: string;')
done()
}))
})
})

function once (fn: () => void): (p: string) => void {
Expand All @@ -91,6 +116,12 @@ function test (file: string, expected: string) {
)
}

function vue (code: string): string {
return '<script lang="ts">' + code + '</script>'
function vue (code: string, attrs: Record<string, string> = {}): string {
const attrsStr = Object.keys(attrs)
.map(key => {
return `${key}="${attrs[key]}"`
})
.join(' ')

return '<script lang="ts" ' + attrsStr + '>' + code + '</script>'
}

0 comments on commit b03c2af

Please sign in to comment.