Page MenuHomePhabricator

Support archive templates in zhwiki
Closed, ResolvedPublicBUG REPORT

Assigned To
Authored By
Supergrey1
Nov 9 2025, 8:45 AM
Referenced Files
F82140084: 圖片.png
May 17 2026, 12:00 PM
F81731777: image.png
May 15 2026, 7:29 PM
F81701756: 圖片.png
May 15 2026, 4:16 PM

Description

Support the following templates:

Example usage:

What happens?:

The user name and date are recognized and moved out of the message, which is unneeded, and left an empty space in 執行者:。 (translated as Operator: .)

What should have happened instead?:

Easiest solution would be to ignore these archive templates.

Event Timeline

Thanks for the task. I'll add a full configuration for zhwiki when I get a free minute :)

1F616EMO changed the task status from Stalled to In Progress.May 15 2026, 4:12 PM
1F616EMO claimed this task.
1F616EMO triaged this task as Medium priority.
1F616EMO subscribed.

Hmm, apparently I did not fix the problem here (and I personally don't think it's a big deal); instead, I went on to fix the DYKN issue and other smaller quirks. Will decide if I should unassign myself or decline this ticket tomorrow.

圖片.png (956×405 px, 198 KB)

Xqt changed the task status from In Progress to Open.May 15 2026, 4:25 PM

I have ideas on how to support these templates. Currently discussing with @1F616EMO.

I definitely need a better doc here, haha.

You see, there are two stages at which an element may be excluded in CD:

  1. The stage at which we collect valid signatures to form comments around them.
  2. The stage at which we collect valid comment parts around signatures from stage 1, going back in the DOM.

An element may be excluded at stage 1 (= a comment won't be formed around it) but still be considered a part of (another) comment at stage 2, and vice versa.

  1. To list classes that should be excluded from stage 1, the noSignatureClasses config property is used, accompanied by noSignatureTemplates directly below it. (The first is for the rendered web page, the second is for wikitext.)
  2. To describe conditions that should halt stage 2, the rejectNode function is used.

You have several options here:

  1. (Recommended.) Just add cd-moveMark class to your "moved to/from" templates. This allows CD to correctly classify this element as a "moved to/from" template AND consider it part of comment BUT exclude it visually. E.g. if I click "Edit subject" on this screenshot, I'll still be able to edit the topic subject as part of the first comment:
    image.png (1,092×301 px, 64 KB)
  2. Alternatively or additionally, add mw-notalk class to your "move to/from" templates. This is the recommended way in DiscussionTools to remove the "Reply" button from "moved to/from" templates. CD also supports it.
  3. Alternatively or additionally, add any class already used by your "moved to/from" templates (e.g. notice or metadata) to the noSignatureClasses config property. In this case, for all elements with this class, no comments will be formed around them.

In fact, you can do all 3! E.g. in enwiki, noSignatureClasses has this → no comments may be formed around signatures in ambox and tmbox notices:

	noSignatureClasses: [
		'unresolved',
		'resolved',
		'ambox',

		// {{GA nominee|timestamp}}
		'tmbox',

		'NavFrame',
	],

I hope this helps.

Xqt subscribed.

I don’t see how this is related to archivbot.

Fixed via cd-moveMark. The addition of mw-notalk would affect users using the default settings and would require community input.

@Jack_who_built_the_house It seems like the use of htmlpaser2 in the worker breaks a lot of the checking logic; for example, nodeName, innerText, classList and matches are not a thing in the supplied node element. How should I deal with that?

FYI, the code:

		'_rejectNodeMatches': `
			.memo-rfcmakepublic, /* RFC 公示模板 */
			.dykentry, /* DYKC 投票元數據 */
			div.archived.archive-top > dl:first-of-type, /* [[T:archive top]]系統提示 */
			div.archived.archive-top > dl:first-of-type ~ hr,
			p.notice /* [[T:存檔至]]等模板 */
		`,
		'rejectNode': function (node) {
			// 優良、典範條目投票期模板匹配
			if (node.nodeName === 'DL' && node.innerText.match(
					/^投票期:.*\n下次可提名.*起/s)) {
				return true;
			}

			return node.matches(convenientDiscussions.config._rejectNodeMatches);
		},

@1F616EMO In the worker context, node is domhandler's Element with some props and methods I added for uniformity. It doesn't have the matches method. innerText and nodeName I've just added as aliases for textContent and tagName.

In the worker context, you don't really need the precision you need in the window context. The page is parsed in the worker solely to check for new and edited comments. So you may simply add a check like 'matches' in node or node instanceof Element before calling node.matches.

The only case where this will make a difference is when an element that matches _rejectNodeMatches is added before a comment. In this case, CD will think it was edited and show a corresponding note. So, I asked Claude Sonnet 4.6 Extended Thinking to generate a replacement code without matches() and checked if the props it uses exist in our worker context. The result is quite lengthy, but you can use it if you want.

'rejectNode': function (node) {
	// 優良、典範條目投票期模板匹配
	if (node.nodeName === 'DL' && node.innerText.match(
			/^投票期:.*\n下次可提名.*起/s)) {
		return true;
	}

	// .memo-rfcmakepublic
	if (node.classList.contains('memo-rfcmakepublic')) return true;

	// .dykentry
	if (node.classList.contains('dykentry')) return true;

	const parent = node.parentElement;
	const isInArchiveTop = (
		parent?.nodeName === 'DIV' &&
		parent.classList.contains('archived') &&
		parent.classList.contains('archive-top')
	);

	if (isInArchiveTop) {
		// div.archived.archive-top > dl:first-of-type
		if (node.nodeName === 'DL') {
			let sibling = node.previousElementSibling;
			let isFirstDl = true;
			while (sibling) {
				if (sibling.nodeName === 'DL') { isFirstDl = false; break; }
				sibling = sibling.previousElementSibling;
			}
			if (isFirstDl) return true;
		}

		// div.archived.archive-top > dl:first-of-type ~ hr
		if (node.nodeName === 'HR') {
			let sibling = node.previousElementSibling;
			while (sibling) {
				// Any preceding DL must be (or precede) the first-of-type DL
				if (sibling.nodeName === 'DL') return true;
				sibling = sibling.previousElementSibling;
			}
		}
	}

	// p.notice
	if (node.nodeName === 'P' && node.classList.contains('notice')) return true;

	return false;
},

Thank you for your suggestion. I decide to keep the simple checks while not doing the heavy ones in the worker.

https://zh.wikipedia.org/wiki/User:1F616EMO/convenientDiscussions.js#L-177--L-207

@1F616EMO Sorry, I'm being silly. There is no Element in the worker scope (and if it were, it'd be domhandler's Element), so you get "ReferenceError: Element is not defined" errors. You'll need to check for 'matches' in node instead of node instanceof Element.

Patch applied. Thank you for the clarification.

@Jack_who_built_the_house As seen on https://zh.wikipedia.org/wiki/User_talk:~2026-27770-11#c-1F616EMO-20260517113100-2026年5月, only the texts inside the block template is considered part of the comment, while the whole template should be seen as one. Is it possible to solve it?

-{H|zh-hans:封禁;zh-hant:封鎖;}-<div class="user-block skin-invert mw-archivedtalk" style="min-height: 40px;color:#000">[[File:Stop x nuvola with clock.svg|40px|left|alt=附上時鐘的停止圖標|class=skin-invert]]<div style="margin-left:45px">由於持續進行[[Wikipedia:破坏|破壞]],您已被'''[[WP:封禁方针|禁止]]'''在'''31小時'''內編輯維基百科。當封禁結束後,我們歡迎您[[WP:五大支柱|作出有建設性的貢獻]]。</div><div style="margin-left:45px">如果您認為有合理的理由可獲解封,請閱讀[[WP:封禁申诉指导|封禁申訴指導]],然後在討論頁上的封禁通知下添加以下文字:<!-- 請複製頁面上顯示的文本,而不是此編輯區域中顯示的文本。請勿包含“tlx|”代碼。 -->{{tlx|unblock|您的理由'' &#126;&#126;&#126;&#126;''}}。若您'''重新-{zh-hans:创建;zh-hant:建立;}-帳戶'''或'''使用匿名身份'''在討論頁申訴,會被視為[[Wikipedia:封禁#繞過封鎖|繞過封禁]]發言,可能導致您的'''封禁時間被延長''',且您用作申訴的帳戶亦會被封禁。[[U:1F616EMO|1F616EMO]]([[UT:1F616EMO|喵留言]]~[[WP:VPH|求助?]]) 2026年5月17日 (日) 11:31 (UTC)</div></div><!-- Template:uw-vblock -->

圖片.png (1,211×266 px, 193 KB)

@1F616EMO The problem here is that that template has the mw-archivedtalk class. As a result, CD treats it as a container for an archived discussion. Without this class, the parsing will be correct. If you want to disable the reply button in both DT and CD for this element, add the mw-notalk class instead.

I believe mw-notalk is not desired as it should still be treated as a talk message and generate DT anchors, while the reply button should be disabled so that blocked users won't use {{unblock}} over the colon indent (which would cause rendering errors). Should I do this instead:

<div class="mw-archivedtalk">
    <div class="user-block skin-invert"><!-- My contents... --></div>
</div>
1F616EMO changed the task status from Open to In Progress.May 19 2026, 12:37 PM

The local configuration of CD is now on ext.gadget.convenientDiscussions as a hidden gadget (no consensus so far on whether to accept it as a gadget, that's why it's hidden).