Skip to content

Commit

Permalink
feat: support pug templates in Vue files (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonhaenisch authored Nov 9, 2022
1 parent a521e09 commit 290a1fd
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
node: [12, 14, 16, 18]
node: [14, 16, 18]

runs-on: ${{ matrix.os }}

Expand Down
46 changes: 34 additions & 12 deletions lib/get-compiler-options.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
const { dirname } = require('path');
const ts = require('typescript');
const { memoize } = require('./memoize');

/**
* Get the compiler options from a tsconfig path. Returns from in-memory cache if they have been read already.
* Get the compiler options from a path to a file in the project. Returns from in-memory cache if they have been read already.
*
* @param {string} path path to a file in the project
*/
module.exports.getCompilerOptions = (tsconfig = '') => {
const cachedCompilerOptions = compilerOptionsCache.get(tsconfig);

if (cachedCompilerOptions) {
return cachedCompilerOptions;
}
function getCompilerOptions(path) {
const tsconfig = findTsconfig(path);

const compilerOptions = tsconfig
? ts.parseJsonConfigFileContent(ts.readConfigFile(tsconfig, ts.sys.readFile).config, ts.sys, dirname(tsconfig))
Expand All @@ -18,12 +17,35 @@ module.exports.getCompilerOptions = (tsconfig = '') => {

compilerOptions.allowJs = true; // for automatic JS support

compilerOptionsCache.set(tsconfig, compilerOptions);

return compilerOptions;
};
}

module.exports.getCompilerOptions = memoize(getCompilerOptions);

/**
* Get the Vue compiler options from a path to a file in the project.
*
* @param {string} path path to a file in the project
*/
function getVueCompilerOptions(path) {
const tsconfig = findTsconfig(path);

return tsconfig
? require('@volar/vue-language-core').createParsedCommandLine(
// @ts-ignore
ts,
ts.sys,
tsconfig,
[],
).vueOptions
: {};
}

module.exports.getVueCompilerOptions = memoize(getVueCompilerOptions);

/**
* @type {Map<string, ts.CompilerOptions>}
* Find the path of the project's tsconfig from a path to a file in the project.
*
* @type {(path: string) => string | undefined}
*/
const compilerOptionsCache = new Map();
const findTsconfig = memoize((path) => ts.findConfigFile(path, ts.sys.fileExists));
23 changes: 23 additions & 0 deletions lib/memoize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Simple memoization utility that only uses the first argument as cache key and has no memory limit.
*
* @template {(...args: any[]) => any} F
* @param {F} f
* @returns {F}
*/
module.exports.memoize = (f) => {
const cache = new Map();

// @ts-ignore
return function (cacheKey, ...rest) {
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}

const result = f(cacheKey, ...rest);

cache.set(cacheKey, result);

return result;
};
};
38 changes: 20 additions & 18 deletions lib/service-host.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const ts = require('typescript');

const { getCompilerOptions } = require('./get-compiler-options');
const { getCompilerOptions, getVueCompilerOptions } = require('./get-compiler-options');

/**
* Create the most basic TS language service host for the given file to make import sorting work.
Expand All @@ -10,10 +10,8 @@ const { getCompilerOptions } = require('./get-compiler-options');
*
* @returns {ts.LanguageServiceHost}
*/
const getTypeScriptLanguageServiceHost = (path, content) => {
const tsconfig = ts.findConfigFile(path, ts.sys.fileExists);

const compilerOptions = getCompilerOptions(tsconfig);
function getTypeScriptLanguageServiceHost(path, content) {
const compilerOptions = getCompilerOptions(path);

return {
directoryExists: ts.sys.directoryExists,
Expand All @@ -33,7 +31,7 @@ const getTypeScriptLanguageServiceHost = (path, content) => {
}
},
};
};
}

