Skip to content

Commit

Permalink
Merge pull request #23 from NewFuture/master
Browse files Browse the repository at this point in the history
add prettier and prettyhtml for wxml formatter
  • Loading branch information
qiu8310 authored Mar 17, 2019
2 parents 659d75d + a3e45f3 commit 813f693
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 31 deletions.
57 changes: 52 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "1.12.1",
"publisher": "qiu8310",
"scripts": {
"lint": "tslint src/**/*.ts",
"lint": "tslint src/**/*.ts --fix",
"clear": "remove-all dist",
"vscode:prepublish": "npm run build",
"build": "npm run clear && npm run lint && tsc -p ./",
Expand Down Expand Up @@ -178,6 +178,50 @@
"scss"
],
"description": "当前样式文件的后缀中,系统会自动查找和当前模板同名的样式文件,用于模板中的 class 补全"
},
"minapp-vscode.wxmlFormatter": {
"type": "string",
"default": "wxml",
"enum": [
"wxml",
"prettier",
"prettyHtml"
],
"description": "wxml 格式化工具"
},
"minapp-vscode.prettyHtml": {
"type": "object",
"default": {
"useTabs": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": false,
"usePrettier": true,
"wrapAttributes": false,
"sortAttributes": false
},
"description": "prettyHtml 配置"
},
"minapp-vscode.prettier": {
"type": "object",
"default": {
"useTabs": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": false
},
"description": "prettier 配置"
},
"minapp-vscode.documentSelector": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"default": [
"wxml"
],
"description": "The associated document types"
}
}
},
Expand Down Expand Up @@ -223,14 +267,17 @@
"dependencies": {
"@minapp/common": "^2.2.3",
"@minapp/wxml-parser": "^2.1.4",
"@starptech/prettyhtml": "^0.8.16",
"prettier": "^1.16.4",
"tslib": "^1.9.0"
},
"devDependencies": {
"@types/mocha": "^2.2.42",
"@types/node": "^8.10.22",
"mora-scripts": "1.6.35",
"tslint": "^5.11.0",
"typescript": "^3.1.6",
"@types/prettier": "^1.16.1",
"mora-scripts": "^1.6.35",
"tslint": "^5.14.0",
"typescript": "^3.3.3333",
"vscode": "^1.1.21"
}
}
}
60 changes: 37 additions & 23 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ MIT License http://www.opensource.org/licenses/mit-license.php
Author Mora <qiuzhongleiabc@126.com> (https://github.com/qiu8310)
*******************************************************************/

import {ExtensionContext, languages, workspace} from 'vscode'
import { ExtensionContext, languages, workspace } from 'vscode'

import LinkProvider from './plugin/LinkProvider'
import HoverProvider from './plugin/HoverProvider'
import WxmlFormatter from './plugin/WxmlFormatter'
import PrettyHtmlEditProvider from './plugin/PrettyhtmlEditProvider'
import PrettierProvider from './plugin/PrettierProvider'

import WxmlAutoCompletion from './plugin/WxmlAutoCompletion'
import PugAutoCompletion from './plugin/PugAutoCompletion'
Expand All @@ -16,9 +18,10 @@ import WxmlDocumentHighlight from './plugin/WxmlDocumentHighlight'

import ActiveTextEditorListener from './plugin/ActiveTextEditorListener'

import {config, configActivate, configDeactivate} from './plugin/lib/config'
import { config, configActivate, configDeactivate } from './plugin/lib/config'
import { PropDefinitionProvider } from './plugin/PropDefinitionProvider'


export function activate(context: ExtensionContext) {
// console.log('minapp-vscode is active!')
configActivate()
Expand All @@ -27,16 +30,27 @@ export function activate(context: ExtensionContext) {
autoConfig()
}

let formatter = new WxmlFormatter(config)
let autoCompletionWxml = new WxmlAutoCompletion(config)
let hoverProvider = new HoverProvider(config)
let linkProvider = new LinkProvider(config)
let autoCompletionPug = new PugAutoCompletion(config)
let autoCompletionVue = new VueAutoCompletion(autoCompletionPug, autoCompletionWxml)
let documentHighlight = new WxmlDocumentHighlight(config)
let propDefinitionProvider = new PropDefinitionProvider(config)

const wxml = schemes('wxml')
let formatter
switch (config.wxmlFormatter) {
case 'prettier':
formatter = new PrettierProvider(config.prettier)
break
case 'prettyHtml':
formatter = new PrettyHtmlEditProvider(config.prettyHtml)
break
default:
formatter = new WxmlFormatter(config)
break
}
const autoCompletionWxml = new WxmlAutoCompletion(config)
const hoverProvider = new HoverProvider(config)
const linkProvider = new LinkProvider(config)
const autoCompletionPug = new PugAutoCompletion(config)
const autoCompletionVue = new VueAutoCompletion(autoCompletionPug, autoCompletionWxml)
const documentHighlight = new WxmlDocumentHighlight(config)
const propDefinitionProvider = new PropDefinitionProvider(config)

const wxmls = config.documentSelector.map(l => schemes(l))
const pug = schemes('wxml-pug')
const vue = schemes('vue')

Expand All @@ -45,24 +59,24 @@ export function activate(context: ExtensionContext) {
new ActiveTextEditorListener(config),

// hover 效果
languages.registerHoverProvider([wxml, pug, vue], hoverProvider),
languages.registerHoverProvider([pug, vue].concat(wxmls), hoverProvider),

// 添加 link
languages.registerDocumentLinkProvider([wxml, pug], linkProvider),
languages.registerDocumentLinkProvider([pug].concat(wxmls), linkProvider),

// 高亮匹配的标签
languages.registerDocumentHighlightProvider(wxml, documentHighlight),
languages.registerDocumentHighlightProvider(wxmls, documentHighlight),

// 格式化
languages.registerDocumentFormattingEditProvider(wxml, formatter),
languages.registerDocumentRangeFormattingEditProvider(wxml, formatter),
languages.registerDocumentFormattingEditProvider(wxmls, formatter),
languages.registerDocumentRangeFormattingEditProvider(wxmls, formatter),


// DefinitionProvider
languages.registerDefinitionProvider([wxml, pug], propDefinitionProvider),
languages.registerDefinitionProvider([pug].concat(wxmls), propDefinitionProvider),

// 自动补全
languages.registerCompletionItemProvider(wxml, autoCompletionWxml, '<', ' ', ':', '@', '.', '-', '"', '\''),
languages.registerCompletionItemProvider(wxmls, autoCompletionWxml, '<', ' ', ':', '@', '.', '-', '"', '\''),
languages.registerCompletionItemProvider(pug, autoCompletionPug, '\n', ' ', '(', ':', '@', '.', '-', '"', '\''),
// trigger 需要是上两者的和
languages.registerCompletionItemProvider(vue, autoCompletionVue, '<', ' ', ':', '@', '.', '-', '(', '"', '\'')
Expand All @@ -75,7 +89,7 @@ export function deactivate() {

function autoConfig() {
let c = workspace.getConfiguration()
const updates: Array<{key: string, map: any}> = [
const updates: Array<{ key: string, map: any }> = [
{
key: 'files.associations',
map: {
Expand All @@ -92,20 +106,20 @@ function autoConfig() {
}
]

updates.forEach(({key, map}) => {
updates.forEach(({ key, map }) => {
let oldMap = c.get(key, {}) as any
let appendMap: any = {}
Object.keys(map).forEach(k => {
if (!(oldMap.hasOwnProperty(k))) appendMap[k] = map[k]
})
if (Object.keys(appendMap).length) {
c.update(key, {...oldMap, ...appendMap}, true)
c.update(key, { ...oldMap, ...appendMap }, true)
}
})

c.update('minapp-vscode.disableAutoConfig', true, true)
}

export function schemes(key: string) {
return {scheme: 'file', language: key}
return { scheme: 'file', language: key }
}
59 changes: 59 additions & 0 deletions src/plugin/PrettierProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

import { TextEdit, Range, TextDocument, DocumentRangeFormattingEditProvider, DocumentFormattingEditProvider, FormattingOptions, CancellationToken, window } from 'vscode'
import { Options, resolveConfig } from 'prettier'

function prettierify(
code: string,
options: Options,
): string {
const prettier = require('prettier')
const prettierifiedCode = prettier.format(code, options)
return prettierifiedCode
}

function fullDocumentRange(document: TextDocument): Range {
const lastLineId = document.lineCount - 1
return new Range(0, 0, lastLineId, document.lineAt(lastLineId).text.length)
}

class PrettierProvider
implements
DocumentRangeFormattingEditProvider,
DocumentFormattingEditProvider {
readonly options: { [index: string]: any }
constructor(options: { [index: string]: any }) {
this.options = options
}

provideDocumentRangeFormattingEdits(
document: TextDocument,
range: Range,
options: FormattingOptions,
token: CancellationToken
): Promise<TextEdit[]> {
return this._provideEdits(document)
}

provideDocumentFormattingEdits(
document: TextDocument,
options: FormattingOptions,
token: CancellationToken
): Promise<TextEdit[]> {
return this._provideEdits(document)
}

async _provideEdits(document: TextDocument): Promise<TextEdit[]> {
try {
const prettierOptions = await resolveConfig(document.uri.fsPath, { editorconfig: true })
const prettierifiedCode = prettierify(document.getText(), Object.assign({}, this.options, prettierOptions))
return [TextEdit.replace(fullDocumentRange(document), prettierifiedCode)]
} catch (error) {
console.log('Prettier format failed')
console.error(error.message)
window.showErrorMessage(error.message)
return []
}
}
}

export default PrettierProvider
100 changes: 100 additions & 0 deletions src/plugin/PrettyhtmlEditProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* modified from https://github.com/StarpTech/prettyhtml-vscode/blob/master/src/prettyhtmlEditProvider.ts
*/
import {
DocumentRangeFormattingEditProvider,
DocumentFormattingEditProvider,
Range,
TextDocument,
FormattingOptions,
CancellationToken,
TextEdit,
window
} from 'vscode'
import { resolveConfig } from 'prettier'

async function format(
text: string,
{ uri }: TextDocument,
options: { [index: string]: any },
prettyhtmlOptions: { [index: string]: any }
): Promise<string> {
const prettyhtml = require('@starptech/prettyhtml')

const op = {
useTabs: prettyhtmlOptions.useTabs,
tabWidth: prettyhtmlOptions.tabWidth,
printWidth: prettyhtmlOptions.printWidth,
singleQuote: prettyhtmlOptions.singleQuote,
usePrettier: prettyhtmlOptions.usePrettier,
// prettier: prettierOptions,
wrapAttributes: prettyhtmlOptions.wrapAttributes,
sortAttributes: prettyhtmlOptions.sortAttributes
}

if (prettyhtmlOptions.usePrettier) {
const prettierOptions = await resolveConfig(uri.fsPath, { editorconfig: true })
Object.assign(op, prettierOptions, { prettier: prettierOptions })
}

return await prettyhtml(text, op).contents
}

function fullDocumentRange(document: TextDocument): Range {
const lastLineId = document.lineCount - 1
return new Range(0, 0, lastLineId, document.lineAt(lastLineId).text.length)
}

class PrettyhtmlEditProvider
implements
DocumentRangeFormattingEditProvider,
DocumentFormattingEditProvider {
readonly prettyhtmlOptions: { [index: string]: any }
constructor(options: { [index: string]: any }) {
this.prettyhtmlOptions = options
}

provideDocumentRangeFormattingEdits(
document: TextDocument,
range: Range,
options: FormattingOptions,
token: CancellationToken
): Promise<TextEdit[]> {
return this._provideEdits(document, {
rangeStart: document.offsetAt(range.start),
rangeEnd: document.offsetAt(range.end)
})
}

provideDocumentFormattingEdits(
document: TextDocument,
options: FormattingOptions,
token: CancellationToken
): Promise<TextEdit[]> {
return this._provideEdits(document, options)
}

private async _provideEdits(document: TextDocument, options: Object) {
if (this.prettyhtmlOptions.enable === false) {
console.info(
'Prettyhtml is not enabled. Set \'prettyhtml.enable\' to true'
)
return []
}
try {
const code = await format(
document.getText(),
document,
options,
this.prettyhtmlOptions
)
return [TextEdit.replace(fullDocumentRange(document), code)]
} catch (error) {
console.error('prettyhtml error \n', error.message)
window.showErrorMessage(error.message)
return []
}
}
}

export default PrettyhtmlEditProvider
Loading

0 comments on commit 813f693

Please sign in to comment.