volar-service-pug 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ import { TextDocument } from 'vscode-languageserver-textdocument';
2
+ export declare function baseParse(pugCode: string): {
3
+ htmlCode: string;
4
+ mappings: import("@volar/source-map").Mapping<any>[];
5
+ pugTextDocument: TextDocument;
6
+ error: {
7
+ code: string;
8
+ msg: string;
9
+ line: number;
10
+ column: number;
11
+ filename: string;
12
+ } | undefined;
13
+ ast: Node | undefined;
14
+ emptyLineEnds: number[];
15
+ };
16
+ export type Node = BlockNode | MixinNode | TagNode | TextNode | CommentNode | BlockCommentNode;
17
+ export interface BlockNode {
18
+ type: 'Block';
19
+ nodes: Node[];
20
+ line: number;
21
+ }
22
+ export interface TagNode {
23
+ type: 'Tag';
24
+ name: string;
25
+ selfClosing: boolean;
26
+ block: BlockNode;
27
+ attrs: {
28
+ name: string;
29
+ val: string | true;
30
+ line: number;
31
+ column: number;
32
+ mustEscape: boolean;
33
+ }[];
34
+ attributeBlocks: {}[];
35
+ isInline: boolean;
36
+ line: number;
37
+ column: number;
38
+ }
39
+ export interface TextNode {
40
+ type: 'Text';
41
+ val: string;
42
+ line: number;
43
+ column: number;
44
+ }
45
+ export interface CommentNode {
46
+ type: 'Comment';
47
+ val: string;
48
+ buffer: boolean;
49
+ line: number;
50
+ column: number;
51
+ }
52
+ export interface BlockCommentNode {
53
+ type: 'BlockComment';
54
+ block: BlockNode;
55
+ val: string;
56
+ buffer: boolean;
57
+ line: number;
58
+ column: number;
59
+ }
60
+ export interface MixinNode {
61
+ type: 'Mixin';
62
+ name: string;
63
+ args: null;
64
+ block: BlockNode | null;
65
+ line: number;
66
+ column: number;
67
+ }
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.baseParse = void 0;
7
+ const muggle_string_1 = require("muggle-string");
8
+ const source_map_1 = require("@volar/source-map");
9
+ const pug_lexer_1 = __importDefault(require("pug-lexer"));
10
+ const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
11
+ const pugParser = require('pug-parser');
12
+ function baseParse(pugCode) {
13
+ const fileName = 'foo.pug';
14
+ const pugTextDocument = vscode_languageserver_textdocument_1.TextDocument.create('file:///a.pug', 'jade', 0, pugCode);
15
+ const codes = [];
16
+ let error;
17
+ let emptyLineEnds = [];
18
+ let attrsBlocks;
19
+ let ast;
20
+ try {
21
+ const tokens = (0, pug_lexer_1.default)(pugCode, { filename: fileName });
22
+ emptyLineEnds = collectEmptyLineEnds(tokens);
23
+ attrsBlocks = collectAttrsBlocks(tokens);
24
+ ast = pugParser(tokens, { filename: fileName, src: pugCode });
25
+ visitNode(ast, undefined, undefined);
26
+ codes.push([
27
+ '',
28
+ undefined,
29
+ pugCode.trimEnd().length,
30
+ ]);
31
+ }
32
+ catch (e) {
33
+ const _error = e;
34
+ error = {
35
+ ..._error,
36
+ line: _error.line - 1,
37
+ column: _error.column - 1,
38
+ };
39
+ }
40
+ ;
41
+ return {
42
+ htmlCode: (0, muggle_string_1.toString)(codes),
43
+ mappings: (0, source_map_1.buildMappings)(codes),
44
+ pugTextDocument,
45
+ error,
46
+ ast,
47
+ emptyLineEnds,
48
+ };
49
+ function visitNode(node, next, parent) {
50
+ if (node.type === 'Block') {
51
+ for (let i = 0; i < node.nodes.length; i++) {
52
+ visitNode(node.nodes[i], node.nodes[i + 1], node);
53
+ }
54
+ }
55
+ else if (node.type === 'Mixin') {
56
+ if (node.block) {
57
+ visitNode(node.block, undefined, node);
58
+ }
59
+ }
60
+ else if (node.type === 'Tag') {
61
+ const pugTagRange = getDocRange(node.line, node.column, node.name.length);
62
+ codes.push([
63
+ '',
64
+ undefined,
65
+ pugTagRange.start,
66
+ ]);
67
+ const selfClosing = node.block.nodes.length === 0;
68
+ addStartTag(node, selfClosing);
69
+ if (!selfClosing) {
70
+ visitNode(node.block, next, parent);
71
+ addEndTag(node, next, parent);
72
+ }
73
+ codes.push([
74
+ '',
75
+ undefined,
76
+ pugTagRange.start,
77
+ ]);
78
+ }
79
+ else if (node.type === 'Text') {
80
+ codes.push([
81
+ node.val,
82
+ undefined,
83
+ getDocOffset(node.line, node.column),
84
+ ]);
85
+ }
86
+ }
87
+ function addStartTag(node, selfClosing) {
88
+ codes.push([
89
+ '',
90
+ undefined,
91
+ getDocOffset(node.line, node.column),
92
+ ]);
93
+ codes.push('<');
94
+ const tagRange = getDocRange(node.line, node.column, node.name.length);
95
+ if (pugCode.substring(tagRange.start, tagRange.end) === node.name) {
96
+ codes.push([
97
+ node.name,
98
+ undefined,
99
+ tagRange.start,
100
+ ]);
101
+ }
102
+ else {
103
+ codes.push(node.name);
104
+ }
105
+ const noTitleAttrs = node.attrs.filter(attr => !attr.mustEscape && attr.name !== 'class');
106
+ const noTitleClassAttrs = node.attrs.filter(attr => !attr.mustEscape && attr.name === 'class');
107
+ const attrsBlock = attrsBlocks.get(getDocOffset(node.line, node.column)); // support attr auto-complete in spaces
108
+ const hasClassAttr = attrsBlock && attrsBlock.text.match(/\bclass\b\s*=/i);
109
+ if (!hasClassAttr) {
110
+ addClassesOrStyles(noTitleClassAttrs, 'class');
111
+ }
112
+ for (const attr of noTitleAttrs) {
113
+ codes.push(' ');
114
+ codes.push(attr.name);
115
+ if (typeof attr.val !== 'boolean') {
116
+ codes.push('=');
117
+ codes.push([
118
+ attr.val,
119
+ undefined,
120
+ getDocOffset(attr.line, attr.column),
121
+ ]);
122
+ }
123
+ }
124
+ if (attrsBlock) {
125
+ codes.push(' ');
126
+ codes.push([
127
+ attrsBlock.text,
128
+ undefined,
129
+ attrsBlock.offset,
130
+ ]);
131
+ }
132
+ if (selfClosing) {
133
+ codes.push(' />');
134
+ }
135
+ else {
136
+ codes.push('>');
137
+ }
138
+ }
139
+ function addEndTag(node, next, parent) {
140
+ let nextStart;
141
+ if (next) {
142
+ if (next.type === 'Block') {
143
+ nextStart = getDocOffset(next.line, 1);
144
+ }
145
+ else {
146
+ nextStart = getDocOffset(next.line, next.column);
147
+ }
148
+ }
149
+ else if (!parent) {
150
+ nextStart = pugCode.length;
151
+ }
152
+ if (nextStart !== undefined) {
153
+ codes.push([
154
+ '',
155
+ undefined,
156
+ nextStart,
157
+ ]);
158
+ }
159
+ codes.push(`</${node.name}>`);
160
+ }
161
+ function addClassesOrStyles(attrs, attrName) {
162
+ if (!attrs.length)
163
+ return;
164
+ codes.push(' ');
165
+ codes.push(attrName);
166
+ codes.push('=');
167
+ codes.push('"');
168
+ for (const attr of attrs) {
169
+ if (typeof attr.val !== 'boolean') {
170
+ codes.push(' ');
171
+ codes.push([
172
+ attr.val.slice(1, -1),
173
+ undefined,
174
+ getDocOffset(attr.line, attr.column + 1),
175
+ ]);
176
+ }
177
+ }
178
+ codes.push('"');
179
+ }
180
+ function collectEmptyLineEnds(tokens) {
181
+ const ends = [];
182
+ for (const token of tokens) {
183
+ if (token.type === 'newline' || token.type === 'outdent') {
184
+ let currentLine = token.loc.start.line - 2;
185
+ let prevLine = getLineText(pugTextDocument, currentLine);
186
+ while (prevLine.trim() === '') {
187
+ ends.push(pugTextDocument.offsetAt({ line: currentLine + 1, character: 0 }) - 1);
188
+ if (currentLine <= 0)
189
+ break;
190
+ currentLine--;
191
+ prevLine = getLineText(pugTextDocument, currentLine);
192
+ }
193
+ }
194
+ }
195
+ return ends.sort((a, b) => a - b);
196
+ }
197
+ function collectAttrsBlocks(tokens) {
198
+ const blocks = new Map();
199
+ for (let i = 0; i < tokens.length; i++) {
200
+ const token = tokens[i];
201
+ if (token.type === 'start-attributes') {
202
+ let tagStart = token;
203
+ for (let j = i - 1; j >= 0; j--) {
204
+ const prevToken = tokens[j];
205
+ if (prevToken.type === 'newline'
206
+ || prevToken.type === 'indent'
207
+ || prevToken.type === 'outdent'
208
+ || prevToken.type === ':')
209
+ break;
210
+ tagStart = prevToken;
211
+ if (prevToken.type === 'tag')
212
+ break;
213
+ }
214
+ let prevToken = token;
215
+ let text = '';
216
+ for (i++; i < tokens.length; i++) {
217
+ const attrToken = tokens[i];
218
+ addPrevSpace(attrToken);
219
+ if (attrToken.type === 'attribute') {
220
+ let attrText = pugCode.substring(getDocOffset(attrToken.loc.start.line, attrToken.loc.start.column), getDocOffset(attrToken.loc.end.line, attrToken.loc.end.column));
221
+ if (typeof attrToken.val === 'string' && attrText.indexOf('=') >= 0) {
222
+ let valText = attrToken.val;
223
+ if (valText.startsWith('`') && valText.endsWith('`')) {
224
+ if (valText.indexOf('"') === -1) {
225
+ valText = `"${valText.slice(1, -1)}"`;
226
+ }
227
+ else {
228
+ valText = `'${valText.slice(1, -1)}'`;
229
+ }
230
+ }
231
+ valText = valText.replace(/ \\\n/g, '//\n');
232
+ text += attrText.substring(0, attrText.lastIndexOf(attrToken.val)) + valText;
233
+ }
234
+ else {
235
+ text += attrText;
236
+ }
237
+ }
238
+ else if (attrToken.type === 'end-attributes') {
239
+ blocks.set(getDocOffset(tagStart.loc.start.line, tagStart.loc.start.column), {
240
+ offset: getDocOffset(token.loc.end.line, token.loc.end.column),
241
+ text,
242
+ });
243
+ break;
244
+ }
245
+ prevToken = attrToken;
246
+ }
247
+ function addPrevSpace(currentToken) {
248
+ text += pugCode.substring(getDocOffset(prevToken.loc.end.line, prevToken.loc.end.column), getDocOffset(currentToken.loc.start.line, currentToken.loc.start.column)).replace(/,/g, '\n');
249
+ }
250
+ }
251
+ }
252
+ return blocks;
253
+ }
254
+ function getDocOffset(pugLine, pugColumn) {
255
+ return pugTextDocument.offsetAt({ line: pugLine - 1, character: pugColumn - 1 });
256
+ }
257
+ function getDocRange(pugLine, pugColumn, length) {
258
+ const start = getDocOffset(pugLine, pugColumn);
259
+ const end = start + length;
260
+ return {
261
+ start,
262
+ end,
263
+ };
264
+ }
265
+ }
266
+ exports.baseParse = baseParse;
267
+ function getLineText(document, line) {
268
+ const endOffset = document.offsetAt({ line: line + 1, character: 0 });
269
+ const end = document.positionAt(endOffset);
270
+ const text = document.getText({
271
+ start: { line: line, character: 0 },
272
+ end: end.line === line ? end : document.positionAt(endOffset - 1),
273
+ });
274
+ return text;
275
+ }
276
+ //# sourceMappingURL=baseParse.js.map
package/out/empty.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Service } from '@volar/language-service';
2
+ declare const _default: () => Service;
3
+ export default _default;
package/out/empty.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ console.warn('volar-service-pug: This plugin is not support on web yet.');
4
+ exports.default = () => () => ({});
5
+ //# sourceMappingURL=empty.js.map
package/out/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { Service, ServiceContext } from '@volar/language-service';
2
+ import type * as html from 'vscode-html-languageservice';
3
+ import { TextDocument } from 'vscode-languageserver-textdocument';
4
+ import * as pug from './languageService';
5
+ export interface PluginInstance extends ReturnType<Service> {
6
+ getHtmlLs: () => html.LanguageService;
7
+ updateCustomData(extraData: html.IHTMLDataProvider[]): void;
8
+ getPugLs: () => pug.LanguageService;
9
+ getPugDocument: (document: TextDocument) => pug.PugDocument | undefined;
10
+ }
11
+ declare const _default: () => (context: ServiceContext | undefined) => PluginInstance;
12
+ export default _default;
package/out/index.js ADDED
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const volar_service_html_1 = __importDefault(require("volar-service-html"));
30
+ const language_service_1 = require("@volar/language-service");
31
+ const pug = __importStar(require("./languageService"));
32
+ exports.default = () => (context) => {
33
+ if (!context) {
34
+ return {};
35
+ }
36
+ const pugDocuments = new WeakMap();
37
+ const htmlPlugin = (0, volar_service_html_1.default)()(context);
38
+ const pugLs = pug.getLanguageService(htmlPlugin.getHtmlLs());
39
+ return {
40
+ ...htmlPlugin,
41
+ getPugLs: () => pugLs,
42
+ getPugDocument,
43
+ resolveRuleContext(context) {
44
+ worker(context.document, (pugDocument) => {
45
+ if (pugDocument.ast) {
46
+ context.pug = {
47
+ rootNode: pugDocument.ast,
48
+ languageService: pugLs,
49
+ };
50
+ }
51
+ });
52
+ return context;
53
+ },
54
+ provideCompletionItems(document, position, _) {
55
+ return worker(document, (pugDocument) => {
56
+ return pugLs.doComplete(pugDocument, position, context.env.documentContext);
57
+ });
58
+ },
59
+ provideDiagnostics(document) {
60
+ return worker(document, (pugDocument) => {
61
+ if (pugDocument.error) {
62
+ return [{
63
+ source: 'pug',
64
+ code: pugDocument.error.code,
65
+ message: pugDocument.error.msg,
66
+ range: {
67
+ start: { line: pugDocument.error.line, character: pugDocument.error.column },
68
+ end: { line: pugDocument.error.line, character: pugDocument.error.column },
69
+ },
70
+ }];
71
+ }
72
+ return [];
73
+ });
74
+ },
75
+ provideHover(document, position) {
76
+ return worker(document, async (pugDocument) => {
77
+ const hoverSettings = await context.env.getConfiguration?.('html.hover');
78
+ return pugLs.doHover(pugDocument, position, hoverSettings);
79
+ });
80
+ },
81
+ provideDocumentHighlights(document, position) {
82
+ return worker(document, (pugDocument) => {
83
+ return pugLs.findDocumentHighlights(pugDocument, position);
84
+ });
85
+ },
86
+ provideDocumentLinks(document) {
87
+ return worker(document, (pugDocument) => {
88
+ if (context.env.documentContext) {
89
+ return pugLs.findDocumentLinks(pugDocument, context.env.documentContext);
90
+ }
91
+ });
92
+ },
93
+ provideDocumentSymbols(document, token) {
94
+ return worker(document, async (pugDoc) => {
95
+ const htmlResult = await htmlPlugin.provideDocumentSymbols?.(pugDoc.map.virtualFileDocument, token) ?? [];
96
+ const pugResult = htmlResult.map(htmlSymbol => language_service_1.transformer.asDocumentSymbol(htmlSymbol, range => pugDoc.map.toSourceRange(range))).filter((symbol) => symbol !== undefined);
97
+ return pugResult;
98
+ });
99
+ },
100
+ provideFoldingRanges(document) {
101
+ return worker(document, (pugDocument) => {
102
+ return pugLs.getFoldingRanges(pugDocument);
103
+ });
104
+ },
105
+ provideSelectionRanges(document, positions) {
106
+ return worker(document, (pugDocument) => {
107
+ return pugLs.getSelectionRanges(pugDocument, positions);
108
+ });
109
+ },
110
+ async provideAutoInsertionEdit(document, position, insertContext) {
111
+ return worker(document, async (pugDocument) => {
112
+ const lastCharacter = insertContext.lastChange.text[insertContext.lastChange.text.length - 1];
113
+ if (insertContext.lastChange.rangeLength === 0 && lastCharacter === '=') {
114
+ const enabled = (await context.env.getConfiguration?.('html.autoCreateQuotes')) ?? true;
115
+ if (enabled) {
116
+ const text = pugLs.doQuoteComplete(pugDocument, position, await context.env.getConfiguration?.('html.completion'));
117
+ if (text) {
118
+ return text;
119
+ }
120
+ }
121
+ }
122
+ });
123
+ },
124
+ };
125
+ function worker(document, callback) {
126
+ const pugDocument = getPugDocument(document);
127
+ if (!pugDocument)
128
+ return;
129
+ return callback(pugDocument);
130
+ }
131
+ function getPugDocument(document) {
132
+ if (document.languageId !== 'jade')
133
+ return;
134
+ const cache = pugDocuments.get(document);
135
+ if (cache) {
136
+ const [cacheVersion, cacheDoc] = cache;
137
+ if (cacheVersion === document.version) {
138
+ return cacheDoc;
139
+ }
140
+ }
141
+ const doc = pugLs.parsePugDocument(document.getText());
142
+ pugDocuments.set(document, [document.version, doc]);
143
+ return doc;
144
+ }
145
+ };
146
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,32 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ export { PugDocument } from './pugDocument';
3
+ export * from './baseParse';
4
+ export interface LanguageService extends ReturnType<typeof getLanguageService> {
5
+ }
6
+ export declare function getLanguageService(htmlLs: html.LanguageService): {
7
+ parsePugDocument: (pugCode: string) => {
8
+ htmlTextDocument: html.TextDocument;
9
+ htmlDocument: html.HTMLDocument;
10
+ map: import("@volar/language-service").SourceMapWithDocuments<any>;
11
+ htmlCode: string;
12
+ mappings: import("@volar/source-map").Mapping<any>[];
13
+ pugTextDocument: html.TextDocument;
14
+ error: {
15
+ code: string;
16
+ msg: string;
17
+ line: number;
18
+ column: number;
19
+ filename: string;
20
+ } | undefined;
21
+ ast: import("./baseParse").Node | undefined;
22
+ emptyLineEnds: number[];
23
+ };
24
+ doComplete: (pugDoc: import("./pugDocument").PugDocument, pos: html.Position, documentContext: html.DocumentContext | undefined, options?: html.CompletionConfiguration | undefined) => Promise<html.CompletionList | undefined>;
25
+ findDocumentHighlights: (pugDoc: import("./pugDocument").PugDocument, pos: html.Position) => html.DocumentHighlight[] | undefined;
26
+ findDocumentLinks: (pugDoc: import("./pugDocument").PugDocument, docContext: html.DocumentContext) => html.DocumentLink[];
27
+ doHover: (pugDoc: import("./pugDocument").PugDocument, pos: html.Position, options?: html.HoverSettings | undefined) => html.Hover | undefined;
28
+ createScanner: (pugDoc: import("./pugDocument").PugDocument, initialOffset?: number) => html.Scanner | undefined;
29
+ getSelectionRanges: (pugDoc: import("./pugDocument").PugDocument, posArr: html.Position[]) => html.SelectionRange[];
30
+ doQuoteComplete: (pugDoc: import("./pugDocument").PugDocument, pos: html.Position, options?: html.CompletionConfiguration | undefined) => string | null | undefined;
31
+ getFoldingRanges: (pugDoc: import("./pugDocument").PugDocument) => html.FoldingRange[];
32
+ };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.getLanguageService = void 0;
18
+ const pugDocument_1 = require("./pugDocument");
19
+ const completion_1 = require("./services/completion");
20
+ const documentHighlight_1 = require("./services/documentHighlight");
21
+ const documentLinks_1 = require("./services/documentLinks");
22
+ const hover_1 = require("./services/hover");
23
+ const scanner_1 = require("./services/scanner");
24
+ const selectionRanges_1 = require("./services/selectionRanges");
25
+ const foldingRanges_1 = require("./services/foldingRanges");
26
+ const quoteComplete_1 = require("./services/quoteComplete");
27
+ __exportStar(require("./baseParse"), exports);
28
+ function getLanguageService(htmlLs) {
29
+ return {
30
+ parsePugDocument: (0, pugDocument_1.register)(htmlLs),
31
+ doComplete: (0, completion_1.register)(htmlLs),
32
+ findDocumentHighlights: (0, documentHighlight_1.register)(htmlLs),
33
+ findDocumentLinks: (0, documentLinks_1.register)(htmlLs),
34
+ doHover: (0, hover_1.register)(htmlLs),
35
+ createScanner: (0, scanner_1.register)(htmlLs),
36
+ getSelectionRanges: (0, selectionRanges_1.register)(htmlLs),
37
+ doQuoteComplete: (0, quoteComplete_1.register)(htmlLs),
38
+ getFoldingRanges: (0, foldingRanges_1.register)(),
39
+ };
40
+ }
41
+ exports.getLanguageService = getLanguageService;
42
+ //# sourceMappingURL=languageService.js.map
@@ -0,0 +1,22 @@
1
+ import { SourceMapWithDocuments } from '@volar/language-service';
2
+ import { TextDocument } from 'vscode-languageserver-textdocument';
3
+ import type * as html from 'vscode-html-languageservice';
4
+ export interface PugDocument extends ReturnType<ReturnType<typeof register>> {
5
+ }
6
+ export declare function register(htmlLs: html.LanguageService): (pugCode: string) => {
7
+ htmlTextDocument: TextDocument;
8
+ htmlDocument: html.HTMLDocument;
9
+ map: SourceMapWithDocuments<any>;
10
+ htmlCode: string;
11
+ mappings: import("@volar/source-map").Mapping<any>[];
12
+ pugTextDocument: TextDocument;
13
+ error: {
14
+ code: string;
15
+ msg: string;
16
+ line: number;
17
+ column: number;
18
+ filename: string;
19
+ } | undefined;
20
+ ast: import("./baseParse").Node | undefined;
21
+ emptyLineEnds: number[];
22
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
6
+ const baseParse_1 = require("./baseParse");
7
+ const source_map_1 = require("@volar/source-map");
8
+ function register(htmlLs) {
9
+ return (pugCode) => {
10
+ const parsed = (0, baseParse_1.baseParse)(pugCode);
11
+ const htmlTextDocument = vscode_languageserver_textdocument_1.TextDocument.create('foo.html', 'html', 0, parsed.htmlCode);
12
+ const sourceMap = new language_service_1.SourceMapWithDocuments(parsed.pugTextDocument, htmlTextDocument, new source_map_1.SourceMap(parsed.mappings));
13
+ const htmlDocument = htmlLs.parseHTMLDocument(htmlTextDocument);
14
+ return {
15
+ ...parsed,
16
+ htmlTextDocument,
17
+ htmlDocument,
18
+ map: sourceMap,
19
+ };
20
+ };
21
+ }
22
+ exports.register = register;
23
+ //# sourceMappingURL=pugDocument.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, pos: html.Position, documentContext: html.DocumentContext | undefined, options?: html.CompletionConfiguration | undefined) => Promise<html.CompletionList | undefined>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ const vscode_html_languageservice_1 = require("vscode-html-languageservice");
6
+ function register(htmlLs) {
7
+ const docForEmptyLineCompletion = vscode_html_languageservice_1.TextDocument.create('file:///foo.html', 'html', 0, '< />');
8
+ const htmlDocForEmptyLineCompletion = htmlLs.parseHTMLDocument(docForEmptyLineCompletion);
9
+ const posForEmptyLine = docForEmptyLineCompletion.positionAt(1);
10
+ return async (pugDoc, pos, documentContext, options) => {
11
+ const offset = pugDoc.pugTextDocument.offsetAt(pos);
12
+ if (pugDoc.emptyLineEnds.includes(offset)) {
13
+ const htmlComplete = htmlLs.doComplete(docForEmptyLineCompletion, posForEmptyLine, htmlDocForEmptyLineCompletion, options);
14
+ for (const item of htmlComplete.items) {
15
+ item.textEdit = undefined;
16
+ }
17
+ return htmlComplete;
18
+ }
19
+ const htmlPos = pugDoc.map.toGeneratedPosition(pos);
20
+ if (!htmlPos)
21
+ return;
22
+ const htmlComplete = documentContext ? await htmlLs.doComplete2(pugDoc.htmlTextDocument, htmlPos, pugDoc.htmlDocument, documentContext, options) : htmlLs.doComplete(pugDoc.htmlTextDocument, htmlPos, pugDoc.htmlDocument, options);
23
+ return language_service_1.transformer.asCompletionList(htmlComplete, htmlRange => pugDoc.map.toSourceRange(htmlRange), pugDoc.map.virtualFileDocument);
24
+ };
25
+ }
26
+ exports.register = register;
27
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, pos: html.Position) => html.DocumentHighlight[] | undefined;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ function register(htmlLs) {
6
+ return (pugDoc, pos) => {
7
+ const htmlPos = pugDoc.map.toGeneratedPosition(pos);
8
+ if (!htmlPos)
9
+ return;
10
+ const htmlResult = htmlLs.findDocumentHighlights(pugDoc.map.virtualFileDocument, htmlPos, pugDoc.htmlDocument);
11
+ return language_service_1.transformer.asLocations(htmlResult, htmlRange => pugDoc.map.toSourceRange(htmlRange));
12
+ };
13
+ }
14
+ exports.register = register;
15
+ //# sourceMappingURL=documentHighlight.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, docContext: html.DocumentContext) => html.DocumentLink[];
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ function register(htmlLs) {
6
+ return (pugDoc, docContext) => {
7
+ const htmlResult = htmlLs.findDocumentLinks(pugDoc.map.virtualFileDocument, docContext);
8
+ return language_service_1.transformer.asLocations(htmlResult, htmlRange => pugDoc.map.toSourceRange(htmlRange));
9
+ };
10
+ }
11
+ exports.register = register;
12
+ //# sourceMappingURL=documentLinks.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(): (pugDoc: PugDocument) => html.FoldingRange[];
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.register = void 0;
27
+ const vscode = __importStar(require("vscode-languageserver-types"));
28
+ function register() {
29
+ return (pugDoc) => {
30
+ const result = [];
31
+ const docEndPos = pugDoc.pugTextDocument.positionAt(pugDoc.pugTextDocument.getText().length);
32
+ if (pugDoc.ast) {
33
+ visitNode(pugDoc.ast, findMinimalEndLine(docEndPos.line));
34
+ }
35
+ return result;
36
+ function visitNode(node, endLine) {
37
+ if (node.type === 'Block') {
38
+ for (let i = 0; i < node.nodes.length; i++) {
39
+ const child = node.nodes[i];
40
+ const next = i + 1 < node.nodes.length ? node.nodes[i + 1] : undefined;
41
+ visitNode(child, next ? findMinimalEndLine(next.line - 2) : endLine);
42
+ }
43
+ }
44
+ else if (node.type === 'Tag' || node.type === 'BlockComment') {
45
+ const nodeLine = node.line - 1; // one base to zero base
46
+ if (nodeLine !== endLine) {
47
+ result.push(vscode.FoldingRange.create(nodeLine, endLine, undefined, undefined, node.type === 'BlockComment' ? vscode.FoldingRangeKind.Comment : undefined));
48
+ }
49
+ visitNode(node.block, endLine);
50
+ }
51
+ }
52
+ function findMinimalEndLine(endLine) {
53
+ while (endLine > 0 && getLineText(endLine).trim() === '') {
54
+ endLine--;
55
+ }
56
+ return endLine;
57
+ }
58
+ function getLineText(line) {
59
+ if (line === docEndPos.line) {
60
+ return pugDoc.pugTextDocument.getText({
61
+ start: { line: line, character: 0 },
62
+ end: docEndPos,
63
+ });
64
+ }
65
+ const text = pugDoc.pugTextDocument.getText({
66
+ start: { line: line, character: 0 },
67
+ end: { line: line + 1, character: 0 },
68
+ });
69
+ return text.substring(0, text.length - 1);
70
+ }
71
+ };
72
+ }
73
+ exports.register = register;
74
+ //# sourceMappingURL=foldingRanges.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, pos: html.Position, options?: html.HoverSettings | undefined) => html.Hover | undefined;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ function register(htmlLs) {
6
+ return (pugDoc, pos, options) => {
7
+ const htmlPos = pugDoc.map.toGeneratedPosition(pos);
8
+ if (!htmlPos)
9
+ return;
10
+ const htmlResult = htmlLs.doHover(pugDoc.map.virtualFileDocument, htmlPos, pugDoc.htmlDocument, options);
11
+ if (!htmlResult)
12
+ return;
13
+ return language_service_1.transformer.asHover(htmlResult, htmlRange => pugDoc.map.toSourceRange(htmlRange));
14
+ };
15
+ }
16
+ exports.register = register;
17
+ //# sourceMappingURL=hover.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, pos: html.Position, options?: html.CompletionConfiguration | undefined) => string | null | undefined;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ function register(htmlLs) {
5
+ return (pugDoc, pos, options) => {
6
+ const htmlStart = pugDoc.map.toGeneratedPosition(pos);
7
+ if (!htmlStart)
8
+ return;
9
+ const text = htmlLs.doQuoteComplete(pugDoc.htmlTextDocument, htmlStart, pugDoc.htmlDocument, options);
10
+ return text;
11
+ };
12
+ }
13
+ exports.register = register;
14
+ //# sourceMappingURL=quoteComplete.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, initialOffset?: number) => html.Scanner | undefined;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ function register(htmlLs) {
5
+ return (pugDoc, initialOffset = 0) => {
6
+ const htmlOffset = pugDoc.map.map.mappings
7
+ .filter(mapping => mapping.sourceRange[0] >= initialOffset)
8
+ .sort((a, b) => a.generatedRange[0] - b.generatedRange[0])[0]
9
+ ?.generatedRange[0];
10
+ if (htmlOffset === undefined)
11
+ return;
12
+ const htmlScanner = htmlLs.createScanner(pugDoc.htmlTextDocument.getText(), htmlOffset);
13
+ // @ts-expect-error
14
+ const scanner = {
15
+ scan: () => {
16
+ return htmlScanner.scan();
17
+ },
18
+ getTokenOffset: () => {
19
+ return pugDoc.map.map.toSourceOffset(htmlScanner.getTokenOffset())?.[0] ?? -1;
20
+ },
21
+ getTokenEnd: () => {
22
+ return pugDoc.map.map.toSourceOffset(htmlScanner.getTokenEnd())?.[0] ?? -1;
23
+ },
24
+ getTokenText: htmlScanner.getTokenText,
25
+ getTokenLength: htmlScanner.getTokenLength,
26
+ getTokenError: htmlScanner.getTokenError,
27
+ getScannerState: htmlScanner.getScannerState,
28
+ };
29
+ return scanner;
30
+ };
31
+ }
32
+ exports.register = register;
33
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1,3 @@
1
+ import type * as html from 'vscode-html-languageservice';
2
+ import type { PugDocument } from '../pugDocument';
3
+ export declare function register(htmlLs: html.LanguageService): (pugDoc: PugDocument, posArr: html.Position[]) => html.SelectionRange[];
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.register = void 0;
4
+ const language_service_1 = require("@volar/language-service");
5
+ function register(htmlLs) {
6
+ return (pugDoc, posArr) => {
7
+ const htmlPosArr = posArr
8
+ .map(position => pugDoc.map.toGeneratedPosition(position))
9
+ .filter((v) => !!v);
10
+ const htmlResult = htmlLs.getSelectionRanges(pugDoc.map.virtualFileDocument, htmlPosArr);
11
+ return language_service_1.transformer.asLocations(htmlResult, htmlRange => pugDoc.map.toSourceRange(htmlRange));
12
+ };
13
+ }
14
+ exports.register = register;
15
+ //# sourceMappingURL=selectionRanges.js.map
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "volar-service-pug",
3
+ "version": "0.0.0",
4
+ "main": "out/index.js",
5
+ "license": "MIT",
6
+ "files": [
7
+ "rules.d.ts",
8
+ "out/**/*.js",
9
+ "out/**/*.d.ts"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/volarjs/services.git",
14
+ "directory": "packages/pug"
15
+ },
16
+ "dependencies": {
17
+ "muggle-string": "^0.2.2",
18
+ "pug-lexer": "^5.0.1",
19
+ "pug-parser": "^6.0.0",
20
+ "volar-service-html": "0.0.0",
21
+ "vscode-html-languageservice": "^5.0.4",
22
+ "vscode-languageserver-textdocument": "^1.0.8",
23
+ "vscode-languageserver-types": "^3.17.2"
24
+ },
25
+ "peerDependencies": {
26
+ "@volar/language-service": "*",
27
+ "@volar/source-map": "*"
28
+ },
29
+ "browser": {
30
+ "./out/index.js": "./out/empty.js"
31
+ },
32
+ "gitHead": "1011561ac4bbf79c53c3b80c27692569bf861519"
33
+ }
package/rules.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import * as pug from 'volar-service-pug';
2
+
3
+ declare module '@volar/language-service' {
4
+ interface RuleContext {
5
+ pug?: {
6
+ rootNode: pug.Node;
7
+ languageService: pug.LanguageService;
8
+ }
9
+ }
10
+ }