-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tiddlywiki 5.2.7版本中Markdown toc按钮失效 #9
Comments
https://github.com/Gk0Wk/TiddlySeq/blob/master/src/page-toc/PageTOCWidget.ts 这里根据tiddler标题获取那个tree,但是对于markdown来说,html下还有一层 导致tree返回的列表失败,我就卡在这里不知到怎么改了
|
由于ts插件修改调试不是很方便(懒), 所以这里仅给出Chatgpt参考代码, 可用性未知 如果当前标题下多嵌套了一层
通过以上修改,即可在处理标题时,包括嵌套在一层 |
发现你改的代码还是有问题,修改了下,目前在markdown中没问题,在tw文档中点击事件注入没做适配( 因为我自己也不使用) import {
HTMLTags,
IParseTreeNode,
IChangedTiddlers,
IWidgetInitialiseOptions,
IWikiASTNode,
} from 'tiddlywiki';
import { widget as Widget } from '$:/core/modules/widgets/widget.js';
type HeaderTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
class PageTOCWidget extends Widget {
private tocNodeTag: HTMLTags = 'div';
private tocHeaderNodeTag: HTMLTags = 'p';
private tocNodeClass: string = 'gk0wk-tiddlertoc-container';
private tocHeaderNodeClassPrefix: string = 'gk0wk-tiddlertoc-';
private tocTitle: string = '';
private emptyMessage: string = '';
private scrollMode: 'start' | 'center' | 'end' | 'nearest' = 'center';
private includeHeaderMap: Record<HeaderTag, boolean> = {
h1: true,
h2: true,
h3: true,
h4: true,
h5: true,
h6: true,
};
initialise(parseTreeNode: IParseTreeNode, options: IWidgetInitialiseOptions) {
super.initialise(parseTreeNode, options);
this.computeAttributes();
}
execute() {
this.tocTitle = this.getAttribute(
'tiddler',
this.getVariable('currentTiddler'),
);
this.tocNodeTag = this.getAttribute('tag', 'div') as any;
if (($tw.config.htmlUnsafeElements as any).includes(this.tocNodeTag)) {
this.tocNodeTag = 'div';
}
this.tocHeaderNodeTag = this.getAttribute('headerTag', 'p') as any;
if (
($tw.config.htmlUnsafeElements as any).includes(this.tocHeaderNodeTag)
) {
this.tocHeaderNodeTag = 'p';
}
this.tocNodeClass = this.getAttribute(
'class',
'gk0wk-tiddlertoc-container',
);
this.tocHeaderNodeClassPrefix = this.getAttribute(
'headerClassPrefix',
'gk0wk-tiddlertoc-',
);
this.emptyMessage = this.getAttribute('emptyMessage', '');
this.includeHeaderMap.h1 = this.getAttribute('h1', 'yes') === 'yes';
this.includeHeaderMap.h2 = this.getAttribute('h2', 'yes') === 'yes';
this.includeHeaderMap.h3 = this.getAttribute('h3', 'yes') === 'yes';
this.includeHeaderMap.h4 = this.getAttribute('h4', 'yes') === 'yes';
this.includeHeaderMap.h5 = this.getAttribute('h5', 'yes') === 'yes';
this.includeHeaderMap.h6 = this.getAttribute('h6', 'yes') === 'yes';
this.scrollMode = this.getAttribute('scrollMode', 'center') as any;
if (!['start', 'center', 'end', 'nearest'].includes(this.scrollMode)) {
this.scrollMode = 'center';
}
}
render(parent: Node, nextSibling: Node | null) {
this.parentDomNode = parent;
this.execute();
// 递归检测
if (this.parentWidget!.hasVariable('page-toc-recursion-detection', 'yes')) {
this.domNodes.push(
parent.appendChild(this.document.createTextNode('[Page TOC]')),
);
return;
}
this.setVariable('page-toc-recursion-detection', 'yes');
// 渲染目录
const tocNode = $tw.utils.domMaker(this.tocNodeTag, {
class: this.tocNodeClass,
});
this.domNodes.push(tocNode);
try {
const toc = this.getTOCInfo();
if (!toc || toc.headers.length === 0) {
tocNode.insertBefore(
$tw.utils.domMaker(this.tocHeaderNodeTag, {
class: `${this.tocHeaderNodeClassPrefix}empty`,
text: this.emptyMessage,
}),
nextSibling,
);
} else {
for (let i = 0, len = toc.headers.length; i < len; i++) {
const { tag, text, count } = toc.headers[i];
const headerNode = $tw.utils.domMaker(this.tocHeaderNodeTag, {
class: `${this.tocHeaderNodeClassPrefix}${tag}`,
text,
});
if ($tw.browser) {
// eslint-disable-next-line @typescript-eslint/no-loop-func
headerNode.addEventListener('click', () => {
const target = document
.querySelector(
`.tc-tiddler-frame[data-tiddler-title="${toc.title.replace(
'"',
'\\"',
)}"]`,
)
?.querySelectorAll?.(`.tc-tiddler-body > .markdown > ${tag}`)?.[count];
if (!target) {
return;
}
switch (this.scrollMode) {
case 'center':
case 'nearest': {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
target.scrollIntoView({
behavior: 'smooth',
block: this.scrollMode,
});
break;
}
default: {
target.scrollIntoView({
behavior: 'auto',
block: this.scrollMode,
});
if (this.scrollMode === 'end') {
document.body.scrollTop += 100;
if (document.scrollingElement) {
document.scrollingElement.scrollTop += 100;
}
} else {
document.body.scrollTop -= 100;
if (document.scrollingElement) {
document.scrollingElement.scrollTop -= 100;
}
}
}
}
});
}
tocNode.appendChild(headerNode);
}
}
} catch (e) {
console.error(e);
tocNode.textContent = String(e);
}
parent.insertBefore(tocNode, nextSibling);
}
refresh(changedTiddlers: IChangedTiddlers) {
const changedAttributes = this.computeAttributes();
if (
$tw.utils.count(changedAttributes) > 0 ||
Object.hasOwnProperty.call(changedAttributes, this.tocTitle)
) {
this.refreshSelf();
this.refreshChildren(changedTiddlers);
return true;
}
return this.refreshChildren(changedTiddlers);
}
getTOCInfo() {
// Check empty
if (this.tocTitle === '') {
return undefined;
}
const currentTiddler = $tw.wiki.getTiddler(this.tocTitle);
if (!currentTiddler) {
return undefined;
}
const type = currentTiddler.fields.type || 'text/vnd.tiddlywiki';
if (type !== 'text/vnd.tiddlywiki' && type !== 'text/x-markdown' && type !== 'text/markdown') {
return undefined;
}
const headers: { tag: HeaderTag; count: number; text: string }[] = [];
const headersCount: Record<HeaderTag, number> = {
h1: 0,
h2: 0,
h3: 0,
h4: 0,
h5: 0,
h6: 0,
};
const root = $tw.wiki.parseTiddler(this.tocTitle).tree;
if (root.length === 0) {
return undefined;
}
let contents = root;
// Parse params
while (['set', 'importvariables'].includes(contents[0]?.type)) {
contents = (contents[0] as IWikiASTNode).children ?? [];
}
const processNode = (node: IWikiASTNode) => {
if (node.type !== 'element') {
return;
}
// Find text within the header element
let text = '';
for (const childNode of node.children || []) {
if (childNode.type === 'text') {
text += childNode.text;
}
}
// Recursive processing for nested div elements
for (const childNode of node.children || []) {
if (childNode.type === 'element' && childNode.tag.match(/^h[1-6]$/)) {
processNode(childNode);
}
}
if (node.tag.match(/^h[1-6]$/)){
headers.push({
tag: (node as any).tag,
count: headersCount[(node as any).tag as HeaderTag]++,
text: text.trim(),
});
}
};
$tw.utils.each([...contents], processNode);
return {
title: this.tocTitle,
headers,
};
}
}
exports['page-toc'] = PageTOCWidget; |
@straywriter 你的这份代码有个问题就是只能识别纯文本的标题,如果其中包含了变量微件等就看不到了。 因此最后的方式是先渲染,渲染之后再找,这样反倒是很简单,写个dfs就可以了。 于是现在tos已经可以支持任意位置的标题了,除了写在外面的、还有引用的等等,和看到的保持一致。 请升级最新版本 |
查到 const root = $tw.wiki.parseTiddler(this.tocTitle).tree;这行代码不能返回markdown正文里面的标题导致,相关接口我不太熟悉,不知道怎么修,可以修一下吗
The text was updated successfully, but these errors were encountered: