<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://test.zybkcn.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-AdvancedSiteNotices.js</id>
	<title>MediaWiki:Gadget-AdvancedSiteNotices.js - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://test.zybkcn.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-AdvancedSiteNotices.js"/>
	<link rel="alternate" type="text/html" href="https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;action=history"/>
	<updated>2026-07-18T09:16:23Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;diff=285&amp;oldid=prev</id>
		<title>2026年6月14日 (日) 05:35 鹿野耕云</title>
		<link rel="alternate" type="text/html" href="https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;diff=285&amp;oldid=prev"/>
		<updated>2026-06-14T05:35:40Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;amp;diff=285&amp;amp;oldid=72&quot;&gt;显示更改&lt;/a&gt;</summary>
		<author><name>鹿野耕云</name></author>
	</entry>
	<entry>
		<id>https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;diff=72&amp;oldid=prev</id>
		<title>鹿野耕云：​创建页面，内容为“// &lt;nowiki&gt; /*  * ****************************************************************************  * *          &gt;&gt;&gt;&gt;&gt; 小工具导入者：导入前请阅读 &lt;&lt;&lt;&lt;&lt;                     *  * * 请确保通告页面 (Template:AdvancedSiteNotices/ajax)               *  * *                   在您的维基上已受到适当保护。                         *  * *    虽然已尽力正确处理 JavaScript 表达式，                            *  * *…”</title>
		<link rel="alternate" type="text/html" href="https://test.zybkcn.com/w/index.php?title=MediaWiki:Gadget-AdvancedSiteNotices.js&amp;diff=72&amp;oldid=prev"/>
		<updated>2025-11-23T14:24:19Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“// &amp;lt;nowiki&amp;gt; /*  * ****************************************************************************  * *          &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 小工具导入者：导入前请阅读 &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;                     *  * * 请确保通告页面 (&lt;a href=&quot;/w/index.php?title=Template:AdvancedSiteNotices/ajax&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Template:AdvancedSiteNotices/ajax（页面不存在）&quot;&gt;Template:AdvancedSiteNotices/ajax&lt;/a&gt;)               *  * *                   在您的维基上已受到适当保护。                         *  * *    虽然已尽力正确处理 JavaScript 表达式，                            *  * *…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * ****************************************************************************&lt;br /&gt;
 * *          &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 小工具导入者：导入前请阅读 &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;                     *&lt;br /&gt;
 * * 请确保通告页面 ([[Template:AdvancedSiteNotices/ajax]])               *&lt;br /&gt;
 * *                   在您的维基上已受到适当保护。                         *&lt;br /&gt;
 * *    虽然已尽力正确处理 JavaScript 表达式，                            *&lt;br /&gt;
 * *                但它们未经充分的实战测试。                             *&lt;br /&gt;
 * ****************************************************************************&lt;br /&gt;
 *&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