/**
* Get a Language Service Host for Vue support, that has some extra methods needed by `@volar/vue-typescript`.
Expand All @@ -45,17 +43,21 @@ const getTypeScriptLanguageServiceHost = (path, content) => {
*
* @returns {VueLanguageServiceHost}
*/
const getVueLanguageServiceHost = (path, content) => ({
...getTypeScriptLanguageServiceHost(path, content),
getVueCompilationSettings: () => ({}),
/**
* Can return either `require('typescript')` or `require('typescript/lib/tsserverlibrary')`.
*
* @see https://github.com/simonhaenisch/prettier-plugin-organize-imports/pull/60#discussion_r934408179
*
* @returns {any}
*/
getTypeScriptModule: () => ts,
});
function getVueLanguageServiceHost(path, content) {
const vueCompilerOptions = getVueCompilerOptions(path);

return {
...getTypeScriptLanguageServiceHost(path, content),
getVueCompilationSettings: () => vueCompilerOptions,
/**
* Can return either `require('typescript')` or `require('typescript/lib/tsserverlibrary')`.
*
* @see https://github.com/simonhaenisch/prettier-plugin-organize-imports/pull/60#discussion_r934408179
*
* @returns {any}
*/
getTypeScriptModule: () => ts,
};
}

module.exports = { getTypeScriptLanguageServiceHost, getVueLanguageServiceHost };
14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,27 @@
"repository": "simonhaenisch/prettier-plugin-organize-imports",
"homepage": "https://github.com/simonhaenisch/prettier-plugin-organize-imports#readme",
"peerDependencies": {
"@volar/vue-typescript": ">=0.40.2",
"@volar/vue-language-plugin-pug": "^1.0.4",
"@volar/vue-typescript": "^1.0.4",
"prettier": ">=2.0",
"typescript": ">=2.9"
},
"peerDependenciesMeta": {
"@volar/vue-language-plugin-pug": {
"optional": true
},
"@volar/vue-typescript": {
"optional": true
}
},
"devDependencies": {
"@types/node": "18.6.4",
"@volar/vue-typescript": "0.40.5",
"@types/node": "18.11.9",
"@types/prettier": "2.7.1",
"@volar/vue-language-plugin-pug": "1.0.9",
"@volar/vue-typescript": "1.0.9",
"ava": "3.15.0",
"prettier": "2.7.1",
"typescript": "4.7.4"
"typescript": "4.8.4"
},
"prettier": {
"printWidth": 120,
Expand Down
4 changes: 3 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Make sure that you have the optional peer dependency `@volar/vue-typescript` ins
npm i --save-dev @volar/vue-typescript
```

If you're using Vue.js with Pug templates, you'll also need to install `@volar/pug-language-service` as a dev dependency.
If you're using Vue.js with Pug templates, you'll also need to install `@volar/vue-language-plugin-pug` as a dev dependency, and configure it in `vueCompilerOptions` (see [usage](https://www.npmjs.com/package/@volar/vue-language-plugin-pug)).

### Debug Logs

Expand All @@ -69,6 +69,8 @@ This plugin acts outside of [Prettier's scope](https://prettier.io/docs/en/ratio

## Changelog

Version `3.2.0` adds and fixes support for pug templates in Vue files (via `@volar/vue-language-plugin-pug`). Please be aware that you'll need to update your version of the `@volar/vue-typescript` peer dependency from `0.x` to `1.x`.

Version `3.1.0` adds an option to skip destructive code actions like removing unused imports.

Version `3.0.3` fixes a performance regression introduced in `3.0.2`.
Expand Down
15 changes: 15 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ import { NDivider } from "naive-ui";
t.is(formattedCode, code);
});

test('works with pug templates in Vue files', (t) => {
const code = `<script setup lang="ts">
import Foo from "@/components";
</script>
<template lang="pug">
Foo
</template>
`;

const formattedCode = prettify(code, { filepath: 'file.vue' });

t.is(formattedCode, code);
});

test('does not remove unused imports with `organizeImportsSkipDestructiveCodeActions` enabled', (t) => {
const code = `import { foo } from "./bar";
`;
Expand Down
3 changes: 2 additions & 1 deletion jsconfig.json → tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"target": "es2015",
"checkJs": true,
"strict": true
}
},
"vueCompilerOptions": { "plugins": ["@volar/vue-language-plugin-pug"] }
}

0 comments on commit 290a1fd

Please sign in to comment.