Skip to content

Commit

Permalink
feat(autocorrect): first blood, should just work (#227)
Browse files Browse the repository at this point in the history
close #224
  • Loading branch information
JounQin committed Sep 6, 2022
1 parent 27d49c2 commit dee35e2
Show file tree
Hide file tree
Showing 23 changed files with 581 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-bobcats-cough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"prettier-plugin-autocorrect": minor
---

feat: first blood, should just work
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"github-markdown-css": "^5.1.0",
"linguist-languages": "^7.21.0",
"lodash": "^4.17.21",
"prettier-plugin-autocorrect": "link:packages/autocorrect",
"prettier-plugin-pkg": "link:packages/pkg",
"prettier-plugin-sh": "link:packages/sh",
"prettier-plugin-sql": "link:packages/sql",
Expand Down
2 changes: 2 additions & 0 deletions packages/autocorrect/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Change Log

21 changes: 21 additions & 0 deletions packages/autocorrect/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 UnTS

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
66 changes: 66 additions & 0 deletions packages/autocorrect/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# prettier-plugin-autocorrect ![npm bundle size](https://img.shields.io/bundlephobia/min/prettier-plugin-autocorrect) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/prettier-plugin-autocorrect)

> An opinionated sql formatter plugin for [Prettier][]
Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing, taking various rules into account.

This plugin adds support for a lot of files through [autocorrect][].

## Notice

This plugin is still under development, its printer just wraps [autocorrect][]'s default printer.
Of course it should just work, but may not match [prettier][]'s format sometimes.

## Requirements

`prettier-plugin-autocorrect` is an evergreen module. 🌲 This module requires an [LTS](https://github.com/nodejs/Release) Node version (v14.0.0+).

## Install

Using npm:

```sh
# npm
npm i -D prettier prettier-plugin-autocorrect

# yarn
yarn add -D prettier prettier-plugin-autocorrect
```

## Usage

Once installed, [Prettier plugins](https://prettier.io/docs/en/plugins.html) should be automatically recognized by Prettier. To use this plugin, confirm that it's installed and run Prettier using your preferred method. For example:

```sh
# npx
npx prettier --write db.sql

# yarn
yarn prettier --write db.sql
```

## Sponsors

| 1stG | RxTS | UnTS |
| ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| [![1stG Open Collective backers and sponsors](https://opencollective.com/1stG/organizations.svg)](https://opencollective.com/1stG) | [![RxTS Open Collective backers and sponsors](https://opencollective.com/rxts/organizations.svg)](https://opencollective.com/rxts) | [![UnTS Open Collective backers and sponsors](https://opencollective.com/unts/organizations.svg)](https://opencollective.com/unts) |

## Backers

| 1stG | RxTS | UnTS |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| [![1stG Open Collective backers and sponsors](https://opencollective.com/1stG/individuals.svg)](https://opencollective.com/1stG) | [![RxTS Open Collective backers and sponsors](https://opencollective.com/rxts/individuals.svg)](https://opencollective.com/rxts) | [![UnTS Open Collective backers and sponsors](https://opencollective.com/unts/individuals.svg)](https://opencollective.com/unts) |

## Changelog

Detailed changes for each release are documented in [CHANGELOG.md](./CHANGELOG.md).

## License

[MIT][] © [JounQin][]@[1stG.me][]

[1stg.me]: https://www.1stg.me
[jounqin]: https://GitHub.com/JounQin
[mit]: http://opensource.org/licenses/MIT
[autocorrect]: https://github.com/huacnlee/autocorrect
[prettier]: https://prettier.io
44 changes: 44 additions & 0 deletions packages/autocorrect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "prettier-plugin-autocorrect",
"version": "0.0.0",
"type": "module",
"description": "An opinionated AutoCorrect plugin for Prettier",
"repository": "git@github.com/un-ts/prettier.git",
"homepage": "https://github.com/un-ts/prettier/tree/master/packages/autocorrect",
"author": "JounQin (https://www.1stG.me) <admin@1stg.me>",
"funding": "https://opencollective.com/unts",
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"main": "./lib/index.cjs",
"module": "./lib/index.js",
"exports": {
"types": "./lib/index.d.ts",
"import": "./lib/index.js",
"require": "./lib/index.cjs"
},
"types": "./lib/index.d.ts",
"files": [
"lib"
],
"keywords": [
"autocorrect",
"copywriting",
"spaces",
"punctuations",
"CJK"
],
"peerDependencies": {
"prettier": "^2.0.0"
},
"dependencies": {
"@huacnlee/autocorrect-node": "^1.10.2",
"cosmiconfig": "^7.0.1",
"synckit": "^0.8.4",
"tslib": "^2.4.0"
},
"publishConfig": {
"access": "public"
}
}
42 changes: 42 additions & 0 deletions packages/autocorrect/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { Plugin } from 'prettier'
import { createSyncFn } from 'synckit'

import { languages } from './languages.js'
import { FormatFor } from './types.js'

const _dirname =
typeof __dirname === 'undefined'
? path.dirname(fileURLToPath(import.meta.url))
: __dirname

const formatFor = createSyncFn<FormatFor>(path.resolve(_dirname, 'worker.js'))

const AutocorrectPlugin: Plugin<string> = {
languages,
parsers: {
autocorrect: {
parse(text) {
return text
},
astFormat: 'autocorrect',
locStart: () => -1,
locEnd: () => -1,
},
},
printers: {
autocorrect: {
print(path, { filepath }) {
const result = formatFor(path.getValue(), filepath)
if (result.error) {
throw new Error(result.error)
}
return result.out
},
},
},
}

export default AutocorrectPlugin
11 changes: 11 additions & 0 deletions packages/autocorrect/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface FormatResult {
out: string
error: string
raw?: string
enable?: boolean
}

export type FormatFor = (
source: string,
filename: string,
) => Promise<FormatResult>
20 changes: 20 additions & 0 deletions packages/autocorrect/src/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { formatFor, loadConfig } from '@huacnlee/autocorrect-node'
import { cosmiconfig } from 'cosmiconfig'
import { runAsWorker } from 'synckit'

import type { FormatResult } from './types.js'

const explorer = cosmiconfig('autocorrect')

runAsWorker(async (source: string, filename: string) => {
const result = await explorer.search(filename)

if (result) {
loadConfig(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
result.config, // type-coverage:ignore-line -- cosmiconfig's typings issue
)
}

return formatFor(source, filename) as Promise<FormatResult>
})
154 changes: 154 additions & 0 deletions packages/autocorrect/test/__snapshots__/fixtures.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Vitest Snapshot v1

exports[`parser and printer > should format all fixtures > test.css 1`] = `
"/*
这是多行 CSS 第 1 行
这是第 2 行
*/
.btn {
.strong { font-weight: bold; }
padding: 10px; // comment 在属性后面
// 这是 comment 单行
font: Helvetica, sans-serif;
}
"
`;

exports[`parser and printer > should format all fixtures > test.go 1`] = `
"// WithContext 创建基于 ctx 的 db
// 第 2 行注释
func (d *Dao) WithContext(ctx context.Context) (db *gorm.DB) {
a := \\"第 1 个\\"
b := \\\\\`
多行 string
第 2 行
\\\\\`
re := regexp.MustCompile(\\\\\`regexp 不处理\\\\\`)
re1 := regexp.Compile(\\"regexp不处理\\")
t := time.Parse(\\"2006年01月02日 15:04\\", t)
fmt.Println(a + b + \\"go 语言\\")
fmt.Println(\\"%s链接的内容不会空格%d也不处理,保守\\", \\"格式\\", 100)
db = d.DB.WithContext(ctx)
return
}
"
`;
exports[`parser and printer > should format all fixtures > test.html 1`] = `
"<h1>编译 rust 为 WebAssembly</h1>
<div></div>
<p class=\\"summary\\">如果你写了一些 RUST 代码,你可以把它编译成 webAssembly!这份教程将带你编译 Rust 项目为 wasm 并在一个现存的 web 应用中使用它。</p></div>
<h2 id=\\"rust_和_webassembly_用例\\"><a href=\\"#rust_和_webassembly_用例\\" title=\\"Permalink to Rust和WebAssembly用例\\">Rust WebAssembly 用例</a></h2>
<div><p>rust webassembly 有两大主要用例:</p>
<ul>
<li>构建完整应用 —— 整个 web 应用都基于 rust 开发!</li>
<li>构建应用的组成部分 —— 在现存的 javascript 前端中使用 RUst。</li>
</ul>
<p>目前,Rust 团队正专注于第二种用例,因此我们也将着重介绍它。对于第一种用例,可以参阅<code><a href=\\"https://github.com/DenisKolodin/yew\\" class=\\"external\\" rel=\\" noopener\\">yew</a></code>这类项目。</p>
<p>在本教程中,我们将使用 Rust npm 包构建工具<code>wasm-pack</code>来构建一个 npm 包。这个包只包含 WebAssembly JavaScript 代码,以便包的用户无需安装 Rust 就能使用。他们甚至不需要知道这里包含 WebAssembly!</p></div>
"
`;
exports[`parser and printer > should format all fixtures > test.js 1`] = `
"/**
* Hello 你好
* 这是第 2 行
*/
function application() {
let example = \\"这是 single line 单行注释\\";
console.log(\\\\\`这是 string 第 1 行
这是 string 第 2 行
\\\\\`)
// autocorrect-disable
const disable_1 = \\"这行将会disable掉\\";
const disable_2 = \\"这行将也会disable掉\\";
// autocorrect-enable
const c = \\"这是 string 第 3 行\\";
}
"
`;
exports[`parser and printer > should format all fixtures > test.md 1`] = `
"# 这是 Heading 1 大标题
**加粗**
*倾斜*
~~删除线~~
这是**Bold 加粗**在 1 个段落中,这端会 correct 掉,如果是 inline code,例如\`Rust 语言\`,也可以应该处理。
> 引用文本:Quote 也是可以的。
\`\`\`rust
// Codeblock 里面也会处理
let a = \\"你好 hello\\";
\`\`\`
- ![img 图片](https://google.com/a/b/url不处理)
- [link 链接](https://google.com/a/b/url不处理)\`,
},
rust: {
title: 'Rust',
raw: \`fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let mut largest = number_list[0];
let regexp = %r\\"包含#regexp 测试\\";
// 1 第一行 Single line 注释
// 2 第二行注释
for number in number_list {
if number > largest {
largest = number;
}
}
// autocorrect: false
let disable_1 = \\"这行将会 disable 掉\\";
let disable_2 = \\"这行将也会 disable 掉\\";
// autocorrect: true
let a = r#\\"
这是第 1 行
这是第 2 行
\\"#;
let b = r##\\"
这是第 3 行
这是第 4 行
\\"##;
/**
* 多行 Rust 注释
* 第二行 Rust 注释
*/
println!(\\"最大的数字 number 是{}\\", largest);
}
"
`;
exports[`parser and printer > should format all fixtures > test.py 1`] = `
"'''
这是多行 1 注释
这是多行 2 注释
这是多行 3 注释
'''
def hello(a):
multi_str = \\"\\"\\"
第 1 行多行字符串
第 2 行多行字符串
\\"\\"\\"
re = r'包含#regexp测试'
re1 = r\\"\\"\\"
包含re0测试
包含re1测试
\\"\\"\\"
re2 = re.compile( \\"hello你\\" + \\"world好\\")
# 第 4 个注释
print(\\"你好 hello 世界\\")
print('你好 hello 世界')
"
`;
exports[`parser and printer > should format all fixtures > test.rb 1`] = `
"# 第 1 行注释
# 第 2 行注释
def hello(a, b: \\"第 1 个参数\\")
re = /hello你好/
re1 = %r{hello你好}
re2 = Regexp.new('hello你好' )
re3 = Regexp.new( \\"hello你好\\")
a = \\"hello 世界#{a}\\"
b = '你好 hello 世界'
end
"
`;

0 comments on commit dee35e2

Please sign in to comment.