Skip to content

Commit

Permalink
feat(folding): sticky scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
bhsd-harry committed Dec 3, 2024
1 parent dcef1fc commit d7e9c76
Show file tree
Hide file tree
Showing 8 changed files with 783 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**Added**

- New parser function signatures
- Sticky scroll by sections

**Fixed**

Expand Down
33 changes: 26 additions & 7 deletions server/src/folding.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {FoldingRangeKind, Range as TextRange, SymbolKind} from 'vscode-languageserver/node';
import {parse, docs} from './tasks';
import {getText} from './util';
import type {FoldingRangeParams, FoldingRange, DocumentSymbol} from 'vscode-languageserver/node';
import type {Token, HeadingToken} from 'wikilint';

Expand All @@ -19,28 +20,38 @@ async function provide(
sections = new Array<DocumentSymbol | undefined>(6),
tokens = root.querySelectorAll<Token>(symbol ? 'heading-title' : 'heading-title,table,template,magic-word');
for (const token of tokens) {
const {top, height} = token.getBoundingClientRect();
const {top, left, height, width} = token.getBoundingClientRect();
if (token.type === 'heading-title') {
const {level} = token.parentNode as HeadingToken;
if (symbol) {
for (let i = level - 1; i < 6; i++) {
if (sections[i]) {
const {end} = sections[i]!.range;
end.line = top - 1;
end.character = getText(doc, top - 1, 0, top, 0).length - 1;
}
sections[i] = undefined;
}
const section = token.text().trim() || ' ',
name = names.has(section)
? new Array(names.size).fill('').map((_, i) => `${section.trim()}_${i + 2}`)
.find(s => !names.has(s))!
: section,
container = sections.slice(0, level - 1).findLast(Boolean),
range = TextRange.create(top, 0, top + height, 0),
range = TextRange.create(
top,
left - level,
top + height - 1,
(height === 1 ? left : 0) + width + level,
),
info: DocumentSymbol = {
name,
kind: SymbolKind.String,
range,
selectionRange: range,
selectionRange: structuredClone(range),
};
names.add(name);
sections[level - 1] = info;
for (let i = level; i < 6; i++) {
sections[i] = undefined;
}
if (container) {
container.children ??= [];
container.children.push(info);
Expand Down Expand Up @@ -69,7 +80,15 @@ async function provide(
});
}
}
if (!symbol) {
if (symbol) {
for (const section of sections) {
if (section) {
const {end} = section.range;
end.line = lineCount - 1;
end.character = getText(doc, lineCount - 1, 0, lineCount, 0).length;
}
}
} else {
for (const line of levels) {
if (line !== undefined && line < lineCount) {
ranges.push({
Expand Down
3 changes: 1 addition & 2 deletions server/src/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ export const provideLinks = async ({uri}: TextDocumentIdentifier, path: string):
if (target.startsWith('//')) {
target = `https:${target}`;
}
new URL(target); // eslint-disable-line no-new
return [{range: createNodeRange(root, token), target}];
return [{range: createNodeRange(root, token), target: new URL(target).href}];
} catch {
return [];
}
Expand Down
28 changes: 14 additions & 14 deletions server/src/test/folding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,26 @@ y }} z
{
name: '1',
kind: SymbolKind.String,
range: {start: {line: 3, character: 0}, end: {line: 4, character: 0}},
selectionRange: {start: {line: 3, character: 0}, end: {line: 4, character: 0}},
range: {start: {line: 3, character: 3}, end: {line: 22, character: 0}},
selectionRange: {start: {line: 3, character: 3}, end: {line: 3, character: 8}},
children: [
{
name: '2',
kind: SymbolKind.String,
range: {start: {line: 7, character: 0}, end: {line: 8, character: 0}},
selectionRange: {start: {line: 7, character: 0}, end: {line: 8, character: 0}},
range: {start: {line: 7, character: 8}, end: {line: 19, character: 0}},
selectionRange: {start: {line: 7, character: 8}, end: {line: 7, character: 15}},
children: [
{
name: '3',
kind: SymbolKind.String,
range: {start: {line: 11, character: 0}, end: {line: 12, character: 0}},
selectionRange: {start: {line: 11, character: 0}, end: {line: 12, character: 0}},
range: {start: {line: 11, character: 0}, end: {line: 19, character: 0}},
selectionRange: {start: {line: 11, character: 0}, end: {line: 11, character: 13}},
children: [
{
name: '4_2',
kind: SymbolKind.String,
range: {start: {line: 16, character: 0}, end: {line: 18, character: 0}},
selectionRange: {start: {line: 16, character: 0}, end: {line: 18, character: 0}},
range: {start: {line: 16, character: 0}, end: {line: 19, character: 0}},
selectionRange: {start: {line: 16, character: 0}, end: {line: 17, character: 11}},
},
],
},
Expand All @@ -78,22 +78,22 @@ y }} z
{
name: '4',
kind: SymbolKind.String,
range: {start: {line: 20, character: 0}, end: {line: 21, character: 0}},
selectionRange: {start: {line: 20, character: 0}, end: {line: 21, character: 0}},
range: {start: {line: 20, character: 0}, end: {line: 22, character: 0}},
selectionRange: {start: {line: 20, character: 0}, end: {line: 20, character: 7}},
},
],
},
{
name: '4_3',
kind: SymbolKind.String,
range: {start: {line: 23, character: 0}, end: {line: 24, character: 0}},
selectionRange: {start: {line: 23, character: 0}, end: {line: 24, character: 0}},
range: {start: {line: 23, character: 0}, end: {line: 30, character: 0}},
selectionRange: {start: {line: 23, character: 0}, end: {line: 23, character: 5}},
children: [
{
name: '4_4',
kind: SymbolKind.String,
range: {start: {line: 27, character: 0}, end: {line: 28, character: 0}},
selectionRange: {start: {line: 27, character: 0}, end: {line: 28, character: 0}},
range: {start: {line: 27, character: 0}, end: {line: 30, character: 0}},
selectionRange: {start: {line: 27, character: 0}, end: {line: 27, character: 9}},
},
],
},
Expand Down
56 changes: 56 additions & 0 deletions server/src/test/hover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as assert from 'assert';
import {getPositionParams} from './util';
import {provideHover} from '../hover';

const wikitext = `
__NOTOC__
{{ #LEN: }}
{{ PAGESIZE }}
`;

describe('hoverProvider', () => {
it('behavior switch', async () => {
assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 1, 0)), {
contents: {
kind: 'markdown',
value: 'Hides the table of contents (TOC).',
},
range: {
start: {line: 1, character: 0},
end: {line: 1, character: 9},
},
});
});
it('parser function', async () => {
assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 2, 7)), {
contents: {
kind: 'markdown',
value:
`- **{{ #LEN:** *string* **}}**
The #len function returns the length of the given string.`,
},
range: {
start: {line: 2, character: 2},
end: {line: 2, character: 7},
},
});
});
it('variable', async () => {
assert.deepStrictEqual(await provideHover(getPositionParams(__filename, wikitext, 3, 4)), {
contents: {
kind: 'markdown',
value:
`- **{{ PAGESIZE** **}}**
- **{{ PAGESIZE:** *page name* **}}**
- **{{ PAGESIZE:** *page name* **|** R **}}**
**[Expensive]** Returns the byte size of the specified page.`,
},
range: {
start: {line: 3, character: 2},
end: {line: 3, character: 12},
},
});
});
});
110 changes: 110 additions & 0 deletions server/src/test/links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as assert from 'assert';
import {getParams} from './util';
import {provideLinks} from '../links';
import type {DocumentLink} from 'vscode-languageserver/node';

