字数:31190
Listpage如同盛夏里的飞虫,在网站上无处不在。正如同Croquembouche 在他的Listpages 魔法与你中写下的那样——
有的时候,有人看见了一个 SCP 运用了 ListPages,想要模仿一样的效果,于是在提问区里面求助。有的时候,有人想要知道如何去做一些特别的事情,而回答便是 ListPages。而有的时候,有人在你的页面下面留言,说你应该用一个 ListPages。
事实上,当你希望获取来自站点上其它页面的信息,然后将其以某种方式筛选并展示的时候,Listpage几乎总是你的首选;当你希望在你的页面中做出一些比较有趣的展示效果的时候,Listpage有时也能够以一种相对于html/Javascript来说更简便,更易于实行的方式实现你的需求。(至于css,很抱歉这个躲不掉。)
目前为止,在我们的网站上与Listpage使用方法相关的文章主要有三篇。除了上面提到的Listpages 魔法与你以外,还有由中文分部的fuban 撰写的常用Module(ListPages與ListUsers)簡易教學以及由日文分部的physicslike 撰写的单页迭代教程。当然,如果你完全没有阅读过这三篇文章中的任何一篇也完全没有关系——这篇文章的目的便是尽可能解决理论与应用之间的隔阂,或者说,告诉你"这些东西是可以用Listpage实现的,并且它背后的原理正是如此"。
那么,在进入正题之前,最后一句忠告:当你有什么不明白的地方,去读文档read the docs总是没有错的。
请先登录账号再阅览以下内容,谢谢配合!
1.Listpage基本用法介绍——以作者页作品列表为例
一个完整的作者页应该包含哪些内容?对于这个问题,每个人都有自己不同的看法。但是,最基础的要求是:你必须在作者页中提供一个你在网站上投稿作品的列表,并提供指向作品的链接。尽管有许多人坚持手动维护这个列表,但是事实上,这一点可以用下面的Listpage代码轻易做到:
[[module ListPages created_by="你的用户名" separate="no"]]
* %%title_linked%%
[[/module]]
它的展示效果是这样的:
由于您暂时没有在网站上发布作品,所以这里用笔者的作品列表举例。
它看起来像这样:
这种写法简单明了:module ListPages用以告诉wikidot你调用的是一个叫做ListPages的预设模块——我不想在这里花三行字和三个blockquote来解释这是个什么玩意。跟在这后面的内容是ListPages的模块参数:created_by=是用以筛选页面创建者的参数,separate="no"则是为了页面美观,我们会在后面再来讲这个。
当然,如果你需要将你的作品按照其类别分开进行统计,就需要使用tags=与category=这两个参数。下面的表格中给出了想要筛选出几种常用的文章类别所需要使用的参数预设:
分类 | 参数预设 |
---|---|
原创 | tags="+原创" category="-deleted" |
非作者页翻译 | tags="-原创 -作者 -补充材料" category="-deleted -fragment -log-of-anomalous-items-cn -short-stories" |
(原创)SCP文档 | tags="+原创 +scp" category="-deleted" |
故事 | tags="+原创 +故事" category="-deleted" |
GOI格式 | tags="+原创 +goi格式" category="-deleted" |
图书馆作品 | tags="+原创 +wanderers" category="-deleted" |
艺术作品 | tags="+原创 +艺术作品" category="-deleted" |
其它原创作品(版式、文章等) | tags="+原创 -scp -故事 -goi格式 -wanderers -艺术作品" category="-deleted" |
异常物品记录与三句话外围 | category="log-of-anomalous-items-cn short-stories" |
搞定了筛选之后,往往会有将筛选出的内容以指定方式排序的需求。例如:SCP文档按照编号排序可能看上去更加整齐,故事需要按照长度排序,而在作者页里搭建的私人竞赛排行榜可能会有以评分倒序排序的需求。当你没有指定排序方式参数order=的时候,Listpages的默认排序方式是按照发布时间倒序排序。下面的表格中给出了几种常用的排序方法及其参数预设,需要完整列表请参见文档。
排序方法 | 参数预设 |
---|---|
评分倒序 | order="rating desc" |
发布时间正序 | order="created_at" |
页面标题正序 | order="title" |
页面名正序 | order="name" |
内容字数正序 | order="size" |
随机顺序 | order="random" |
好,接着让我们测试一下上面的代码——比如,筛选出你的所有原创SCP,然后按照页面名正序排序。它的代码显然应该是这样的:
[[module ListPages created_by="你的用户名" order="name" tags="+原创 +scp" category="-deleted" separate="no"]]
* %%title_linked%%
[[/module]]
考虑到你暂时还没有在网站上创作并发布过原创SCP文档。这里同样选用笔者的作品进行展示:
好的,现在我们已经搞定了模版参数部分(不要管separate=,那玩意还要再靠后一点儿),该进入展示效果部分了。显然,只为每个作品展示其标题以及前往这个作品的链接尽管满足了要求,但是它看起来可能会有那么一点低级。你也许会希望再展示一些这篇文章的其他信息,比如文章的创建时间、最后更新时间、标签、字数以及最重要的——评分和评论数。这些内容都可以使用Listpages模块的内置可调用变量实现。下面的表格中给出了几个常用的变量及其变量名,需要完整列表请参见文档。
变量名 | 变量含义 |
---|---|
%%created_by%% | 页面创建者,即作者(之一)。 |
%%created_at%% | 页面创建日期。 |
%%updated_at%% | 页面最后更新日期。 |
%%title_linked%% | 页面标题,附带一个前往页面的链接。 |
%%content%% | 页面完整内容。 |
%%content{n}%% | 页面第n部分的完整内容。 |
%%tags%% | 页面的所有非隐藏标签。 |
%%children%% | 页面的子页面数量。 |
%%comments%% | 页面的评论数。 |
%%size%% | 页面的统计大小。 |
%%rating%% | 页面的当前评分。 |
%%rating_votes%% | 页面的总计评分人数。 |
%%index%% | 在所有被筛选出的页面中,该页面在当前排序方式下的顺位。 |
%%total%% | 被筛选出的页面总数。 |
日期变量细化格式
Listpage格式抓取的日期变量(例如%%created_at%%)支持使用
%%日期变量|展示格式%%
以自定义日期变量的展示形式。展示格式中支持的部分参数列举如下:
变量名 | 变量含义 | 示例 |
---|---|---|
%y/%Y | 年份 | 21 Jan 2025 08:21/21 Jan 2025 08:21 |
%m/%b/%B | 月份 | 21 Jan 2025 08:21/21 Jan 2025 08:21/21 Jan 2025 08:21 |
%d/%e | 一月中的天数 | 21 Jan 2025 08:21/21 Jan 2025 08:21 |
%a/%A | 一周中的天数 | 21 Jan 2025 08:21/21 Jan 2025 08:21 |
%H/%I | 小时(24/12时制) | 21 Jan 2025 08:21/21 Jan 2025 08:21 |
%p | 上午/下午 | 21 Jan 2025 08:21 |
%z | 时区 | 21 Jan 2025 08:21 |
%M | 分钟 | 21 Jan 2025 08:21 |
%S | 秒 | 21 Jan 2025 08:21 |
如果将上述代码改为%%日期变量|展示格式|agohover%%,就会在鼠标移动到日期上之后显示该日期至今的间隔时间。
希望了解更多内容可参见这里。
你可以很轻松地用这些变量中的一部分组合成一个可用的展示单元。例如下面这样:
[[module ListPages created_by="你的用户名" separate="no"]]
**%%title_linked%%**[+%%rating%%]
{{**创建于:**%%created_at%%}}
{{**标签:**%%tags%%}}
{{**字符数:**%%size%%}}
[[/module]]
SCP-2825 [+0]
创建于:13 Oct 2025 12:19
标签:euclid scp 活物 生物危害
字符数:4044
基金会世界观倾向自测系统(AST-MT)(爱蒂塔归档) [+82]
创建于:01 Oct 2025 04:00
标签:2025新秀竞赛 互动性 原创 合著 故事 爱蒂塔计划
字符数:29804
表达式结构
表达式结构主要被用于实现一些相对来说较为复杂的功能。常用的表达式结构有#if、#expr与#ifexpr三种。其语法如下:
[[#if 值 | 值为真时展示内容 | 值为假时展示内容 ]]
输出结果为值对应的展示内容。
[[#expr 表达式]]
输出结果为表达式运算后得出的值。
[[#ifexpr 表达式 | 表达式为真时展示内容 | 表达式为假时展示内容 ]]
输出结果为表达式运算结果对应的展示内容。
此处的假值包括字符串"false"、字符串"null"、空字符串与数字0。而表达式可以是一个算术表达式,也可以是一个返回字符串true或false的布尔表达式。表达式中支持基础的+、-、*、/、%等四则运算符,括号嵌套,>、=、<等比较运算符,以及三个预制的函数:绝对值函数abs()、最大值函数max()与最小值函数min()。
如果需要了解更多信息,请参阅官方文档。
但是,当你打算让Listpages模块展示一些在变量列表里无法直接获取到的信息的时候,事情就变得麻烦起来了。在这之中,最流行的一种展示内容是在评分上做文章——比如,展示upvote与downvote的具体数量,展示upvote率,根据阈值为评分值染色,甚至是根据upvote率制作一个酷炫的评分条。而这就要求我们利用表达式结构,使用Listpages模块提供的少数变量进行计算。
Listpages提供的与评分相关的变量有两个:%%rating%%是页面的当前评分,记为R,%%rating_votes%%是页面的总计评分人数,记为T。显而易见地,upvote数与downvote数可以通过下面的公式计算得出:
(1)此时,尽管upvote率可以简单通过U/T计算,但是由于wikidot没有将一个浮点数保留到小数点后X位的函数,因此为了美观,一般选择使用下面这个公式将其保留至小数点后两位:
(3)因此,如果你想在Listpages的单个模块内部实现[评分 (+正票/-负票,uv率)]这一格式,下面的这段代码就能做到这一点:
[%%rating%% (+[[#expr (%%rating_votes%%+%%rating%%)/2]]/-[[#expr (%%rating_votes%%-%%rating%%)/2]],[[#expr (%%rating_votes%%+%%rating%%)/2/%%rating_votes%%*10000%10001/100]]%)]
当然,表达式结构还能做到一些其他事情。例如:如果我希望在字数超过2750的时候将字数部分标红,反之则标为绿色,可以用如下的代码实现:
**字符数:**##[[#ifexpr %%size%% > 2750 | red | green]]|%%size%%##
下面我们将这两段代码融入上面的示例之中,其展示效果如下:
SCP-2825 [0 (+0/-0,run-time error: division by zero%)]
创建于:13 Oct 2025 12:19
标签:euclid scp 活物 生物危害
字符数:4044
基金会世界观倾向自测系统(AST-MT)(爱蒂塔归档) [82 (+83/-1,98.8%)]
创建于:01 Oct 2025 04:00
标签:2025新秀竞赛 互动性 原创 合著 故事 爱蒂塔计划
字符数:29804
文章部分划分
你可通过十七个等于号"================="将文章划分为两个不同的部分。这种划分不会对文章的内容带来任何显示上的改变,但是你可以使用Listpages模块的%%content{n}%%变量对文章的不同部分进行分别抓取。
一个简单的划分示意如下:
content{1}
====
content{2}
====
content{3}
====
content{4}
另外,需要注意的是,content{0}的内容永远为空字符串。
效果很好,是吧?但这还不够。有的时候,你可能会希望Listpage组件能够抓取一段由你精心挑选的风味文本展示在作者页,这时,我们就要利用到前面提到的%%content{n}%%参数了。
你可以在你需要被Listpages模块抓取的文章开头添加如下这段代码:
[!--
====
你想要的风味文本
====
--]
这段代码中的[!-- --]是注释标记,也就是说,当你渲染主页面的时候,这一整段内容都会被"注释"掉从而不会影响页面原始代码的展示效果。
但是当你使用Listpages模块抓取这一页面的第二部分,即%%content{2}%%时,它抓取到的内容仅仅只会是被两条分段线包裹的"你想要的风味文本",而不包括前后的注释标记。因此,只需要通过这种方式,就能实现风味文本的自动抓取。
以下,我使用这一篇文档本身作为示例,展示抓取风味文本的效果。你可以在完成阅读后点击查看源代码检查内置风味文本部分的实现方式。
[[module ListPages range="." wrapper="no" separate="no"]]
----
%%content{2}%%
----
[[/module]]
这里是preview!
最后,让我们回到相对来说比较简单的一个部分——Listpages的展示方式控制。影响展示方式的主要参数有四个:offset=、limit=、separate=与wrapper=。前两者与展示的具体内容有关,后两者则与展示的样式有关。
如果你的原创文章超过10篇的话,你可能已经注意到了:在这一部分最开始的那个Listpages模块里,只展示了其中最新发布的10篇。这便是limit的功劳——limit=10可以只让模块展示当前排序方式下展示顺位1~10的页面,而剩下的部分将被隐藏。还有一个与此类似的参数perPage=,但是在仅设置这个参数的时候,模块仍然会展示全部满足筛选条件的文章,而仅仅将单页上展示的页面数量限制到了设置的数值。
offset=则代表偏移量。举个简单的例子:当limit=10 offset=2的时候,模块展示的内容就是当前排序方式下顺位为3~12的页面。这一个参数在迭代中被频繁使用,但是这是第二部分的内容,此处暂且按下不讲。
默认生成结构
[[div class="list-pages-box"]]
[[div class="list-pages-item"]]
内容1
[[/div]]
[[div class="list-pages-item"]]
内容2
[[/div]]
......
[[/div]]
wrapper=与separate=这两个参数分别控制Listpages模块生成结构的外部div和内部div。它们的缺省值是"yes"。当wrapper="no"时,将不会在编译时添加list-pages-box这一div块,当separate="no"时,则不会添加list-pages-item这一div块。正常来说,当你的展示内容仅为单行,或是你自己用了一个div块把展示内容包起来的时候,separate="no"的展示效果总会更好一些,反之,separate="yes"的展示效果会更好。而wrapper=对展示效果的影响一般并不太大。
在初步了解Listpages生成结构后,我们便可以对其展示样式进行一定的调整。例如,下面的代码可以实现双列视图显示:
[[module css]]
.list2 {
display: grid;
grid-template-columns: repeat(2, 1fr); /*双列显示*/
}
@media only screen and (max-width: 1020px) { /*下面为移动端适配:*/
.list2 {grid-template-columns: 1fr;} /*单列显示*/
}
[[/module]]
[[div class="list2"]]
[[module ListPages created_by="你的用户名" limit="4" wrapper="no" separate="yes"]]
**%%title_linked%%** [+%%rating%%]
{{**创建于:**%%created_at%%}}
{{**标签:**%%tags%%}}
{{**字符数:**%%size%%}}
[[/module]]
[[/div]]
SCP-2825 [+0]
创建于:13 Oct 2025 12:19
标签:euclid scp 活物 生物危害
字符数:4044
SCP-891-JP [+1]
创建于:13 Oct 2025 11:54
标签:jp safe scp 建筑 肢体 自主
字符数:1074
SCP-8119 [+1]
创建于:13 Oct 2025 11:27
标签:are-we-cool-yet kondraki博士 safe scp 工具 心灵感应 摄像 视觉性
字符数:11874
‘帝伦黛丝®’(F3B3R/X44NM/PLL77) [+0]
创建于:13 Oct 2025 09:34
标签:goi格式 mc&d percival-darke ruprecht-carter 亿万黑钻 企业性 悲剧 政治性
字符数:13779
基金会世界观倾向自测系统(AST-MT)(爱蒂塔归档) [+82]
创建于:01 Oct 2025 04:00
标签:2025新秀竞赛 互动性 原创 合著 故事 爱蒂塔计划
字符数:29804
SCP 9000 — 阿斯忒里翁之屋 [+7]
创建于:20 Sep 2025 13:24
标签:9000 keter meta scp 人工智能 神话小说 超现实小说
字符数:18690
SCP-CN-1064 [+39]
创建于:11 Aug 2025 16:55
标签:keter meta scp 原创 合著 悖论 电子 电脑 线上 预测性
字符数:10266
屎山雕花魔法与你:基于Wikidot原生语法的切换式按钮实现 [+60]
创建于:03 Aug 2025 08:56
标签:原创 文章
字符数:17926
当然,CSS部分并不是本篇文章的重点——如果想要知道这玩意为什么能够工作,建议去网上搜索并阅读一些更专业的CSS代码教程。那么,接下来,我们将会进入与所有人都息息相关,也相对更困难的第二部分:迭代。
2.条条大路通迭代
传统的Listpages迭代早已是老生常谈。让我们回顾一下这类Listpages迭代的创建步骤吧:
1. 创建主页面。在其中填入下面这段代码:
所有迭代之上相同的部分
[[module ListPages category="fragment" parent="." limit="1" order="created_at" offset="@URL|0"]]
%%content%%
[[/module]]
所有迭代之下相同的部分
2. 按迭代的进行顺序创建所需的,位于fragment:分类下的子页面,你需要将其父页面设置为第1步中创建的主页面,并添加段落标签。
3. 填充迭代页内容。去往其它迭代页的链接将是主页面链接/offset/0~n。
第一类迭代的原理
根据我们在第一部分中了解到的相关知识,此处的category="fragment" parent="."起到了筛选的作用,它们筛选出了父页面为本页面的,分类为fragment:的所有页面,limit="1"代表这个Listpages模块一次只会展示其中一个页面的%%content%%变量值,即对应页面内的全部内容。offset="@URL|0"是个新东西——它代表这个Listpage模块会从页面的链接里读取offset参数,而当页面链接里不包含这一部分信息的时候,就会取缺省值0。
现在,你可以试着查看这个页面的链接:在它的原始链接之后,跟着offset/1/created_by/你的用户名。也就是说,如果我在这个页面中出现的某个Listpages模块中将offset参数设为@URL,它的值就会取到链接中的1。同理,如果某个模块的created_by参数是@URL,那么它的值就会取到你的用户名——如果你在网站上创建过一些页面,你就会发现第一部分的那些示例都是用你的作品展示的,这就是@URL的一个有趣应用。
现在,让我们回到第一类迭代。这一类迭代通过调整偏移量使仅抓取一个页面的展示模块得以"抓取"到筛选出页面中的不同页面。而如果将Listpages的抓取内容改成来自本页面的%%content{n}%%,我们就可以得到第一类迭代的单页迭代实现形式:
所有迭代之上相同的部分
[!--
====
第1迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page2_limit/1 第2迭代的链接]
====
第2迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page3_limit/1 第3迭代的链接]
====
第3迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称 第1迭代的链接]
====
--]
[[module ListPages offset="@URL|0" range="."]]
%%content{2}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page2"]]
%%content{3}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page3"]]
%%content{4}%%
[[/module]]
所有迭代之下相同的部分
所有迭代之上相同的部分
[[module ListPages offset="@URL|0" range="."]]
第1迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page2_limit/1 第2迭代的链接]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page2"]]
第2迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page3_limit/1 第3迭代的链接]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page3"]]
第3迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称 第1迭代的链接]
[[/module]]
所有迭代之下相同的部分
[[module css]]
.listpart {display:none;}
[[/module]]
所有迭代之上相同的部分
[[div class="listpart page1"]]
第1迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page2_limit/1 第2迭代的链接]
[[/div]]
[[div class="listpart page2"]]
第2迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page3_limit/1 第3迭代的链接]
[[/div]]
[[div class="listpart page3"]]
第3迭代的文本
[https://scp-wiki-cn.wikidot.com/页面名称 第1迭代的链接]
[[/div]]
所有迭代之下相同的部分
[[module ListPages offset="@URL|0" range="."]]
[[%%content{0}%%module css]]
.listpart.page1 {display:block;}
额外的CSS代码,下同
[[%%content{0}%%/module]]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page2"]]
[[%%content{0}%%module css]]
.listpart.page2 {display:block;}
[[%%content{0}%%/module]]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page3"]]
[[%%content{0}%%module css]]
.listpart.page3 {display:block;}
[[%%content{0}%%/module]]
[[/module]]
这里的三个格式在展示效果上差别不大,唯一的区别是第一种可以直接在文本里添加module css模块,第二种则由于老生常谈的module嵌套问题,需要使用这一代码替代:
[[%%content{0}%%module css]]
你需要的css代码
[[%%content{0}%%/module]]
第三种格式中就应用了上面的这一段代码。这一种格式相比于前两者的优势是可以在迭代部分中加入其它的Listpages模块,但劣势是这种格式事实上只是将其中的一部分内容在视觉上隐藏了起来,该加载的还是会加载。也就是说,如果你想用这种格式修改CSS,仍然需要将这一部分内容写在Listpages模块的内部。
在抓取第1迭代的Listpages模块中,在range=".",也就是仅抓取本页面一个页面的基础上,添加了一段offset="@URL|0"的偏移值筛选。这代表着当我们通过链接为offset赋值之后,这一模块就会抓取到一个空值——你会发现前往后续迭代的页面连接中包含了一个offset/1,这就是在第二与第三迭代中隐藏第一迭代的原理。
在抓取后续迭代的Listpages模块中,出现了一个新参数,即urlAttrPrefix="XXX"。以上面的代码为例,附加了这个参数的Listpages模块在设置为limit="@URL|0"之后,就可以从XXX_limit/1中读取到这个参数。这个方式可以仅为某一个特定的Listpages模块传递参数,从而实现单页第一类迭代的一次仅显示一个页面的需求。
如果你希望扩展迭代页的话,你需要复制代码中用等宽字表示的模块化组件,然后将它们的参数按照规律修改——我相信你能做对。
当然,有的时候你并不希望在一次阅读中向读者展示全部内容,而是将一切交予命运——比如著名的001提案 - Keter任务以及SCP-1893,我们将这种形式称作第二类迭代。第二类迭代可以用下面的这段代码实现:
第二类迭代的原理
所有迭代之上相同的部分
[[module ListPages category="fragment" parent="." limit="1" order="random"]]
%%content%%
[[/module]]
所有迭代之下相同的部分
第二类迭代的特点是每一次刷新后页面的内容都会产生随机的变化,同时页面中一般无需提供前往其他"迭代页"的链接。其原理便是Listpages的随机排序以及限制抓取页数为1后实现的单页抽选。这个功能同样可以在单页迭代中实现,但需要用到一些JavaScript知识——所以我把这些烦人的东西都藏到折叠里面去了,需要请自取。
此外,单页迭代组件提供了一种无需使用html即可调用单页随机迭代的方案,可以直接复制使用。
所有迭代之上相同的部分
[!--
====
[[html]]
<script type="text/javascript">
window.onload = function(){
var rand = Math.floor( Math.random() * 3 );
var linkA = "https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page";
var linkB = "_limit/1";
parent.location.href = linkA + rand + linkB;
}
</script>
[[/html]]
[[module css]]
*{display: none;} /* 这一部分代码用以在跳转时隐藏页面元素,改善阅读体验 */
[[/module]]
====
第1迭代的文本
====
第2迭代的文本
====
第3迭代的文本
====
--]
[[module ListPages offset="@URL|0" range="."]]
%%content{2}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page0"]]
%%content{3}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page1"]]
%%content{4}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page2"]]
%%content{5}%%
[[/module]]
所有迭代之下相同的部分
如果你需要调整迭代数目的话,需要将JavaScript里的那个加粗的3更改为你所需的迭代数量,然后像第一类迭代一样复制以等宽字展示的模块化组件。记得更改linkA里面的链接为你的页面!
在第二类迭代的基础上,如果我们将Listpages模块的limit限制上调到与子页面的数量相等,就实现了第三类迭代。这种迭代的展现效果类似图竞的"灵感卡片"——每当你刷新页面,文章中的一些文段都会随机变换位置,从而带来全新的阅读体验。SCP-8118和SCP-CN-3797都使用了这个技巧。它的代码实现如下:
第三类迭代的原理
所有迭代之上相同的部分
[[module ListPages category="fragment" parent="." limit="n" order="random"]]
%%content%%
[[/module]]
所有迭代之下相同的部分
顺带一提,尽管这种迭代类型同样有其单页迭代的实现形式,但它的代码复杂程度可能有些不太友好。我把它的一个实例藏在了下面的折叠里面,如果你想看的话,那就去看吧!
所有迭代之上相同的部分
[[module css]]
.iter {display:none;}
[[/module]]
[!--
====
[[html]]
<script type="text/javascript">
window.onload = function(){
let arr = [1, 2, 3];
arr.sort(function() {
return 0.5 - Math.random();
});
var linkA = "https://scp-wiki-cn.wikidot.com/页面名称/offset/1/page10_limit/";
var linkB = "/page11_limit/";
var linkC = "/page12_limit/";
parent.location.href = linkA + arr[0] + linkB + arr[1] + linkC + arr[2];
}
</script>
[[/html]]
[[module css]]
*{display: none;}
[[/module]]
====
第1迭代的文本
====
第2迭代的文本
====
第3迭代的文本
====
--]
[[module ListPages offset="@URL|0" range="."]]
%%content{2}%%
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page10"]]
[[%%content{0}%%module css]]
.iter.p10%%limit%%{display:block;}
[[%%content{0}%%/module]]
[[div class="iter p101"]]
%%content{3}%%
[[/div]]
[[div class="iter p102"]]
%%content{4}%%
[[/div]]
[[div class="iter p103"]]
%%content{5}%%
[[/div]]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page11"]]
[[%%content{0}%%module css]]
.iter.p11%%limit%%{display:block;}
[[%%content{0}%%/module]]
[[div class="iter p111"]]
%%content{3}%%
[[/div]]
[[div class="iter p112"]]
%%content{4}%%
[[/div]]
[[div class="iter p113"]]
%%content{5}%%
[[/div]]
[[/module]]
[[module ListPages limit="@URL|0" range="." urlAttrPrefix="page12"]]
[[%%content{0}%%module css]]
.iter.p12%%limit%%{display:block;}
[[%%content{0}%%/module]]
[[div class="iter p121"]]
%%content{3}%%
[[/div]]
[[div class="iter p122"]]
%%content{4}%%
[[/div]]
[[div class="iter p123"]]
%%content{5}%%
[[/div]]
[[/module]]
所有迭代之下相同的部分
用这种方式实现的第三类迭代的劣势显而易见:它的代码有点太复杂了。但是比起使用传统的Listpages+子页面实现的迭代形式,它又有其独有的优势,也就是你可以将每个单独的Listpages模块放到文章的不同位置,并在中间任意插入内容,而不要求这些文段必须在你的文章中彼此相邻。这显然比传统的第三类迭代更具泛用性。
最后,我不是很想解释这玩意的工作原理——如果你确实有使用它的需求又有扩展上的困难的话,通过wikidot或者即时聊天软件私信我都没有问题。
3.强强联合——基于Listpages与Listusers的用户筛选技术
如果说Listpages是盛夏里的飞虫,那么Listusers就是你在林荫道上散步的时候突然从树上掉到你头上的臭虫:你冷不丁就会在某一篇文章中看到你自己的用户名出现在一个奇妙的地方,而你似乎刚刚庄严宣誓了"控制,收容,保护",或是花费了15分钟无意义的时间和O5议会斗智斗勇斗嘴——伙计们,该把Listusers用在一些更有价值的地方了。
ListUsers模块
Listusers看起来像一个没有做完的功能——它完全不能调整参数,却需要你输入一个预设好的唯一参数。它的语法如下:
[[module ListUsers users="."]]
你的UID是%%number%%,%%title%%(%%name%%)!
[[/module]]
Listusers模块支持调用下面三个参数:
- %%number%%:用户的UID。
- %%title%%:用户的展示名,带有非法符号。
- %%name%%:用户的内部名,与%%title%%的区别是它将非法字符替换成了"-",并把所有字母变成小写。
上面那段代码的展示效果如下:
如果希望了解更多信息,可以参考文档。
由于未登录用户查看页面时,wikidot无法解析Listusers模块内部的内容,因此,下面的这段代码可以让你的页面为登录用户与未登录用户分别展示不同的内容:
[[module css]]
.textchange .sitemember:nth-child(2) {display:none;}
[[/module]]
[[div class="textchange"]]
[[module ListUsers users="."]]
[[div class="sitemember"]]
对已登录用户展示的内容
[[/div]]
[[/module]]
[[div class="sitemember"]]
对未登录用户展示的内容
[[/div]]
[[/div]]
还记得这个页面最开始的那个跳转链接吗?如果你没有登陆的话,那里会是一个指向wikidot账号登陆页面的链接。这段代码在站点上有一个可以直接调用的相关组件,你可以在这里找到。
然后,让我们更进一步:你可以使用下面的这段代码让你页面中的一部分内容不对或仅对某一名或某几名特定用户展示。
[[module css]]
.show {display: none;}
.show.nXXXXXXX {display: block;}
.hide.nXXXXXXX {display: none;}
[[/module]]
[[module Listusers users="."]]
[[div class="hide n%%number%%"]]
这里填写你需要对指定用户隐藏的内容
[[/div]]
[[div class="show n%%number%%"]]
这里填写你需要对指定用户展示的内容
[[/div]]
[[/module]]
上面这段代码中的XXXXXXX是你希望隐藏/展示的用户的UID:这段代码也可以使用通过%%name%%获取的内部名进行替代,此时XXXXXXX即为那名用户的内部名。展示名是不可用的,因为你永远不知道一个用户的展示名里面会有几个空格。
你可以通过这个页面了解获取一名用户UID的方法。
此外,利用Listusers可以实现"某种意义上"的单页随机迭代。这一方法最初见于Site-69的第十四迭代,其原理是以用户的UID作为随机种子,从而为不同的用户展示不同的内容。其代码如下:
[[module Listusers users="."]]
前置的共同部分\
[[#ifexpr (%%number%% + 0) % 4==0 | 随机内容1 | ]]\
[[#ifexpr (%%number%% + 1) % 4==0 | 随机内容2 | ]]\
[[#ifexpr (%%number%% + 2) % 4==0 | 随机内容3 | ]]\
[[#ifexpr (%%number%% + 3) % 4==0 | 随机内容4 | ]]\
……
后置的共同部分
[[/module]]
代码中的\是维基语法中的代码换行标记,在句末添加该标记能够在链接前后两行内容时不添加额外的换行。下面是一个简单的范例:
[[module Listusers users="."]]
您的UID是%%number%%,为\
[[#ifexpr (%%number%% + 0) % 2==0 | 偶数 | ]]\
[[#ifexpr (%%number%% + 1) % 2==0 | 奇数 | ]]\
!
[[/module]]
在这一部分的最后,便是当Listusers与Listpages强强联合之后,真正神奇的魔法——你可以根据一个用户在网站上发布页面的统计数据来为他们展示不同的内容。你可以将它用在文章类型的页面中:如果你有一篇以搞笑的口吻介绍了网站上常见的糟糕写作方法的文章,却又不希望它被刚加入网站尝试写作的萌新奉为圭臬的话,这可能会很有用。
首先,你需要一个单页迭代让读你这篇文章的人主动提供自己的用户内部名——它可以看起来像这样:
[[module ListUsers users="."]]
[https://scp-wiki-cn.wikidot.com/页面名称/offset/1/created_by/%%name%% 这里是你可以自定义的链接文字]
[[/module]]
[[module ListPages offset="@URL|0" range="." ]]
[[%%content{0}%%module css]]
.hide {display:none;}
[[%%content{0}%%/module]]
[[/module]]
[[div class="hide"]]
包含筛选后展示内容的全部文段
[[/div]]
这些代码里的大部分我们都在前面介绍过了——事实上,这篇文章就用了这个技巧。还记得你开始时点的那个写着的按钮吗?它就是用来干这个的。
在这之后,假如说我们需要筛选出所有在网站上有作品,但不能只是三句话外围和异常物品记录的那一部分用户,为他们展示某一段内容,而为不满足条件的用户展示不同的内容,可以使用下面这段代码:
[[module css]]
.content1 {display:none;}
.content2 {display:block;}
[[/module]]
[[module ListPages created_by="@URL" limit="1" category="-log-of-anomalous-items-cn -short-stories"]]
[[%%content{0}%%module css]]
.content1.one {display:block;}
.content2.one {display:none;}
[[%%content{0}%%/module]]
[[/module]]
[[div class="content1 one"]]
为有作品用户展示的内容
[[/div]]
[[div class="content2 one"]]
为无作品用户展示的内容
[[/div]]
你可以翻到这篇文章的第一部分查看这段代码的实例:如果你在网站上有作品的话,第一处Listpages展示会显示你的作品,否则则会用笔者的作品列表进行替代。很好用,对吧?
如果你对这篇文章中的内容有任何问题,欢迎在评论区留言或通过各种途径联系笔者,即Sharia Vanilla 。
请按如下方式引用此页:
"Listpages:从入门到再次入门",作者 Sharia Vanilla,来自 SCP-CN 维基。原文链接:https://scp-wiki-cn.wikidot.com/listpages-entry-again。遵循 CC-BY-SA 协议。
更多详情请参阅授权指南。
授权信息
更多维基文档信息,请见版权信息总览。