Skip to content

Commit 279b3b4

Browse files
Improved parsing of tags (fixes #1434)
1 parent e3c63fc commit 279b3b4

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

packages/foam-vscode/src/core/services/markdown-parser.test.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,55 @@ this is some #text that includes #tags we #care-about.
320320
]);
321321
});
322322

323-
it('provides rough range for tags in yaml', () => {
323+
it('provides a specific range for tags in yaml', () => {
324324
// For now it's enough to just get the YAML block range
325325
// in the future we might want to be more specific
326326

327327
const noteA = createNoteFromMarkdown(`
328328
---
329+
prop: hello world
329330
tags: [hello, world, this_is_good]
331+
another: i love the world
330332
---
331333
# this is a heading
332334
this is some text
333335
`);
334336
expect(noteA.tags[0]).toEqual({
335337
label: 'hello',
336-
range: Range.create(1, 0, 3, 3),
338+
range: Range.create(3, 7, 3, 12),
339+
});
340+
expect(noteA.tags[1]).toEqual({
341+
label: 'world',
342+
range: Range.create(3, 14, 3, 19),
343+
});
344+
expect(noteA.tags[2]).toEqual({
345+
label: 'this_is_good',
346+
range: Range.create(3, 21, 3, 33),
347+
});
348+
349+
const noteB = createNoteFromMarkdown(`
350+
---
351+
prop: hello world
352+
tags:
353+
- hello
354+
- world
355+
- this_is_good
356+
another: i love the world
357+
---
358+
# this is a heading
359+
this is some text
360+
`);
361+
expect(noteB.tags[0]).toEqual({
362+
label: 'hello',
363+
range: Range.create(4, 2, 4, 7),
364+
});
365+
expect(noteB.tags[1]).toEqual({
366+
label: 'world',
367+
range: Range.create(5, 2, 5, 7),
368+
});
369+
expect(noteB.tags[2]).toEqual({
370+
label: 'this_is_good',
371+
range: Range.create(6, 2, 6, 14),
337372
});
338373
});
339374
});

packages/foam-vscode/src/core/services/markdown-parser.ts

+37-1
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,51 @@ const getTextFromChildren = (root: Node): string => {
173173
return text;
174174
};
175175

176+
function getPropertiesInfoFromYAML(yamlText: string): {
177+
[key: string]: { key: string; value: string; text: string; line: number };
178+
} {
179+
const yamlProps = yamlText
180+
.split(/(\w+:)/g)
181+
.filter(item => item.trim() !== '');
182+
const lines = yamlText.split('\n');
183+
let result: { line: number; key: string; text: string; value: string }[] = [];
184+
for (let i = 0; i < yamlProps.length / 2; i++) {
185+
const key = yamlProps[i * 2].replace(':', '');
186+
const value = yamlProps[i * 2 + 1].trim();
187+
const text = yamlProps[i * 2] + yamlProps[i * 2 + 1];
188+
result.push({ key, value, text, line: -1 });
189+
}
190+
result = result.map(p => {
191+
const line = lines.findIndex(l => l.startsWith(p.key + ':'));
192+
return { ...p, line };
193+
});
194+
return result.reduce((acc, curr) => {
195+
acc[curr.key] = curr;
196+
return acc;
197+
}, {});
198+
}
199+
176200
const tagsPlugin: ParserPlugin = {
177201
name: 'tags',
178202
onDidFindProperties: (props, note, node) => {
179203
if (isSome(props.tags)) {
204+
const tagPropertyInfo = getPropertiesInfoFromYAML((node as any).value)[
205+
'tags'
206+
];
207+
const tagPropertyStartLine =
208+
node.position!.start.line + tagPropertyInfo.line;
209+
const tagPropertyLines = tagPropertyInfo.text.split('\n');
180210
const yamlTags = extractTagsFromProp(props.tags);
181211
for (const tag of yamlTags) {
212+
const tagLine = tagPropertyLines.findIndex(l => l.includes(tag));
213+
const line = tagPropertyStartLine + tagLine;
214+
const charStart = tagPropertyLines[tagLine].indexOf(tag);
182215
note.tags.push({
183216
label: tag,
184-
range: astPositionToFoamRange(node.position!),
217+
range: Range.createFromPosition(
218+
Position.create(line, charStart),
219+
Position.create(line, charStart + tag.length)
220+
),
185221
});
186222
}
187223
}

0 commit comments

Comments
 (0)