const wikitext = `
[[ : help : a ]]
{{ b }}
{{ #invoke: c | c }}
RFC 1
PMID 1
ISBN 1-2-3-4-5-6-7-8-9-0
[//d d]
News:e
<templatestyles src = f />
<q cite = "HTTPS://G/G">
`,
results: DocumentLink[] = [
{
range: {
start: {line: 1, character: 2},
end: {line: 1, character: 14},
},
target: 'https://mediawiki.org/wiki/Help%3AA',
},
{
range: {
start: {line: 2, character: 2},
end: {line: 2, character: 5},
},
target: 'https://mediawiki.org/wiki/Template%3AB',
},
{
range: {
start: {line: 3, character: 11},
end: {line: 3, character: 14},
},
target: 'https://mediawiki.org/wiki/Module%3AC',
},
{
range: {
start: {line: 4, character: 0},
end: {line: 4, character: 5},
},
target: 'https://tools.ietf.org/html/rfc1',
},
{
range: {
start: {line: 5, character: 0},
end: {line: 5, character: 6},
},
target: 'https://pubmed.ncbi.nlm.nih.gov/1',
},
{
range: {
start: {line: 6, character: 0},
end: {line: 6, character: 24},
},
target: 'https://mediawiki.org/wiki/Special%3ABooksources%2F1234567890',
},
{
range: {
start: {line: 7, character: 1},
end: {line: 7, character: 4},
},
target: 'https://d/',
},
{
range: {
start: {line: 8, character: 0},
end: {line: 8, character: 6},
},
target: 'news:e',
},
{
range: {
start: {line: 9, character: 22},
end: {line: 9, character: 23},
},
target: 'https://mediawiki.org/wiki/Template%3AF',
},
{
range: {
start: {line: 10, character: 11},
end: {line: 10, character: 22},
},
target: 'https://g/G',
},
];

describe('documentLinkProvider', () => {
it('https://mediawiki.org/wiki/$1', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/$1'),
results,
);
});
it('https://mediawiki.org/wiki/', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki/'),
results,
);
});
it('https://mediawiki.org/wiki', async () => {
assert.deepStrictEqual(
await provideLinks(getParams(__filename, wikitext).textDocument, 'https://mediawiki.org/wiki'),
results,
);
});
});
Loading

0 comments on commit d7e9c76

Please sign in to comment.