学本教程,请保证拥有一定电脑基础和js基础
准备工作
首先,如果你需要一个拓展,你需要一个强有力的大脑。
咳咳,需要一个示例程序作为模板,在他的基础上进行修改。这里推荐FPS拓展,因为他的代码量是我写过(或者说整个ccw中)最少的。(只有366行)
要获取FPS拓展,请点击这里跳转对应网站,使用下载按钮下载这个文件:

下载按钮
如果你进去显示拒绝连接怎么办呢?
不用慌,距离成功你只差一个加速器,点我打开加速器官网,按照提示下载安装后勾选GitHub进行加速,这时再访问,多半就可以进去了,如果还进不去...那你还是放弃吧。
如果实在不行,可以在本文章末尾的代码块中找到FPS.js文件代码,复制粘贴到本地新建的js文件中。但是还是必须学会使用github,不然将会无法提交审核。
下载完毕后,让我们下载Visual Studio Code(以下简称VSC),一个强大却又轻松的编辑器。也是编写拓展最方便的编辑器。
首先,进入VSC的下载页,选择对应的系统版本下载。
下载后打开,第一次使用VSC的人可能会被英文的界面吓住,不用担心,只需点击拓展页:

拓展页
然后搜索“chinese”

中文语言
认准蓝标简体中文,安装!
重启VSC后,你的界面就会变成中文了。
接下来,让我们打开刚才下载的.js文件(使用VSC打开)
于是...你就得到了他:

FPS.js
看着一大堆乱码,可能有很多人都被唬住了,但是其实这些乱码是图片文件,都是系统生成的base64编码的文件,所以我们完全不需要看它,而是看下面的内容:

下面的内容
双语转换
大家是不是一眼就看见了“[beta]白猫的FPS”几个大字?
没错,当你需要用到双语转换时,就可以写在这里!
这段代码很好理解,就是在一个名为WitCatFPS(这里应当是你自己的拓展的ID)的类(class)中,有个constructor方法,会传入runtime参数。
而我们的变量定义就在这个方法中,这就类似于初始化了。
这个参数能干的事情有比如初始化变量,加载语言对照列表。

语言对照列表
使用过Not Js的人对json应该很熟悉吧,没错,这就是json结构。
zh-cn对应中文界面,en对应英文界面。key(键)就是内部用来获取文本内容的名字,命名一般使用“拓展ID.功能”。当然,你也可以自定义,但是如果要发布到ccw中,肯定是要规范命名的。
看完了双语转换的部分,让我们再来看看下面的内容

翻译
这段代码是默认的,不去动他就行了。
拓展信息/积木列表
再往下看,就有了getInfo方法。他会使用return返回一个数组。
这个数组的内容就是你拓展的所有信息了,比如你的拓展ID,拓展主/副色调,拓展名字,拓展图标/封面,拓展积木等

信息对照
这里的图标因为前两行已经定义了全局变量,所以这里就直接调用就行了。
再往下,就是一个名为“blocks”的数组了,这个数组决定了你的积木有哪些积木的顺序。他内部的json有三种写法:

按钮

单行文本

积木
首先,按钮,大家肯定都见过类似

按钮
这样的按钮吧,没错就是通过这个实现的。
在这个json里,blockType指定这个按钮的类型,目前我知道的就只有button,欢迎补充。
text顾名思义,就是显示按钮时上面显示的文字。但这里明显不是文字啊?
其实很简单,还记得我们之前双语转换提到的那个json吗,没错,这个this.formatMessage()的意思就是调用了我们上面写的双语信息,比如这里我调用了WitCatFPS.docs这个key对应的内容,他在中文下就会返回📖拓展教程,英文返回📖 Tutorial
下面的onClick就是这个按钮在按下时会触发的按钮,如果你使用过HTML的button标签的话,你应该知道,HTML中,button标签有一个属性叫onClick,通过他可以指定按下时触发的函数。
这就是按钮的全部内容了,如果你想找到更多示例,比如高级鼠标的上传ico转base64,高级画笔V2的上传图片都是使用的button。
接下来,就是单行文本的内容了。
单行文本很简单,就是使用“+”把“---”和一个双语文本连接起来。
接着,他就会显示你的双语文本的内容

单行文本
最后一种类型就是积木了,积木相信大家再也熟悉不过了。
一个正常的积木,一般有这几种类型

返回值

执行积木

布尔返回值

