-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1207 from bryceosterhaus/prettierPlugin
feat(prettier-plugin): create new @liferay/prettier-plugin package
- Loading branch information
Showing
9 changed files
with
322 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Based on: https://github.com/actions/starter-workflows/blob/master/ci/node.js.yml | ||
|
||
name: prettier-plugin | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
paths: | ||
- 'projects/prettier-plugin/**' | ||
pull_request: | ||
branches: [master] | ||
paths: | ||
- 'projects/prettier-plugin/**' | ||
|
||
env: | ||
CI: true | ||
yarn-cache-name: yarn-cache-3 | ||
yarn-cache-path: .yarn | ||
|
||
jobs: | ||
check-lockfile: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [20.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Use or update Yarn cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: ${{ env.yarn-cache-path }} | ||
key: ${{ runner.os }}-${{ env.yarn-cache-name }}-${{ hashFiles('**/yarn.lock') }} | ||
- run: yarn --cache-folder=${{ env.yarn-cache-path }} | ||
working-directory: projects/prettier-plugin | ||
- run: git diff --quiet -- yarn.lock | ||
working-directory: projects/prettier-plugin | ||
|
||
test: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [20.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Use or update Yarn cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: ${{ env.yarn-cache-path }} | ||
key: ${{ runner.os }}-${{ env.yarn-cache-name }}-${{ hashFiles('**/yarn.lock') }}-prettier-plugin | ||
- run: yarn --cache-folder=../../../${{ env.yarn-cache-path }} --frozen-lockfile | ||
working-directory: projects/prettier-plugin | ||
- run: yarn --cache-folder=../../../${{ env.yarn-cache-path }} build | ||
working-directory: projects/prettier-plugin | ||
- run: yarn --cache-folder=../../../${{ env.yarn-cache-path }} test | ||
working-directory: projects/prettier-plugin |
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,7 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
export {parsers} from './parsers.js'; | ||
export {printers} from './printers.js'; |
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,17 @@ | ||
{ | ||
"dependencies": { | ||
"prettier": "3.2.5" | ||
}, | ||
"exports": "./index.js", | ||
"name": "@liferay/prettier-plugin", | ||
"scripts": { | ||
"build": "true", | ||
"format": "liferay-workspace-scripts format", | ||
"format:check": "liferay-workspace-scripts format:check", | ||
"postversion": "liferay-workspace-scripts publish", | ||
"preversion": "liferay-workspace-scripts ci", | ||
"test": "node test" | ||
}, | ||
"type": "module", | ||
"version": "1.0.0" | ||
} |
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,45 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
import {format} from 'prettier'; | ||
import {parsers as babelParsers} from 'prettier/plugins/babel'; | ||
import {parsers as typescriptParsers} from 'prettier/plugins/typescript'; | ||
|
||
import {linesAroundComments} from './rules/lines-around-comments.js'; | ||
|
||
function transformParser(parserName, defaultParser) { | ||
return { | ||
...defaultParser, | ||
astFormat: 'liferay-style-ast', | ||
parse: async (text, options) => { | ||
|
||
/* | ||
* We need to filter out our own plugin before calling default prettier | ||
*/ | ||
const plugins = options.plugins.filter( | ||
(plugin) => !plugin.printers['liferay-style-ast'] | ||
); | ||
|
||
let formattedText = await format(text, { | ||
...options, | ||
plugins, | ||
}); | ||
|
||
const ast = defaultParser.parse(formattedText, options); | ||
|
||
formattedText = linesAroundComments(formattedText, ast, parserName); | ||
|
||
return { | ||
body: formattedText, | ||
type: 'FormattedText', | ||
}; | ||
}, | ||
}; | ||
} | ||
|
||
export const parsers = { | ||
babel: transformParser('babel', babelParsers.babel), | ||
typescript: transformParser('typescript', typescriptParsers.typescript), | ||
}; |
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,24 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
function createPrinter() { | ||
function main(path) { | ||
const {node} = path; | ||
|
||
if (node.type === 'FormattedText') { | ||
return node.body; | ||
} | ||
|
||
throw new Error(`Unknown node type: ${node?.type}`); | ||
} | ||
|
||
return { | ||
print: main, | ||
}; | ||
} | ||
|
||
export const printers = { | ||
'liferay-style-ast': createPrinter(), | ||
}; |
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,68 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
export function linesAroundComments(formattedText, ast, parserName) { | ||
let contentLengthIncrease = 0; | ||
|
||
ast.comments.forEach((commentNode) => { | ||
if (isEndofLineComment(commentNode)) { | ||
return; | ||
} | ||
|
||
const nodeStart = | ||
parserName === 'typescript' | ||
? commentNode.range[0] | ||
: commentNode.start; | ||
const nodeEnd = | ||
parserName === 'typescript' | ||
? commentNode.range[1] | ||
: commentNode.end; | ||
|
||
const commentStartIndex = nodeStart + contentLengthIncrease; | ||
|
||
if (!isNewLineBefore(formattedText, commentStartIndex)) { | ||
const position = commentStartIndex - 1; | ||
|
||
formattedText = insertNewLine(formattedText, position); | ||
|
||
contentLengthIncrease += 1; | ||
} | ||
|
||
const commentEndIndex = nodeEnd + contentLengthIncrease; | ||
|
||
if ( | ||
!isBlockComment(commentNode) && | ||
!isNewLineAfter(formattedText, commentEndIndex) | ||
) { | ||
const position = commentEndIndex + 1; | ||
|
||
formattedText = insertNewLine(formattedText, position); | ||
|
||
contentLengthIncrease += 1; | ||
} | ||
}); | ||
|
||
return formattedText; | ||
} | ||
|
||
function isBlockComment(node) { | ||
return node.type === 'CommentBlock' || node.type === 'Block'; | ||
} | ||
|
||
function isEndofLineComment(node) { | ||
return node.loc.start.column !== 0; | ||
} | ||
|
||
function isNewLineBefore(text, index) { | ||
return text.charAt(index - 2) === '\n'; | ||
} | ||
|
||
function isNewLineAfter(text, index) { | ||
return text.charAt(index + 2) === '\n'; | ||
} | ||
|
||
function insertNewLine(text, index) { | ||
return [text.slice(0, index), '\n', text.slice(index)].join(''); | ||
} |
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,92 @@ | ||
/** | ||
* SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
import assert from 'node:assert'; | ||
import {describe, test} from 'node:test'; | ||
import {format} from 'prettier'; | ||
|
||
import * as liferayPrettierPlugin from '../index.js'; | ||
|
||
const baseConfig = { | ||
bracketSpacing: false, | ||
plugins: [liferayPrettierPlugin], | ||
singleQuote: true, | ||
tabWidth: 4, | ||
useTabs: true, | ||
}; | ||
|
||
const babelConfig = { | ||
...baseConfig, | ||
parser: 'babel', | ||
}; | ||
|
||
const tsConfig = { | ||
...baseConfig, | ||
parser: 'typescript', | ||
}; | ||
|
||
const fixtures = [ | ||
{ | ||
_name: 'inline comment', | ||
code: `const foo = 'foo'; | ||
// test | ||
const bar = 'bar';`, | ||
expected: `const foo = 'foo'; | ||
// test | ||
const bar = 'bar'; | ||
`, | ||
}, | ||
{ | ||
_name: 'block comment', | ||
code: `const foo = 'foo'; | ||
/* | ||
* blah | ||
*/ | ||
const bar = 'bar';`, | ||
expected: `const foo = 'foo'; | ||
/* | ||
* blah | ||
*/ | ||
const bar = 'bar'; | ||
`, | ||
}, | ||
]; | ||
|
||
describe('babel', () => { | ||
test('prettier runs', async () => { | ||
const code = `if (foo) {}`; | ||
|
||
assert.ok(await format(code, babelConfig)); | ||
}); | ||
|
||
fixtures.forEach((fixture) => { | ||
test(fixture._name, async () => { | ||
assert.equal( | ||
await format(fixture.code, babelConfig), | ||
fixture.expected | ||
); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('typescript', () => { | ||
test('prettier runs', async () => { | ||
const code = `if (foo) {}`; | ||
|
||
assert.ok(await format(code, tsConfig)); | ||
}); | ||
|
||
fixtures.forEach((fixture) => { | ||
test(fixture._name, async () => { | ||
assert.equal( | ||
await format(fixture.code, tsConfig), | ||
fixture.expected | ||
); | ||
}); | ||
}); | ||
}); |