add experimental classRegex setting (#129)

master
Brad Cornes 2020-11-27 16:56:19 +00:00
parent 5633349c49
commit a4fdd949be
7 changed files with 1921 additions and 5558 deletions

7387
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -158,6 +158,10 @@
"default": "error", "default": "error",
"markdownDescription": "Unknown value used with the [`@tailwind` directive](https://tailwindcss.com/docs/functions-and-directives/#tailwind)", "markdownDescription": "Unknown value used with the [`@tailwind` directive](https://tailwindcss.com/docs/functions-and-directives/#tailwind)",
"scope": "language-overridable" "scope": "language-overridable"
},
"tailwindCSS.experimental.classRegex": {
"type": "array",
"scope": "language-overridable"
} }
} }
} }

View File

@ -46,6 +46,9 @@ const defaultSettings: Settings = {
tabSize: 2, tabSize: 2,
emmetCompletions: false, emmetCompletions: false,
includeLanguages: {}, includeLanguages: {},
experimental: {
classRegex: [],
},
validate: true, validate: true,
lint: { lint: {
cssConflict: 'warning', cssConflict: 'warning',

View File

@ -15,6 +15,7 @@
"line-column": "^1.0.2", "line-column": "^1.0.2",
"mitt": "^2.1.0", "mitt": "^2.1.0",
"moo": "^0.5.1", "moo": "^0.5.1",
"multi-regexp2": "^1.0.3",
"semver": "^7.3.2", "semver": "^7.3.2",
"sift-string": "^0.0.2", "sift-string": "^0.0.2",
"tsdx": "^0.13.3", "tsdx": "^0.13.3",
@ -6417,6 +6418,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/multi-regexp2": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/multi-regexp2/-/multi-regexp2-1.0.3.tgz",
"integrity": "sha512-yYrsPk+8TW+r4HK8/7/BIqc7QzcMSIwUGwGouiwIC/anHpjCfKO/PNACGiPYn0WzEMiq+LuEAmZ80NRiCCykiw=="
},
"node_modules/mute-stream": { "node_modules/mute-stream": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@ -14741,6 +14747,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"multi-regexp2": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/multi-regexp2/-/multi-regexp2-1.0.3.tgz",
"integrity": "sha512-yYrsPk+8TW+r4HK8/7/BIqc7QzcMSIwUGwGouiwIC/anHpjCfKO/PNACGiPYn0WzEMiq+LuEAmZ80NRiCCykiw=="
},
"mute-stream": { "mute-stream": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",

View File

@ -22,6 +22,7 @@
"line-column": "^1.0.2", "line-column": "^1.0.2",
"mitt": "^2.1.0", "mitt": "^2.1.0",
"moo": "^0.5.1", "moo": "^0.5.1",
"multi-regexp2": "^1.0.3",
"semver": "^7.3.2", "semver": "^7.3.2",
"sift-string": "^0.0.2", "sift-string": "^0.0.2",
"tsdx": "^0.13.3", "tsdx": "^0.13.3",

View File

@ -31,6 +31,7 @@ import {
} from './util/lexers' } from './util/lexers'
import { validateApply } from './util/validateApply' import { validateApply } from './util/validateApply'
import { flagEnabled } from './util/flagEnabled' import { flagEnabled } from './util/flagEnabled'
import MultiRegexp from 'multi-regexp2'
export function completionsFromClassList( export function completionsFromClassList(
state: State, state: State,
@ -195,6 +196,72 @@ function provideClassAttributeCompletions(
return null return null
} }
async function provideCustomClassNameCompletions(
state: State,
document: TextDocument,
position: Position
): Promise<CompletionList> {
const settings = await getDocumentSettings(state, document)
const regexes = dlv(settings, 'experimental.classRegex', [])
if (regexes.length === 0) return null
const searchRange = {
start: { line: Math.max(position.line - 10, 0), character: 0 },
end: { line: position.line + 10, character: 0 },
}
let str = document.getText(searchRange)
for (let i = 0; i < regexes.length; i++) {
let [containerRegex, classRegex] = Array.isArray(regexes[i])
? regexes[i]
: [regexes[i]]
containerRegex = new MultiRegexp(new RegExp(containerRegex))
try {
const match = containerRegex.execForGroup(str, 1)
if (match === null) {
throw Error()
}
const searchStart = document.offsetAt(searchRange.start)
const matchStart = searchStart + match.start
const matchEnd = searchStart + match.end
const cursor = document.offsetAt(position)
if (cursor >= matchStart && cursor <= matchEnd) {
let classList
if (classRegex) {
classRegex = new MultiRegexp(new RegExp(classRegex, 'g'))
let classMatch
while (
(classMatch = classRegex.execForGroup(match.match, 1)) !== null
) {
const classMatchStart = matchStart + classMatch.start
const classMatchEnd = matchStart + classMatch.end
if (cursor >= classMatchStart && cursor <= classMatchEnd) {
classList = classMatch.match.substr(0, cursor - classMatchStart)
}
}
if (typeof classList === 'undefined') {
throw Error()
}
} else {
classList = match.match.substr(0, cursor - matchStart)
}
return completionsFromClassList(state, classList, {
start: {
line: position.line,
character: position.character - classList.length,
},
end: position,
})
}
} catch (_) {}
}
return null
}
function provideAtApplyCompletions( function provideAtApplyCompletions(
state: State, state: State,
document: TextDocument, document: TextDocument,
@ -711,7 +778,8 @@ export async function doComplete(
provideCssDirectiveCompletions(state, document, position) || provideCssDirectiveCompletions(state, document, position) ||
provideScreenDirectiveCompletions(state, document, position) || provideScreenDirectiveCompletions(state, document, position) ||
provideVariantsDirectiveCompletions(state, document, position) || provideVariantsDirectiveCompletions(state, document, position) ||
provideTailwindDirectiveCompletions(state, document, position) provideTailwindDirectiveCompletions(state, document, position) ||
(await provideCustomClassNameCompletions(state, document, position))
if (result) return result if (result) return result

View File

@ -41,6 +41,9 @@ export type Settings = {
invalidConfigPath: DiagnosticSeveritySetting invalidConfigPath: DiagnosticSeveritySetting
invalidTailwindDirective: DiagnosticSeveritySetting invalidTailwindDirective: DiagnosticSeveritySetting
} }
experimental: {
classRegex: string[]
}
} }
interface NotificationEmitter { interface NotificationEmitter {