Promise.all([&lt;br /&gt;
    $.ready&lt;br /&gt;
    ]).then(() =&amp;gt; {&lt;br /&gt;
    const geo = null; // 明确设为 null，兼容后续逻辑&lt;br /&gt;
    if (&lt;br /&gt;
        $(&amp;quot;#siteNotice&amp;quot;).length &amp;lt; 0 ||&lt;br /&gt;
        mw.config.get(&amp;quot;wgAction&amp;quot;) === &amp;quot;edit&amp;quot; ||&lt;br /&gt;
        mw.config.get(&amp;quot;wgAction&amp;quot;) === &amp;quot;submit&amp;quot;&lt;br /&gt;
    ) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const { conv } = require(&amp;quot;ext.gadget.HanAssist&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    let customASNInterval = window.customASNInterval || 15;&lt;br /&gt;
    const COOKIE_NAME = &amp;quot;dismissASN&amp;quot;;&lt;br /&gt;
    let cookieVal = Number.parseInt(mw.cookie.get(COOKIE_NAME) || &amp;quot;-1&amp;quot;, 10);&lt;br /&gt;
    let revisionId = 0;&lt;br /&gt;
    let timeoutId = null;&lt;br /&gt;
&lt;br /&gt;
    let $asnRoot = $(&amp;quot;&amp;lt;div&amp;gt;&amp;quot;, { id: &amp;quot;asn-dismissable-notice&amp;quot; });&lt;br /&gt;
    let $asnBody = $(&amp;quot;&amp;lt;div&amp;gt;&amp;quot;, {&lt;br /&gt;
        id: &amp;quot;advancedSiteNotices&amp;quot;,&lt;br /&gt;
        class: &amp;quot;mw-parser-output&amp;quot;,&lt;br /&gt;
    });&lt;br /&gt;
    let $asnClose = $(&amp;quot;&amp;lt;button&amp;gt;&amp;quot;, {&lt;br /&gt;
        title: conv({ hans: &amp;quot;关闭&amp;quot;, hant: &amp;quot;關閉&amp;quot; }),&lt;br /&gt;
        &amp;quot;aria-label&amp;quot;: conv({ hans: &amp;quot;关闭&amp;quot;, hant: &amp;quot;關閉&amp;quot; }),&lt;br /&gt;
        class: &amp;quot;asn-close-button&amp;quot;,&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $asnRoot.append($asnBody, $asnClose);&lt;br /&gt;
    $asnClose.click(() =&amp;gt; {&lt;br /&gt;
        $asnClose.prop(&amp;quot;disabled&amp;quot;, true);&lt;br /&gt;
        mw.cookie.set(COOKIE_NAME, revisionId, {&lt;br /&gt;
            expires: 60 * 60 * 24 * 30,&lt;br /&gt;
            path: &amp;quot;/&amp;quot;,&lt;br /&gt;
            secure: true,&lt;br /&gt;
        });&lt;br /&gt;
        clearTimeout(timeoutId);&lt;br /&gt;
        $asnRoot.fadeOut(() =&amp;gt; {&lt;br /&gt;
            $asnRoot.remove();&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @typedef {Object} TokenizeStatus&lt;br /&gt;
     * @property {string} expression&lt;br /&gt;
     * @property {RegExp} startTokenRe&lt;br /&gt;
     * @property {number} index&lt;br /&gt;
     * @property {((item: any) =&amp;gt; void) &amp;amp; { __orig__?: (item: any) =&amp;gt; void }} append&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * 条件解析器。仅支持 JavaScript 的一个小子集。&lt;br /&gt;
     */&lt;br /&gt;
    class CriteriaExecutor {&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {Record&amp;lt;string, (...args: any[]) =&amp;gt; any&amp;gt;} functions&lt;br /&gt;
         */&lt;br /&gt;
        constructor(functions = {}) {&lt;br /&gt;
            this.functions = functions;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 将表达式解析为标记&lt;br /&gt;
         *&lt;br /&gt;
         * @param {string} expression&lt;br /&gt;
         * @return {any[]}&lt;br /&gt;
         */&lt;br /&gt;
        _tokenizeExpression(expression) {&lt;br /&gt;
            expression = expression.trim();&lt;br /&gt;
            if (!expression) {&lt;br /&gt;
                return [];&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            const result = [];&lt;br /&gt;
            /** @type {TokenizeStatus} */&lt;br /&gt;
            const status = {&lt;br /&gt;
                expression,&lt;br /&gt;
                startTokenRe: /\|\||&amp;amp;&amp;amp;|\b(?:true|false)\b|[(&amp;#039;&amp;quot;!\s]/g,&lt;br /&gt;
                index: 0,&lt;br /&gt;
                append(item) {&lt;br /&gt;
                    result.push(item);&lt;br /&gt;
                },&lt;br /&gt;
            };&lt;br /&gt;
            let match = status.startTokenRe.exec(expression);&lt;br /&gt;
&lt;br /&gt;
            const skipSpace = () =&amp;gt; {&lt;br /&gt;
                while (/\s/.test(expression[status.index] || &amp;quot;&amp;quot;)) {&lt;br /&gt;
                    status.index++;&lt;br /&gt;
                }&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            while (match) {&lt;br /&gt;
                const token = match[0];&lt;br /&gt;
&lt;br /&gt;
                if (status.startTokenRe.lastIndex - token.length !== status.index) {&lt;br /&gt;
                    if (token === &amp;quot;(&amp;quot;) {&lt;br /&gt;
                        // 处理函数调用&lt;br /&gt;
                        const parsed = this._handleFunctionCall(status);&lt;br /&gt;
                        if (!parsed) {&lt;br /&gt;
                            break;&lt;br /&gt;
                        }&lt;br /&gt;
                    } else {&lt;br /&gt;
                        break;&lt;br /&gt;
                    }&lt;br /&gt;
                } else {&lt;br /&gt;
                    let parsed = false;&lt;br /&gt;
                    switch (token) {&lt;br /&gt;
                        case &amp;quot;(&amp;quot;:&lt;br /&gt;
                            parsed = this._handleExpressionStatement(status);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case &amp;quot;||&amp;quot;:&lt;br /&gt;
                        case &amp;quot;&amp;amp;&amp;amp;&amp;quot;:&lt;br /&gt;
                            parsed = this._handleLogicalOperator(status, token);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case &amp;quot;!&amp;quot;:&lt;br /&gt;
                            parsed = this._handleUnaryExpression(status, token);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case &amp;quot;&amp;#039;&amp;quot;:&lt;br /&gt;
                        case &amp;#039;&amp;quot;&amp;#039;:&lt;br /&gt;
                            parsed = this._handleStringLiteral(status, token);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case &amp;quot;true&amp;quot;:&lt;br /&gt;
                        case &amp;quot;false&amp;quot;:&lt;br /&gt;
                            parsed = this._handleBooleanLiteral(status, token);&lt;br /&gt;
                            break;&lt;br /&gt;
                    }&lt;br /&gt;
                    if (!parsed) {&lt;br /&gt;
                        break;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                skipSpace();&lt;br /&gt;
                status.startTokenRe.lastIndex = status.index;&lt;br /&gt;
                match = status.startTokenRe.exec(expression);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (status.index &amp;lt; expression.length - 1) {&lt;br /&gt;
                throw new SyntaxError(&amp;quot;Unexpected token.&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return result;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理函数调用&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleFunctionCall(status) {&lt;br /&gt;
            const functionName = status.expression&lt;br /&gt;
                .slice(status.index, status.startTokenRe.lastIndex - 1)&lt;br /&gt;
                .trim();&lt;br /&gt;
&lt;br /&gt;
            if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(functionName)) {&lt;br /&gt;
                return false;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            const argsStartIndex = status.startTokenRe.lastIndex - 1;&lt;br /&gt;
            const endIndex = this._findNextBalanceItem(&lt;br /&gt;
                status.expression,&lt;br /&gt;
                &amp;quot;(&amp;quot;,&lt;br /&gt;
                &amp;quot;)&amp;quot;,&lt;br /&gt;
                argsStartIndex&lt;br /&gt;
            );&lt;br /&gt;
            if (endIndex === -1) {&lt;br /&gt;
                throw new SyntaxError(&amp;quot;Unbalanced parentheses in function call&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            const rawArgs = status.expression&lt;br /&gt;
                .slice(argsStartIndex + 1, endIndex)&lt;br /&gt;
                .trim();&lt;br /&gt;
            const args = !rawArgs.length&lt;br /&gt;
                ? []&lt;br /&gt;
                : this._balanceSplit(rawArgs, &amp;quot;,&amp;quot;, &amp;quot;(&amp;quot;, &amp;quot;)&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            status.append({&lt;br /&gt;
                type: &amp;quot;FunctionCall&amp;quot;,&lt;br /&gt;
                functionName,&lt;br /&gt;
                args: args.map((arg) =&amp;gt; this._tokenizeExpression(arg)),&lt;br /&gt;
            });&lt;br /&gt;
            status.index = endIndex + 1;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理逻辑运算符&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @param {string} token&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleLogicalOperator(status, token) {&lt;br /&gt;
            status.append({&lt;br /&gt;
                type: &amp;quot;LogicalExpression&amp;quot;,&lt;br /&gt;
                operator: token,&lt;br /&gt;
            });&lt;br /&gt;
            status.index = status.startTokenRe.lastIndex;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理一元表达式&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @param {string} token&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleUnaryExpression(status, token) {&lt;br /&gt;
            const item = {&lt;br /&gt;
                type: &amp;quot;UnaryExpression&amp;quot;,&lt;br /&gt;
                operator: token,&lt;br /&gt;
                argument: undefined,&lt;br /&gt;
            };&lt;br /&gt;
            status.append(item);&lt;br /&gt;
            const origAppend = status.append.__orig__ || status.append;&lt;br /&gt;
            status.append = function (nextItem) {&lt;br /&gt;
                if (nextItem.type === &amp;quot;LogicalExpression&amp;quot;) {&lt;br /&gt;
                    throw new SyntaxError(&amp;quot;Unexpected LogicalExpression&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
                item.argument = nextItem;&lt;br /&gt;
                status.append = origAppend;&lt;br /&gt;
            };&lt;br /&gt;
            status.append.__orig__ = origAppend;&lt;br /&gt;
            status.index = status.startTokenRe.lastIndex;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理布尔值字面量&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @param {string} token&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleBooleanLiteral(status, token) {&lt;br /&gt;
            status.append({&lt;br /&gt;
                type: &amp;quot;BooleanLiteral&amp;quot;,&lt;br /&gt;
                value: token === &amp;quot;true&amp;quot;,&lt;br /&gt;
            });&lt;br /&gt;
            status.index = status.startTokenRe.lastIndex;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理表达式语句&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleExpressionStatement(status) {&lt;br /&gt;
            const endIndex = this._findNextBalanceItem(&lt;br /&gt;
                status.expression,&lt;br /&gt;
                &amp;quot;(&amp;quot;,&lt;br /&gt;
                &amp;quot;)&amp;quot;,&lt;br /&gt;
                status.index&lt;br /&gt;
            );&lt;br /&gt;
            if (endIndex === -1) {&lt;br /&gt;
                throw new SyntaxError(&amp;quot;Unbalanced parentheses in expression.&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            status.append({&lt;br /&gt;
                type: &amp;quot;ExpressionStatement&amp;quot;,&lt;br /&gt;
                expression: this._tokenizeExpression(&lt;br /&gt;
                    status.expression.slice(status.index + 1, endIndex)&lt;br /&gt;
                ),&lt;br /&gt;
            });&lt;br /&gt;
            status.index = endIndex + 1;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 处理字符串字面量&lt;br /&gt;
         *&lt;br /&gt;
         * @param {TokenizeStatus} status&lt;br /&gt;
         * @param {string} delimiter&lt;br /&gt;
         * @return {boolean}&lt;br /&gt;
         */&lt;br /&gt;
        _handleStringLiteral(status, delimiter) {&lt;br /&gt;
            const endIndex = this._findNextTokenWithoutEscape(&lt;br /&gt;
                status.expression,&lt;br /&gt;
                delimiter,&lt;br /&gt;
                status.index + 1&lt;br /&gt;
            );&lt;br /&gt;
            if (endIndex === -1) {&lt;br /&gt;
                throw new SyntaxError(&amp;quot;Unterminated string literal.&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            status.append({&lt;br /&gt;
                type: &amp;quot;StringLiteral&amp;quot;,&lt;br /&gt;
                value: this._parseString(&lt;br /&gt;
                    status.expression.slice(status.index + 1, endIndex)&lt;br /&gt;
                ),&lt;br /&gt;
            });&lt;br /&gt;
            status.index = endIndex + 1;&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 查找下一个平衡项&lt;br /&gt;
         *&lt;br /&gt;
         * @param {string} expression&lt;br /&gt;
         * @param {string} startToken&lt;br /&gt;
         * @param {string} endToken&lt;br /&gt;
         * @param {number} currentIndex&lt;br /&gt;
         * @return {number}&lt;br /&gt;
         */&lt;br /&gt;
        _findNextBalanceItem(expression, startToken, endToken, currentIndex) {&lt;br /&gt;
            let count = 1;&lt;br /&gt;
            while (++currentIndex &amp;lt; expression.length) {&lt;br /&gt;
                if (expression[currentIndex] === startToken) {&lt;br /&gt;
                    count++;&lt;br /&gt;
                } else if (expression[currentIndex] === endToken) {&lt;br /&gt;
                    count--;&lt;br /&gt;
                }&lt;br /&gt;
                if (count === 0) {&lt;br /&gt;
                    return currentIndex;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return -1;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 分割平衡子表达式&lt;br /&gt;
         *&lt;br /&gt;
         * @param {string} expression&lt;br /&gt;
         * @param {string} startToken&lt;br /&gt;
         * @param {string} endToken&lt;br /&gt;
         * @param {string} splitToken&lt;br /&gt;
         * @return {string[]}&lt;br /&gt;
         */&lt;br /&gt;
        _balanceSplit(expression, splitToken, startToken, endToken) {&lt;br /&gt;
            const result = [];&lt;br /&gt;
            let balance = 0;&lt;br /&gt;
            let current = &amp;quot;&amp;quot;;&lt;br /&gt;
            for (const char of expression) {&lt;br /&gt;
                if (char === startToken) {&lt;br /&gt;
                    balance++;&lt;br /&gt;
                } else if (char === endToken) {&lt;br /&gt;
                    balance--;&lt;br /&gt;
                }&lt;br /&gt;
                if (char === splitToken &amp;amp;&amp;amp; balance === 0) {&lt;br /&gt;
                    result.push(current.trim());&lt;br /&gt;
                    current = &amp;quot;&amp;quot;;&lt;br /&gt;
                } else {&lt;br /&gt;
                    current += char;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            if (current) {&lt;br /&gt;
                result.push(current.trim());&lt;br /&gt;
            }&lt;br /&gt;
            return result;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 查找未转义的标记&lt;br /&gt;
         *&lt;br /&gt;
         * @param {string} expression&lt;br /&gt;
         * @param {string} token&lt;br /&gt;
         * @param {number} currentIndex&lt;br /&gt;
         * @return {number}&lt;br /&gt;
         */&lt;br /&gt;
        _findNextTokenWithoutEscape(expression, token, currentIndex) {&lt;br /&gt;
            while (currentIndex &amp;lt; expression.length) {&lt;br /&gt;
                const foundIndex = expression.indexOf(token, currentIndex);&lt;br /&gt;
                if (foundIndex === -1) {&lt;br /&gt;
                    return -1;&lt;br /&gt;
                } else if (expression[foundIndex - 1] !== &amp;quot;\\&amp;quot;) {&lt;br /&gt;
                    return foundIndex;&lt;br /&gt;
                }&lt;br /&gt;
                currentIndex = foundIndex + 1;&lt;br /&gt;
            }&lt;br /&gt;
            return -1;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * 解析字符串并处理转义字符&lt;br /&gt;
         *&lt;br /&gt;
         * @param {string} input&lt;br /&gt;
         * @return {string}&lt;br /&gt;
         */&lt;br /&gt;
        _parseString(input) {&lt;br /&gt;
            return input.replace(&lt;br /&gt;
                /\\(n|t|r|b|f|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\}|u[0-9A-Fa-f]{4}|.)/g,&lt;br /&gt;
                (_, esc) =&amp;gt; {&lt;br /&gt;
                    switch (esc[0]) {&lt;br /&gt;
                        case &amp;quot;n&amp;quot;:&lt;br /&gt;
                            return &amp;quot;\n&amp;quot;;&lt;br /&gt;
                        case &amp;quot;t&amp;quot;:&lt;br /&gt;
                            return &amp;quot;\t&amp;quot;;&lt;br /&gt;
                        case &amp;quot;r&amp;quot;:&lt;br /&gt;
                            return &amp;quot;\r&amp;quot;;&lt;br /&gt;
                        case &amp;quot;b&amp;quot;:&lt;br /&gt;
                            return &amp;quot;\b&amp;quot;;&lt;br /&gt;
                        case &amp;quot;f&amp;quot;:&lt;br /&gt;
                            return &amp;quot;\f&amp;quot;;&lt;br /&gt;
                        case &amp;quot;x&amp;quot;:&lt;br /&gt;
                            if (esc === &amp;quot;x&amp;quot;) {&lt;br /&gt;
                                throw new SyntaxError(&amp;quot;Invalid hexadecimal escape sequence.&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                            return String.fromCharCode(parseInt(esc.slice(1), 16));&lt;br /&gt;
                        case &amp;quot;u&amp;quot;:&lt;br /&gt;
                            if (esc === &amp;quot;u&amp;quot;) {&lt;br /&gt;
                                throw new SyntaxError(&amp;quot;Invalid Unicode escape sequence.&amp;quot;);&lt;br /&gt;
                            } else if (esc[1] === &amp;quot;{&amp;quot;) {&lt;br /&gt;
                                const codePoint = Number.parseInt(esc.slice(2, -1), 16);&lt;br /&gt;
                                if (codePoint &amp;gt; 0x10ffff) {&lt;br /&gt;
                                    throw new SyntaxError(&lt;br /&gt;
                                        `Undefined Unicode code-point: \\${esc}.`&lt;br /&gt;
                                    );&lt;br /&gt;
                                }&lt;br /&gt;
                                return String.fromCodePoint(codePoint);&lt;br /&gt;
                            }&lt;br /&gt;
                            return String.fromCharCode(Number.parseInt(esc.slice(1), 16));&lt;br /&gt;
                        default:&lt;br /&gt;
                            return esc;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {any[]} tokens&lt;br /&gt;
         */&lt;br /&gt;
        _tokensToAst(tokens) {&lt;br /&gt;
            if (!tokens.length) {&lt;br /&gt;
                throw new TypeError(&amp;quot;Token list is empty.&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            // 先處理 &amp;amp;&amp;amp; 再處理 ||&lt;br /&gt;
            let logicalItemIndex = tokens.findIndex((t) =&amp;gt; t.type === &amp;quot;LogicalExpression&amp;quot; &amp;amp;&amp;amp; t.operator === &amp;#039;&amp;amp;&amp;amp;&amp;#039;);&lt;br /&gt;
            if (logicalItemIndex === -1) {&lt;br /&gt;
            	logicalItemIndex = tokens.findIndex((t) =&amp;gt; t.type === &amp;quot;LogicalExpression&amp;quot; &amp;amp;&amp;amp; t.operator === &amp;#039;||&amp;#039;);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (logicalItemIndex === -1) {&lt;br /&gt;
                if (tokens.length === 1) {&lt;br /&gt;
                    return this._tokenToAst(tokens[0]);&lt;br /&gt;
                }&lt;br /&gt;
                throw new SyntaxError(`Unexpected ${tokens[1].type}.`);&lt;br /&gt;
            } else if (logicalItemIndex === 0) {&lt;br /&gt;
                throw new SyntaxError(`Unexpected LogicalExpression`);&lt;br /&gt;
            } else {&lt;br /&gt;
            	const left = this._tokensToAst(tokens.slice(0, logicalItemIndex));&lt;br /&gt;
            	const right = this._tokensToAst(tokens.slice(logicalItemIndex + 1));&lt;br /&gt;
                return {&lt;br /&gt;
                    type: &amp;quot;LogicalExpression&amp;quot;,&lt;br /&gt;
                    operator: tokens[logicalItemIndex].operator,&lt;br /&gt;
                    left,&lt;br /&gt;
                    right,&lt;br /&gt;
                };&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {any} token&lt;br /&gt;
         */&lt;br /&gt;
        _tokenToAst(token) {&lt;br /&gt;
            if (!token) {&lt;br /&gt;
                throw new TypeError(&amp;#039;token is undefined or null.&amp;#039;);&lt;br /&gt;
            }&lt;br /&gt;
            const result = Object.assign({}, token);&lt;br /&gt;
            if (token.type === &amp;quot;UnaryExpression&amp;quot;) {&lt;br /&gt;
                if (!result.argument) {&lt;br /&gt;
                    throw new SyntaxError(&amp;quot;Unexpected UnaryExpression.&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
                result.argument = this._tokenToAst(token.argument);&lt;br /&gt;
            } else if (token.type === &amp;quot;FunctionCall&amp;quot;) {&lt;br /&gt;
                result.args = token.args.map((argument) =&amp;gt;&lt;br /&gt;
                    this._tokensToAst(argument)&lt;br /&gt;
                );&lt;br /&gt;
            } else if (token.type === &amp;quot;ExpressionStatement&amp;quot;) {&lt;br /&gt;
                result.expression = this._tokensToAst(token.expression);&lt;br /&gt;
            }&lt;br /&gt;
            return result;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {string} expression&lt;br /&gt;
         */&lt;br /&gt;
        toAst(expression) {&lt;br /&gt;
            const tokenizes = this._tokenizeExpression(expression);&lt;br /&gt;
            return this._tokensToAst(tokenizes);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {string} functionName&lt;br /&gt;
         * @param {any[]} args&lt;br /&gt;
         */&lt;br /&gt;
        _executeFunction(functionName, args) {&lt;br /&gt;
            if (!Object.prototype.hasOwnProperty.call(this.functions, functionName)) {&lt;br /&gt;
                throw new Error(`Function ${functionName} is not allowed.`);&lt;br /&gt;
            }&lt;br /&gt;
            return this.functions[functionName](...args);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /**&lt;br /&gt;
         * @param {any} ast&lt;br /&gt;
         */&lt;br /&gt;
        evaluate(ast) {&lt;br /&gt;
            switch (ast.type) {&lt;br /&gt;
                case &amp;quot;ExpressionStatement&amp;quot;:&lt;br /&gt;
                    return this.evaluate(ast.expression);&lt;br /&gt;
&lt;br /&gt;
                case &amp;quot;UnaryExpression&amp;quot;:&lt;br /&gt;
                    if (ast.operator === &amp;quot;!&amp;quot;) {&lt;br /&gt;
                        return !this.evaluate(ast.argument);&lt;br /&gt;
                    }&lt;br /&gt;
                    throw new Error(`Unknown UnaryExpression operator: ${ast.operator}`);&lt;br /&gt;
&lt;br /&gt;
                case &amp;quot;LogicalExpression&amp;quot;:&lt;br /&gt;
                    if (ast.operator === &amp;quot;&amp;amp;&amp;amp;&amp;quot; || ast.operator === &amp;quot;||&amp;quot;) {&lt;br /&gt;
                        const left = this.evaluate(ast.left);&lt;br /&gt;
                        if (ast.operator === &amp;quot;&amp;amp;&amp;amp;&amp;quot; &amp;amp;&amp;amp; !left) {&lt;br /&gt;
                            return false;&lt;br /&gt;
                        } else if (ast.operator === &amp;quot;||&amp;quot; &amp;amp;&amp;amp; left) {&lt;br /&gt;
                            return true;&lt;br /&gt;
                        }&lt;br /&gt;
                        return this.evaluate(ast.right);&lt;br /&gt;
                    }&lt;br /&gt;
                    throw new Error(`Unknown LogicalExpression operator: ${ast.operator}`);&lt;br /&gt;
&lt;br /&gt;
                case &amp;quot;FunctionCall&amp;quot;:&lt;br /&gt;
                    const args = ast.args.map((arg) =&amp;gt; this.evaluate(arg));&lt;br /&gt;
                    let returnValue = this._executeFunction(ast.functionName, args);&lt;br /&gt;
                    if (typeof returnValue === &amp;#039;undefined&amp;#039; || returnValue === null) {&lt;br /&gt;
                    	returnValue = false;&lt;br /&gt;
                    } else if (typeof returnValue !== &amp;#039;string&amp;#039; &amp;amp;&amp;amp; typeof returnValue !== &amp;#039;boolean&amp;#039;) {&lt;br /&gt;
	                    console.warn(&lt;br /&gt;
	                        &amp;#039;[AdvancedSiteNotices]: The return type %s of the function %s() is unsafe and has been forcibly converted to a string.&amp;#039;,&lt;br /&gt;
	                        typeof returnValue,&lt;br /&gt;
	                        ast.functionName&lt;br /&gt;
	                    );&lt;br /&gt;
                    	returnValue = String(returnValue);&lt;br /&gt;
                    }&lt;br /&gt;
                    return returnValue;&lt;br /&gt;
&lt;br /&gt;
                case &amp;quot;StringLiteral&amp;quot;:&lt;br /&gt;
                case &amp;quot;BooleanLiteral&amp;quot;:&lt;br /&gt;
                    return ast.value;&lt;br /&gt;
&lt;br /&gt;
                default:&lt;br /&gt;
                    throw new Error(`Unknown AST node type: ${ast.type}`);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const functions = {};&lt;br /&gt;
&lt;br /&gt;
    // 帶參數&lt;br /&gt;
    if (geo) {&lt;br /&gt;
        functions.in_country = (...counties) =&amp;gt; counties.includes(geo.country);&lt;br /&gt;
        functions.in_region = (...regions) =&amp;gt; regions.includes(geo.region);&lt;br /&gt;
        functions.in_city = (...cities) =&amp;gt; cities.includes(geo.city);&lt;br /&gt;
    } else {&lt;br /&gt;
        // 无 geoIP 时，跳过地区筛选（或改为 return false 禁用）&lt;br /&gt;
        functions.in_country = functions.in_region = functions.in_city = (...args) =&amp;gt; args.length ? true : false;&lt;br /&gt;
    }&lt;br /&gt;
    const configs = mw.config.get([&amp;quot;wgUserGroups&amp;quot;, &amp;quot;wgUserLanguage&amp;quot;]);&lt;br /&gt;
    functions.in_group = (...groups) =&amp;gt; groups.some(group =&amp;gt; configs.wgUserGroups.includes(group));&lt;br /&gt;
    functions.in_group_every = (...groups) =&amp;gt; groups.every(group =&amp;gt; configs.wgUserGroups.includes(group));&lt;br /&gt;
    functions.in_lang = (...useLangs) =&amp;gt; useLangs.includes(configs.wgUserLanguage);&lt;br /&gt;
&lt;br /&gt;
    // 不帶參數&lt;br /&gt;
    // 錯誤示範：&lt;br /&gt;
    // functions.is_anon = mw.user.isAnon; // 不安全，無法確定 mw.user.isAnon 是否有被修改過可以傳奇怪的值進去&lt;br /&gt;
    // functions.is_anon = () =&amp;gt; mw.user.isAnon(); // 不安全，返回值為 boolean 的，只要無法保證一定返回 boolean，就應該全部強制轉換成 boolean&lt;br /&gt;
    functions.is_anon = () =&amp;gt; !!mw.user.isAnon();&lt;br /&gt;
    // 支持较旧的 MediaWiki 版本（通常是其他维基）&lt;br /&gt;
    // mw.user.isTemp 和 mw.user.isNamed 在 MediaWiki 1.40 中添加&lt;br /&gt;
    functions.is_temp = () =&amp;gt; typeof mw.user.isTemp === &amp;quot;function&amp;quot; ? !!mw.user.isTemp() : false;&lt;br /&gt;
    functions.is_named = () =&amp;gt; typeof mw.user.isNamed === &amp;quot;function&amp;quot; ? !!mw.user.isNamed() : !mw.user.isAnon();&lt;br /&gt;
&lt;br /&gt;
    const parser = new CriteriaExecutor(functions);&lt;br /&gt;
&lt;br /&gt;
    const cache = new WeakMap();&lt;br /&gt;
    function getCache($element, key) {&lt;br /&gt;
        const element = $element.get(0);&lt;br /&gt;
        if (cache.has(element)) {&lt;br /&gt;
            return cache.get(element)[key];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    function setCache($element, key, value) {&lt;br /&gt;
        const element = $element.get(0);&lt;br /&gt;
        if (cache.has(element)) {&lt;br /&gt;
            cache.get(element)[key] = value;&lt;br /&gt;
        } else {&lt;br /&gt;
            cache.set(element, {&lt;br /&gt;
                [key]: value,&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function matchCriteria($noticeItem) {&lt;br /&gt;
        let cache = getCache($noticeItem, &amp;quot;asn-cache&amp;quot;);&lt;br /&gt;
        if (cache !== undefined) {&lt;br /&gt;
            return cache;&lt;br /&gt;
        }&lt;br /&gt;
        let criteria = $noticeItem.attr(&amp;quot;data-asn-criteria&amp;quot;);&lt;br /&gt;
        let result;&lt;br /&gt;
        if (criteria !== undefined) {&lt;br /&gt;
            if (criteria === &amp;quot;&amp;quot;) {&lt;br /&gt;
                result = true;&lt;br /&gt;
            } else {&lt;br /&gt;
                try {&lt;br /&gt;
                    criteria = decodeURIComponent(criteria.replace(/\+/g, &amp;quot;%20&amp;quot;)).trim();&lt;br /&gt;
                    const ast = parser.toAst(criteria);&lt;br /&gt;
                    result = !!parser.evaluate(ast);&lt;br /&gt;
                } catch (error) {&lt;br /&gt;
                    console.warn(&lt;br /&gt;
                        &amp;#039;[AdvancedSiteNotices]: Fail to parse or evaluate criteria &amp;quot;%s&amp;quot;:&amp;#039;,&lt;br /&gt;
                        criteria,&lt;br /&gt;
                        error&lt;br /&gt;
                    );&lt;br /&gt;
                    result = false;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            const testList = [];&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;only_sysop&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.in_group(&amp;quot;sysop&amp;quot;));&lt;br /&gt;
            }&lt;br /&gt;
            if (&lt;br /&gt;
                $noticeItem.hasClass(&amp;quot;only_logged_in&amp;quot;) ||&lt;br /&gt;
                $noticeItem.hasClass(&amp;quot;only_logged&amp;quot;) /* 已弃用 */ ||&lt;br /&gt;
                $noticeItem.hasClass(&amp;quot;is_named&amp;quot;)&lt;br /&gt;
            ) {&lt;br /&gt;
                testList.push(functions.is_named());&lt;br /&gt;
            }&lt;br /&gt;
            if (&lt;br /&gt;
                $noticeItem.hasClass(&amp;quot;only_logged_out&amp;quot;) ||&lt;br /&gt;
            	$noticeItem.hasClass(&amp;quot;only_anon&amp;quot;) /* 已弃用 */&lt;br /&gt;
            ) {&lt;br /&gt;
                testList.push(!functions.is_named());&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;is_temp&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.is_temp());&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;is_anon&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.is_anon());&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;only_zh_cn&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.in_lang(&amp;quot;zh-cn&amp;quot;));&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;only_zh_hk&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.in_lang(&amp;quot;zh-hk&amp;quot;));&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;only_zh_sg&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.in_lang(&amp;quot;zh-sg&amp;quot;));&lt;br /&gt;
            }&lt;br /&gt;
            if ($noticeItem.hasClass(&amp;quot;only_zh_tw&amp;quot;)) {&lt;br /&gt;
                testList.push(functions.in_lang(&amp;quot;zh-tw&amp;quot;));&lt;br /&gt;
            }&lt;br /&gt;
            result = !testList.length || testList.every((v) =&amp;gt; !!v);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        setCache($noticeItem, &amp;quot;asn-cache&amp;quot;, result);&lt;br /&gt;
        return result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function getNoticeElement($noticeItem) {&lt;br /&gt;
        let $cache = getCache($noticeItem, &amp;quot;asn-element&amp;quot;);&lt;br /&gt;
        if ($cache !== undefined) {&lt;br /&gt;
            return $cache;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $cache = $(&amp;quot;&amp;lt;div&amp;gt;&amp;quot;).append($noticeItem.contents().clone());&lt;br /&gt;
        setCache($noticeItem, &amp;quot;asn-element&amp;quot;, $cache);&lt;br /&gt;
        return $cache;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let isSetMinHeightCalled = false;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * 设置 ASN 的高度为所有条目的最大高度，以防止在切换时出现大量布局偏移。&lt;br /&gt;
     */&lt;br /&gt;
    function setMinHeight($noticeList) {&lt;br /&gt;
        let minHeight = -1;&lt;br /&gt;
        $noticeList.each((_, nt) =&amp;gt; {&lt;br /&gt;
            let $nt = $(nt);&lt;br /&gt;
            $asnBody.replaceWith($nt);&lt;br /&gt;
            minHeight = Math.max(minHeight, $nt.height());&lt;br /&gt;
            $nt.replaceWith($asnBody);&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        $asnRoot.css(&amp;quot;min-height&amp;quot;, `${minHeight}px`);&lt;br /&gt;
&lt;br /&gt;
        if (!isSetMinHeightCalled) {&lt;br /&gt;
            isSetMinHeightCalled = true;&lt;br /&gt;
            window.addEventListener(&lt;br /&gt;
                &amp;quot;resize&amp;quot;,&lt;br /&gt;
                mw.util.debounce(() =&amp;gt; setMinHeight($noticeList), 300)&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function loadNotice($noticeList, pos) {&lt;br /&gt;
        const $noticeItem = $noticeList.eq(pos);&lt;br /&gt;
        let nextPos = pos + 1;&lt;br /&gt;
        if (nextPos === $noticeList.length) {&lt;br /&gt;
            nextPos = 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        const $noticeElement = getNoticeElement($noticeItem);&lt;br /&gt;
        if ($asnBody.children().length) {&lt;br /&gt;
            $asnBody.stop().fadeOut(() =&amp;gt; {&lt;br /&gt;
                $asnBody.empty().append($noticeElement);&lt;br /&gt;
                // 动画 try/catch 以避免 TypeError: (Animation.tweeners[prop]||[]).concat is not a function 错误在生产环境中出现&lt;br /&gt;
                try {&lt;br /&gt;
                    $asnBody.fadeIn();&lt;br /&gt;
                } catch (_) { }&lt;br /&gt;
            });&lt;br /&gt;
        } else {&lt;br /&gt;
            $asnBody.append($noticeElement).fadeIn();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($noticeList.length &amp;gt; 1) {&lt;br /&gt;
            timeoutId = setTimeout(() =&amp;gt; {&lt;br /&gt;
                loadNotice($noticeList, nextPos);&lt;br /&gt;
            }, customASNInterval * 1000);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function initialNotices($noticeList) {&lt;br /&gt;
        if (!$asnRoot.length || !$noticeList.length || revisionId === cookieVal) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        mw.cookie.set(COOKIE_NAME, null);&lt;br /&gt;
        $asnRoot.appendTo($(&amp;quot;#siteNotice&amp;quot;));&lt;br /&gt;
        setMinHeight($noticeList);&lt;br /&gt;
&lt;br /&gt;
        loadNotice($noticeList, Math.floor(Math.random() * $noticeList.length));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    new mw.Api({&lt;br /&gt;
        ajax: {&lt;br /&gt;
            headers: {&lt;br /&gt;
                &amp;quot;Api-User-Agent&amp;quot;: &amp;quot;w:zh:MediaWiki:Gadget-AdvancedSiteNotices.js&amp;quot;,&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    })&lt;br /&gt;
        .parse(new mw.Title(&amp;quot;Template:AdvancedSiteNotices/ajax&amp;quot;), {&lt;br /&gt;
            variant: mw.config.get(&amp;quot;wgUserVariant&amp;quot;),&lt;br /&gt;
            maxage: 3600,&lt;br /&gt;
            smaxage: 3600,&lt;br /&gt;
        })&lt;br /&gt;
        .then((html) =&amp;gt; {&lt;br /&gt;
            let $json = $(&amp;quot;ul.sitents&amp;quot;, $.parseHTML(html));&lt;br /&gt;
            let $noticeList = $(&amp;quot;li&amp;quot;, $json).filter((_, li) =&amp;gt; matchCriteria($(li)));&lt;br /&gt;
            revisionId = $json.data(&amp;quot;asn-version&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            initialNotices($noticeList);&lt;br /&gt;
        })&lt;br /&gt;
        .catch((e) =&amp;gt; {&lt;br /&gt;
            console.error(&amp;quot;[AdvancedSiteNotices]: error &amp;quot;, e);&lt;br /&gt;
        });&lt;br /&gt;
});&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>鹿野耕云</name></author>
	</entry>
</feed>