hat积木
定义积木类型的地方就是blockType,以下的他们的对应关系:
返回值:reporter
执行积木:command
布尔值:Boolean
hat:hat
有了积木的类型,接下来就是积木的文本内容了,积木的文本内容也可以通过text进行设定,也要通过双语文本进行设定,唯一的区别是,积木的文本会解析被“[]”(英文中括号)框起来的内容,我们可以称之为参数。
比如一个积木中的

菜单

输入值
都属于参数。
而被[]框起来的部分并不会直接展示给用户,这里面框起来的内容是你这个参数的内部名称,就是我们常说的变量名。
而我们展示给用户的默认初始值在哪里呢?
让我们目光回到这个json结构上,他有一个名为arguments的key,这个值是一个json,这个json的内容就是我们在双语文本内编写的参数了,比如下面这个积木:

双语文本

积木配置
通过双语文本我们可以得知,他有两个参数,这两个参数的名字分别是fps和num。
那么我们在下面的积木配置的arguments中就可以找到两个内容,分别就是fps和num,这就是两个参数的详细配置,type代表了这个参数的类型,已知有以下类型:
数字:number
字符串:string
布尔值:Boolean
(不完善,因为有部分值我还不会,比如loop)
而下面的defaultValue就是这个参数展示给用户的默认值了,一般情况下,默认值都要展示给用户一个可以直接运行的值作为参考。
当然,还有一种情况,那就是没有defaultValue,而是被menu替代,menu意味着这个参数不是一个需要用户输入的值,而是一个让用户对已有菜单进行选择的参数。
也就是我们的菜单参数:

菜单参数
在menu中,我们指定的值应该是一个我们指定的菜单,这个我会在稍后讲解。
至此,你已经掌握了积木区的编写方法了!
菜单信息
在上文中我们学习了如何调用菜单,但是怎么创建菜单呢?
其实也很简单。(本教程只教授静态菜单,动态菜单我还不会(
在blocks的下面,有个key叫做menus,没错,这就是我们放置菜单的地方,在这里面,你可以使用一个菜单名(也就是上文中menu的值)作为key来创建一个菜单,比如:

菜单
菜单的主体应当是一个列表,列表的内容是数组或者json,其内容包含text和value。
text顾名思义,我已经讲过很多遍了,就是要展示给用户的双语文本。
value就是内部返回值,比如用户选择了type.2的选项,那么它对应的value是false,当你在代码中获取这个参数的值的时候,就会返回false。
这样做出来的菜单,长这样:

菜单
这种菜单无法修改,那要如何才能让用户能选择菜单的同时,能够拖入积木实现自定义内容呢?
这时,你需要把这个菜单从数组变成json,然后在里面写两个key
一个是acceptReporters,这是个布尔值,设置它为true可以实现将积木拼接到这个菜单中。
另一个是items,它的内容和之前的写法是一样的,也是一个数组,里面有json。
大概长这样:

能积木拼接的菜单
这就是菜单的写法了。
写完了menu,getInfo的区域应该就写完了,接下来要写的就是所有积木的代码实现了。
代码实现
还记得上文中的积木配置吗,里面有个没有讲到的属性不知道大家发现没有,没错,就是opcode!
opcode就是这个要实现的功能的名字。它的值应该是一个方法名。
而在getInfo下面,就是定义方法的地方了。
找到你要添加代码的积木,将其opcode的值复制下来,粘贴到getInfo的后面,并写成方法的格式:

添加方法
这里面的内容就完全靠自己的js积累了。
如果你要获取你之前积木中用户输入的参数,你可以使用args。
在方法名后面的括号中写入args来引用参数。
args是个object类型的变量。
当你写完了所有代码的实现后,恭喜你,离一个完整的拓展只差最后一步!
配置信息
在文件的最后,类(class)的外面,你应该可以看见一段代码:

拓展配置信息
这段代码是ccw独有的,旨在为创作者提供

拓展页面。
这里面有一些信息,比如:
Extension:拓展ID
name:拓展名称(双语)
description:拓展描述(双语)
extensionId:拓展ID
iconURL:拓展封面
insetIconURL:拓展图标
collaborator:开发者
其中,拓展ID、拓展图标、拓展封面应该是一开始就被全局变量定义好的。
拓展名称、拓展描述是需要在这里的l10n中重新配置双语文本的。不过调用双语文本不再需要一长串的方法名了,而是简单的用双引号括起来。
featured、disabled我也不清楚有什么用,反正不改就是了