commit
ce3123b03b
441
src/extension.ts
441
src/extension.ts
|
@ -1,7 +1,8 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import * as vscode from 'vscode'
|
import * as vscode from 'vscode'
|
||||||
import { join, dirname } from 'path'
|
import { dirname } from 'path'
|
||||||
|
const htmlElements = require('./htmlElements.js')
|
||||||
const tailwindClassNames = require('tailwind-class-names')
|
const tailwindClassNames = require('tailwind-class-names')
|
||||||
const dlv = require('dlv')
|
const dlv = require('dlv')
|
||||||
const Color = require('color')
|
const Color = require('color')
|
||||||
|
@ -15,16 +16,13 @@ const HTML_TYPES = [
|
||||||
'razor',
|
'razor',
|
||||||
'php',
|
'php',
|
||||||
'blade',
|
'blade',
|
||||||
'vue',
|
|
||||||
'twig',
|
'twig',
|
||||||
'markdown',
|
'markdown',
|
||||||
'erb',
|
'erb',
|
||||||
'handlebars',
|
'handlebars',
|
||||||
'ejs',
|
'ejs',
|
||||||
'nunjucks',
|
'nunjucks',
|
||||||
'haml',
|
'haml'
|
||||||
// for jsx
|
|
||||||
...JS_TYPES
|
|
||||||
]
|
]
|
||||||
const CSS_TYPES = ['css', 'sass', 'scss', 'less', 'postcss', 'stylus']
|
const CSS_TYPES = ['css', 'sass', 'scss', 'less', 'postcss', 'stylus']
|
||||||
|
|
||||||
|
@ -97,14 +95,25 @@ async function getTailwind() {
|
||||||
|
|
||||||
export function deactivate() {}
|
export function deactivate() {}
|
||||||
|
|
||||||
function createCompletionItemProvider(
|
function createCompletionItemProvider({
|
||||||
items,
|
items,
|
||||||
languages: string[],
|
languages,
|
||||||
regex: RegExp,
|
regex,
|
||||||
triggerCharacters: string[],
|
triggerCharacters,
|
||||||
config,
|
config,
|
||||||
prefix = ''
|
prefix = '',
|
||||||
): vscode.Disposable {
|
enable = () => true,
|
||||||
|
emmet = false
|
||||||
|
}: {
|
||||||
|
items?
|
||||||
|
languages?: string[]
|
||||||
|
regex?: RegExp
|
||||||
|
triggerCharacters?: string[]
|
||||||
|
config?
|
||||||
|
prefix?: string
|
||||||
|
enable?: (text: string) => boolean
|
||||||
|
emmet?: boolean
|
||||||
|
} = {}): vscode.Disposable {
|
||||||
return vscode.languages.registerCompletionItemProvider(
|
return vscode.languages.registerCompletionItemProvider(
|
||||||
languages,
|
languages,
|
||||||
{
|
{
|
||||||
|
@ -116,21 +125,38 @@ function createCompletionItemProvider(
|
||||||
let str
|
let str
|
||||||
|
|
||||||
const range: vscode.Range = new vscode.Range(
|
const range: vscode.Range = new vscode.Range(
|
||||||
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
new vscode.Position(0, 0),
|
||||||
position
|
position
|
||||||
)
|
)
|
||||||
const text: string = document.getText(range)
|
const text: string = document.getText(range)
|
||||||
|
|
||||||
let matches = text.match(regex)
|
if (!enable(text)) return []
|
||||||
|
|
||||||
|
let lines = text.split(/[\n\r]/)
|
||||||
|
|
||||||
|
let matches = lines
|
||||||
|
.slice(-5)
|
||||||
|
.join('\n')
|
||||||
|
.match(regex)
|
||||||
|
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let parts = matches[matches.length - 1].split(' ')
|
let parts = matches[matches.length - 1].split(' ')
|
||||||
str = parts[parts.length - 1]
|
str = parts[parts.length - 1]
|
||||||
} else if (languages.indexOf('html') !== -1) {
|
} else if (emmet) {
|
||||||
// match emmet style syntax
|
// match emmet style syntax
|
||||||
// e.g. .flex.items-center
|
// e.g. .flex.items-center
|
||||||
let lineText = text.split('\n').pop()
|
let currentLine = lines[lines.length - 1]
|
||||||
matches = lineText.match(/\.([^()#>*^ \[\]=$@{}]*)$/i)
|
let currentWord = currentLine.split(' ').pop()
|
||||||
|
matches = currentWord.match(/^\.([^.()#>*^ \[\]=$@{}]*)$/)
|
||||||
|
if (!matches) {
|
||||||
|
matches = currentWord.match(
|
||||||
|
new RegExp(
|
||||||
|
`^([A-Z][a-zA-Z0-9]*|[a-z][a-z0-9]*-[a-z0-9-]+|${htmlElements.join(
|
||||||
|
'|'
|
||||||
|
)}).*?\\.([^.()#>*^ \\[\\]=$@{}]*)$`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
let parts = matches[matches.length - 1].split('.')
|
let parts = matches[matches.length - 1].split('.')
|
||||||
str = parts[parts.length - 1]
|
str = parts[parts.length - 1]
|
||||||
}
|
}
|
||||||
|
@ -163,6 +189,59 @@ function createCompletionItemProvider(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createConfigItemProvider({
|
||||||
|
languages,
|
||||||
|
items,
|
||||||
|
enable = () => true
|
||||||
|
}: {
|
||||||
|
languages?: string[]
|
||||||
|
items?: vscode.CompletionItem[]
|
||||||
|
enable?: (text: string) => boolean
|
||||||
|
} = {}) {
|
||||||
|
return vscode.languages.registerCompletionItemProvider(
|
||||||
|
languages,
|
||||||
|
{
|
||||||
|
provideCompletionItems: (
|
||||||
|
document: vscode.TextDocument,
|
||||||
|
position: vscode.Position
|
||||||
|
): vscode.CompletionItem[] => {
|
||||||
|
const range: vscode.Range = new vscode.Range(
|
||||||
|
new vscode.Position(0, 0),
|
||||||
|
position
|
||||||
|
)
|
||||||
|
const text: string = document.getText(range)
|
||||||
|
|
||||||
|
if (!enable(text)) return []
|
||||||
|
|
||||||
|
let lines = text.split(/[\n\r]/)
|
||||||
|
|
||||||
|
let matches = lines
|
||||||
|
.slice(-5)
|
||||||
|
.join('\n')
|
||||||
|
.match(/config\(["']([^"']*)$/)
|
||||||
|
|
||||||
|
if (!matches) return []
|
||||||
|
|
||||||
|
let objPath =
|
||||||
|
matches[1]
|
||||||
|
.replace(/\.[^.]*$/, '')
|
||||||
|
.replace('.', '.children.')
|
||||||
|
.trim() + '.children'
|
||||||
|
let foo = dlv(items, objPath)
|
||||||
|
|
||||||
|
if (foo) {
|
||||||
|
return Object.keys(foo).map(x => foo[x].item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(items).map(x => items[x].item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"'",
|
||||||
|
'"',
|
||||||
|
'.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function prefixItems(items, str, prefix) {
|
function prefixItems(items, str, prefix) {
|
||||||
const addPrefix =
|
const addPrefix =
|
||||||
typeof prefix !== 'undefined' && prefix !== '' && str === prefix
|
typeof prefix !== 'undefined' && prefix !== '' && str === prefix
|
||||||
|
@ -257,7 +336,7 @@ function createItems(classNames, separator, config, parent = '') {
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
function createConfigItems(config) {
|
function createConfigItems(config, prefix = '') {
|
||||||
let items = {}
|
let items = {}
|
||||||
let i = 0
|
let i = 0
|
||||||
|
|
||||||
|
@ -270,7 +349,7 @@ function createConfigItems(config) {
|
||||||
if (depthOf(config[key]) === 0) {
|
if (depthOf(config[key]) === 0) {
|
||||||
if (key === 'plugins') return
|
if (key === 'plugins') return
|
||||||
|
|
||||||
item.filterText = item.insertText = `.${key}`
|
item.filterText = item.insertText = `${prefix}${key}`
|
||||||
item.sortText = naturalExpand(i.toString())
|
item.sortText = naturalExpand(i.toString())
|
||||||
if (typeof config[key] === 'string' || typeof config[key] === 'number') {
|
if (typeof config[key] === 'string' || typeof config[key] === 'number') {
|
||||||
item.detail = config[key]
|
item.detail = config[key]
|
||||||
|
@ -290,7 +369,7 @@ function createConfigItems(config) {
|
||||||
item.filterText = item.insertText = `${key}.`
|
item.filterText = item.insertText = `${key}.`
|
||||||
item.sortText = naturalExpand(i.toString())
|
item.sortText = naturalExpand(i.toString())
|
||||||
item.command = { title: '', command: 'editor.action.triggerSuggest' }
|
item.command = { title: '', command: 'editor.action.triggerSuggest' }
|
||||||
items[key] = { item, children: createConfigItems(config[key]) }
|
items[key] = { item, children: createConfigItems(config[key], prefix) }
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
i++
|
||||||
|
@ -305,6 +384,7 @@ class TailwindIntellisense {
|
||||||
private _tailwind
|
private _tailwind
|
||||||
private _items
|
private _items
|
||||||
private _configItems
|
private _configItems
|
||||||
|
private _prefixedConfigItems
|
||||||
|
|
||||||
constructor(tailwind) {
|
constructor(tailwind) {
|
||||||
if (tailwind) {
|
if (tailwind) {
|
||||||
|
@ -322,162 +402,235 @@ class TailwindIntellisense {
|
||||||
|
|
||||||
this._items = createItems(tailwind.classNames, separator, tailwind.config)
|
this._items = createItems(tailwind.classNames, separator, tailwind.config)
|
||||||
this._configItems = createConfigItems(tailwind.config)
|
this._configItems = createConfigItems(tailwind.config)
|
||||||
|
this._prefixedConfigItems = createConfigItems(tailwind.config, '.')
|
||||||
|
|
||||||
this._providers = []
|
this._providers = []
|
||||||
|
|
||||||
this._providers.push(
|
this._providers.push(
|
||||||
createCompletionItemProvider(
|
createCompletionItemProvider({
|
||||||
this._items,
|
items: this._items,
|
||||||
JS_TYPES,
|
languages: JS_TYPES,
|
||||||
/\btw`([^`]*)$/,
|
regex: /\btw`([^`]*)$/,
|
||||||
['`', ' ', separator],
|
triggerCharacters: ['`', ' ', separator],
|
||||||
tailwind.config
|
config: tailwind.config
|
||||||
)
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
this._providers.push(
|
this._providers.push(
|
||||||
createCompletionItemProvider(
|
createCompletionItemProvider({
|
||||||
this._items,
|
items: this._items,
|
||||||
CSS_TYPES,
|
languages: CSS_TYPES,
|
||||||
/@apply ([^;}]*)$/,
|
regex: /@apply ([^;}]*)$/,
|
||||||
['.', separator],
|
triggerCharacters: ['.', separator],
|
||||||
tailwind.config,
|
config: tailwind.config,
|
||||||
'.'
|
prefix: '.'
|
||||||
)
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
this._providers.push(
|
this._providers.push(
|
||||||
createCompletionItemProvider(
|
createCompletionItemProvider({
|
||||||
this._items,
|
items: this._items,
|
||||||
HTML_TYPES,
|
languages: HTML_TYPES,
|
||||||
/\bclass(Name)?=["']([^"']*)$/, // /\bclass(Name)?=(["'])(?!.*?\2)/
|
regex: /\bclass=["']([^"']*)$/, // /\bclass(Name)?=(["'])(?!.*?\2)/
|
||||||
["'", '"', ' ', '.', separator],
|
triggerCharacters: ["'", '"', ' ', '.', separator],
|
||||||
tailwind.config
|
config: tailwind.config,
|
||||||
)
|
emmet: true
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
this._providers.push(
|
this._providers.push(
|
||||||
vscode.languages.registerCompletionItemProvider(
|
createCompletionItemProvider({
|
||||||
CSS_TYPES,
|
items: this._items,
|
||||||
|
languages: JS_TYPES,
|
||||||
|
regex: /\bclass(Name)?=["']([^"']*)$/, // /\bclass(Name)?=(["'])(?!.*?\2)/
|
||||||
|
triggerCharacters: ["'", '"', ' ', separator]
|
||||||
|
.concat([
|
||||||
|
Object.keys(
|
||||||
|
vscode.workspace.getConfiguration('emmet.includeLanguages')
|
||||||
|
).indexOf('javascript') !== -1 && '.'
|
||||||
|
])
|
||||||
|
.filter(Boolean),
|
||||||
|
config: tailwind.config,
|
||||||
|
emmet:
|
||||||
|
Object.keys(
|
||||||
|
vscode.workspace.getConfiguration('emmet.includeLanguages')
|
||||||
|
).indexOf('javascript') !== -1
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vue.js
|
||||||
|
this._providers.push(
|
||||||
|
createCompletionItemProvider({
|
||||||
|
items: this._items,
|
||||||
|
languages: ['vue'],
|
||||||
|
regex: /\bclass=["']([^"']*)$/,
|
||||||
|
enable: text => {
|
||||||
|
if (
|
||||||
|
text.indexOf('<template') !== -1 &&
|
||||||
|
text.indexOf('</template>') === -1
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
triggerCharacters: ["'", '"', ' ', separator]
|
||||||
|
.concat([
|
||||||
|
Object.keys(
|
||||||
|
vscode.workspace.getConfiguration('emmet.includeLanguages')
|
||||||
|
).indexOf('vue-html') !== -1 && '.'
|
||||||
|
])
|
||||||
|
.filter(Boolean),
|
||||||
|
config: tailwind.config,
|
||||||
|
emmet:
|
||||||
|
Object.keys(
|
||||||
|
vscode.workspace.getConfiguration('emmet.includeLanguages')
|
||||||
|
).indexOf('vue-html') !== -1
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this._providers.push(
|
||||||
|
createCompletionItemProvider({
|
||||||
|
items: this._items,
|
||||||
|
languages: ['vue'],
|
||||||
|
regex: /\bclass=["']([^"']*)$/,
|
||||||
|
enable: text => {
|
||||||
|
if (
|
||||||
|
text.indexOf('<script') !== -1 &&
|
||||||
|
text.indexOf('</script>') === -1
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
triggerCharacters: ["'", '"', ' ', separator],
|
||||||
|
config: tailwind.config
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this._providers.push(
|
||||||
|
createCompletionItemProvider({
|
||||||
|
items: this._items,
|
||||||
|
languages: ['vue'],
|
||||||
|
regex: /@apply ([^;}]*)$/,
|
||||||
|
triggerCharacters: ['.', separator],
|
||||||
|
config: tailwind.config,
|
||||||
|
enable: text => {
|
||||||
|
if (
|
||||||
|
text.indexOf('<style') !== -1 &&
|
||||||
|
text.indexOf('</style>') === -1
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
this._providers.push(
|
||||||
|
createConfigItemProvider({
|
||||||
|
languages: CSS_TYPES,
|
||||||
|
items: this._prefixedConfigItems
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
this._providers.push(
|
||||||
|
createConfigItemProvider({
|
||||||
|
languages: ['vue'],
|
||||||
|
items: this._configItems,
|
||||||
|
enable: text => {
|
||||||
|
if (
|
||||||
|
text.indexOf('<style') !== -1 &&
|
||||||
|
text.indexOf('</style>') === -1
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
this._providers.push(
|
||||||
|
vscode.languages.registerHoverProvider(
|
||||||
|
[...HTML_TYPES, ...JS_TYPES, 'vue'],
|
||||||
{
|
{
|
||||||
provideCompletionItems: (
|
provideHover: (document, position, token) => {
|
||||||
document: vscode.TextDocument,
|
const range1: vscode.Range = new vscode.Range(
|
||||||
position: vscode.Position
|
|
||||||
): vscode.CompletionItem[] => {
|
|
||||||
const range: vscode.Range = new vscode.Range(
|
|
||||||
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
||||||
position
|
position
|
||||||
)
|
)
|
||||||
const text: string = document.getText(range)
|
const text1: string = document.getText(range1)
|
||||||
|
|
||||||
let matches = text.match(/config\(["']([^"']*)$/)
|
if (!/\bclass(Name)?=['"][^'"]*$/.test(text1)) return
|
||||||
|
|
||||||
if (!matches) return []
|
const range2: vscode.Range = new vscode.Range(
|
||||||
|
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
||||||
let objPath =
|
position.with({ line: position.line + 1 })
|
||||||
matches[1]
|
|
||||||
.replace(/\.[^.]*$/, '')
|
|
||||||
.replace('.', '.children.')
|
|
||||||
.trim() + '.children'
|
|
||||||
let foo = dlv(this._configItems, objPath)
|
|
||||||
|
|
||||||
if (foo) {
|
|
||||||
console.log(Object.keys(foo).map(x => foo[x].item))
|
|
||||||
return Object.keys(foo).map(x => foo[x].item)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(this._configItems).map(
|
|
||||||
x => this._configItems[x].item
|
|
||||||
)
|
)
|
||||||
}
|
const text2: string = document.getText(range2)
|
||||||
},
|
|
||||||
"'",
|
|
||||||
'"',
|
|
||||||
'.'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this._providers.push(
|
let str = text1 + text2.substr(text1.length).match(/^([^"' ]*)/)[0]
|
||||||
vscode.languages.registerHoverProvider(HTML_TYPES, {
|
let matches = str.match(/\bclass(Name)?=["']([^"']*)$/)
|
||||||
provideHover: (document, position, token) => {
|
|
||||||
const range1: vscode.Range = new vscode.Range(
|
|
||||||
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
|
||||||
position
|
|
||||||
)
|
|
||||||
const text1: string = document.getText(range1)
|
|
||||||
|
|
||||||
if (!/\bclass(Name)?=['"][^'"]*$/.test(text1)) return
|
if (matches && matches[2]) {
|
||||||
|
let className = matches[2].split(' ').pop()
|
||||||
|
let parts = className.split(':')
|
||||||
|
|
||||||
const range2: vscode.Range = new vscode.Range(
|
if (typeof dlv(this._tailwind.classNames, parts) === 'string') {
|
||||||
new vscode.Position(Math.max(position.line - 5, 0), 0),
|
let base = parts.pop()
|
||||||
position.with({ line: position.line + 1 })
|
let selector = `.${escapeClassName(className)}`
|
||||||
)
|
|
||||||
const text2: string = document.getText(range2)
|
|
||||||
|
|
||||||
let str = text1 + text2.substr(text1.length).match(/^([^"' ]*)/)[0]
|
if (parts.indexOf('hover') !== -1) {
|
||||||
let matches = str.match(/\bclass(Name)?=["']([^"']*)$/)
|
selector += ':hover'
|
||||||
|
} else if (parts.indexOf('focus') !== -1) {
|
||||||
if (matches && matches[2]) {
|
selector += ':focus'
|
||||||
let className = matches[2].split(' ').pop()
|
} else if (parts.indexOf('active') !== -1) {
|
||||||
let parts = className.split(':')
|
selector += ':active'
|
||||||
|
} else if (parts.indexOf('group-hover') !== -1) {
|
||||||
if (typeof dlv(this._tailwind.classNames, parts) === 'string') {
|
selector = `.group:hover ${selector}`
|
||||||
let base = parts.pop()
|
|
||||||
let selector = `.${escapeClassName(className)}`
|
|
||||||
|
|
||||||
if (parts.indexOf('hover') !== -1) {
|
|
||||||
selector += ':hover'
|
|
||||||
} else if (parts.indexOf('focus') !== -1) {
|
|
||||||
selector += ':focus'
|
|
||||||
} else if (parts.indexOf('active') !== -1) {
|
|
||||||
selector += ':active'
|
|
||||||
} else if (parts.indexOf('group-hover') !== -1) {
|
|
||||||
selector = `.group:hover ${selector}`
|
|
||||||
}
|
|
||||||
|
|
||||||
let hoverStr = new vscode.MarkdownString()
|
|
||||||
let css = this._tailwind.classNames[base]
|
|
||||||
let m = css.match(/^(::?[a-z-]+) {(.*?)}/)
|
|
||||||
if (m) {
|
|
||||||
selector += m[1]
|
|
||||||
css = m[2].trim()
|
|
||||||
}
|
|
||||||
css = css.replace(/([;{]) /g, '$1\n').replace(/^/gm, ' ')
|
|
||||||
let code = `${selector} {\n${css}\n}`
|
|
||||||
let screens = dlv(this._tailwind.config, 'screens', {})
|
|
||||||
|
|
||||||
Object.keys(screens).some(screen => {
|
|
||||||
if (parts.indexOf(screen) !== -1) {
|
|
||||||
code = `@media (min-width: ${
|
|
||||||
screens[screen]
|
|
||||||
}) {\n${code.replace(/^/gm, ' ')}\n}`
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
})
|
|
||||||
hoverStr.appendCodeblock(code, 'css')
|
|
||||||
|
|
||||||
let hoverRange = new vscode.Range(
|
let hoverStr = new vscode.MarkdownString()
|
||||||
new vscode.Position(
|
let css = this._tailwind.classNames[base]
|
||||||
position.line,
|
let m = css.match(/^(::?[a-z-]+) {(.*?)}/)
|
||||||
position.character +
|
if (m) {
|
||||||
str.length -
|
selector += m[1]
|
||||||
text1.length -
|
css = m[2].trim()
|
||||||
className.length
|
}
|
||||||
),
|
css = css.replace(/([;{]) /g, '$1\n').replace(/^/gm, ' ')
|
||||||
new vscode.Position(
|
let code = `${selector} {\n${css}\n}`
|
||||||
position.line,
|
let screens = dlv(this._tailwind.config, 'screens', {})
|
||||||
position.character + str.length - text1.length
|
|
||||||
|
Object.keys(screens).some(screen => {
|
||||||
|
if (parts.indexOf(screen) !== -1) {
|
||||||
|
code = `@media (min-width: ${
|
||||||
|
screens[screen]
|
||||||
|
}) {\n${code.replace(/^/gm, ' ')}\n}`
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
hoverStr.appendCodeblock(code, 'css')
|
||||||
|
|
||||||
|
let hoverRange = new vscode.Range(
|
||||||
|
new vscode.Position(
|
||||||
|
position.line,
|
||||||
|
position.character +
|
||||||
|
str.length -
|
||||||
|
text1.length -
|
||||||
|
className.length
|
||||||
|
),
|
||||||
|
new vscode.Position(
|
||||||
|
position.line,
|
||||||
|
position.character + str.length - text1.length
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
return new vscode.Hover(hoverStr, hoverRange)
|
return new vscode.Hover(hoverStr, hoverRange)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
this._disposable = vscode.Disposable.from(...this._providers)
|
this._disposable = vscode.Disposable.from(...this._providers)
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
module.exports = [
|
||||||
|
'a',
|
||||||
|
'abbr',
|
||||||
|
'acronym',
|
||||||
|
'address',
|
||||||
|
'applet',
|
||||||
|
'area',
|
||||||
|
'article',
|
||||||
|
'aside',
|
||||||
|
'audio',
|
||||||
|
'b',
|
||||||
|
'base',
|
||||||
|
'basefont',
|
||||||
|
'bdi',
|
||||||
|
'bdo',
|
||||||
|
'bgsound',
|
||||||
|
'big',
|
||||||
|
'blink',
|
||||||
|
'blockquote',
|
||||||
|
'body',
|
||||||
|
'br',
|
||||||
|
'button',
|
||||||
|
'canvas',
|
||||||
|
'caption',
|
||||||
|
'center',
|
||||||
|
'cite',
|
||||||
|
'code',
|
||||||
|
'col',
|
||||||
|
'colgroup',
|
||||||
|
'command',
|
||||||
|
'content',
|
||||||
|
'data',
|
||||||
|
'datalist',
|
||||||
|
'dd',
|
||||||
|
'del',
|
||||||
|
'details',
|
||||||
|
'dfn',
|
||||||
|
'dialog',
|
||||||
|
'dir',
|
||||||
|
'div',
|
||||||
|
'dl',
|
||||||
|
'dt',
|
||||||
|
'element',
|
||||||
|
'em',
|
||||||
|
'embed',
|
||||||
|
'fieldset',
|
||||||
|
'figcaption',
|
||||||
|
'figure',
|
||||||
|
'font',
|
||||||
|
'footer',
|
||||||
|
'form',
|
||||||
|
'frame',
|
||||||
|
'frameset',
|
||||||
|
'h1',
|
||||||
|
'head',
|
||||||
|
'header',
|
||||||
|
'hgroup',
|
||||||
|
'hr',
|
||||||
|
'html',
|
||||||
|
'i',
|
||||||
|
'iframe',
|
||||||
|
'image',
|
||||||
|
'img',
|
||||||
|
'input',
|
||||||
|
'ins',
|
||||||
|
'isindex',
|
||||||
|
'kbd',
|
||||||
|
'keygen',
|
||||||
|
'label',
|
||||||
|
'legend',
|
||||||
|
'li',
|
||||||
|
'link',
|
||||||
|
'listing',
|
||||||
|
'main',
|
||||||
|
'map',
|
||||||
|
'mark',
|
||||||
|
'marquee',
|
||||||
|
'menu',
|
||||||
|
'menuitem',
|
||||||
|
'meta',
|
||||||
|
'meter',
|
||||||
|
'multicol',
|
||||||
|
'nav',
|
||||||
|
'nextid',
|
||||||
|
'nobr',
|
||||||
|
'noembed',
|
||||||
|
'noframes',
|
||||||
|
'noscript',
|
||||||
|
'object',
|
||||||
|
'ol',
|
||||||
|
'optgroup',
|
||||||
|
'option',
|
||||||
|
'output',
|
||||||
|
'p',
|
||||||
|
'param',
|
||||||
|
'picture',
|
||||||
|
'plaintext',
|
||||||
|
'pre',
|
||||||
|
'progress',
|
||||||
|
'q',
|
||||||
|
'rb',
|
||||||
|
'rp',
|
||||||
|
'rt',
|
||||||
|
'rtc',
|
||||||
|
'ruby',
|
||||||
|
's',
|
||||||
|
'samp',
|
||||||
|
'script',
|
||||||
|
'section',
|
||||||
|
'select',
|
||||||
|
'shadow',
|
||||||
|
'slot',
|
||||||
|
'small',
|
||||||
|
'source',
|
||||||
|
'spacer',
|
||||||
|
'span',
|
||||||
|
'strike',
|
||||||
|
'strong',
|
||||||
|
'style',
|
||||||
|
'sub',
|
||||||
|
'summary',
|
||||||
|
'sup',
|
||||||
|
'table',
|
||||||
|
'tbody',
|
||||||
|
'td',
|
||||||
|
'template',
|
||||||
|
'textarea',
|
||||||
|
'tfoot',
|
||||||
|
'th',
|
||||||
|
'thead',
|
||||||
|
'time',
|
||||||
|
'title',
|
||||||
|
'tr',
|
||||||
|
'track',
|
||||||
|
'tt',
|
||||||
|
'u',
|
||||||
|
'ul',
|
||||||
|
'var',
|
||||||
|
'video',
|
||||||
|
'wbr',
|
||||||
|
'xmp'
|
||||||
|
]
|
Loading…
Reference in New Issue