Repository: liupan1890/aliyunpan Branch: v3 Commit: b3108ebbdda5 Files: 250 Total size: 2.1 MB Directory structure: gitextract_g6ltbs2_/ ├── .gitignore ├── .prettierrc ├── README.md ├── adrive sdk/ │ ├── ReadMe.md │ ├── account.md │ ├── aims.md │ ├── album.md │ ├── archive.md │ ├── book.md │ ├── contact.md │ ├── drive.md │ ├── file.md │ ├── filedir.md │ ├── fileupload.md │ ├── image.md │ ├── member.md │ ├── note.md │ ├── offline.md │ ├── recyclebin.md │ ├── reddot.md │ ├── sbox.md │ ├── search.md │ ├── sfiia.md │ ├── share.md │ ├── timeline.md │ ├── token.md │ ├── user.md │ └── video.md ├── changelog.txt ├── crx/ │ ├── devtools.html │ ├── devtools.js │ └── manifest.json ├── doc/ │ ├── info.md │ ├── v2.8.x 使用PotPlayer.md │ └── v2.8.x 阿里云盘小白羊版和官方性能测试.md ├── electron-builder.json ├── nano-staged.mjs ├── package.json ├── public/ │ ├── comlink.js │ ├── iconfont.css │ ├── lang/ │ │ ├── en.js │ │ └── zh-CN.js │ ├── main.html │ ├── main2.html │ ├── prism-vsc-dark-plus.css │ ├── prism.js │ ├── sha1filework.js │ ├── silvermine-videojs-quality-selector.css │ ├── wasm.wasm │ └── wasm_exec.js ├── src/ │ ├── main/ │ │ ├── index.ts │ │ ├── mainfile.ts │ │ └── window.ts │ ├── preload/ │ │ ├── index.ts │ │ └── preload-env.d.ts │ └── renderer/ │ ├── App.vue │ ├── aliapi/ │ │ ├── alihttp.ts │ │ ├── alimodels.ts │ │ ├── archive.ts │ │ ├── batch.ts │ │ ├── dirfilelist.ts │ │ ├── dirlist.ts │ │ ├── file.ts │ │ ├── filecmd.ts │ │ ├── fileicon.ts │ │ ├── filewalk.ts │ │ ├── following.ts │ │ ├── models.ts │ │ ├── server.tsx │ │ ├── share.ts │ │ ├── sharelist.ts │ │ ├── trash.ts │ │ ├── upload.ts │ │ ├── uploaddisk.ts │ │ ├── uploadhash.ts │ │ ├── uploadhashpool.ts │ │ ├── uploadmem.ts │ │ ├── user.ts │ │ └── utils.ts │ ├── assets/ │ │ ├── antd.css │ │ ├── fileitem.css │ │ └── global.css │ ├── down/ │ │ ├── DownDowned.vue │ │ ├── DownDowning.vue │ │ ├── DownM3U8.vue │ │ ├── DownSync.vue │ │ ├── DownUploaded.vue │ │ ├── DownUploading.vue │ │ ├── downdal.ts │ │ ├── downingstore.ts │ │ ├── downmenu.ts │ │ ├── index.vue │ │ ├── uploadedstore.ts │ │ └── uploadingstore.ts │ ├── env.d.ts │ ├── global.d.ts │ ├── layout/ │ │ ├── MyLoading.vue │ │ ├── MyModal.vue │ │ ├── MySplit.vue │ │ ├── MySwitch.vue │ │ ├── MySwitchTab.vue │ │ ├── MyTags.vue │ │ ├── PageCode.vue │ │ ├── PageHelp.vue │ │ ├── PageImage.vue │ │ ├── PageLoading.vue │ │ ├── PageMain.vue │ │ ├── PageOffice.vue │ │ ├── PageVideo.vue │ │ ├── PageVideoXBT.vue │ │ ├── PageWorker.vue │ │ └── pagemain.ts │ ├── main.ts │ ├── pan/ │ │ ├── PanLeft.vue │ │ ├── PanRight.vue │ │ ├── index.vue │ │ ├── menus/ │ │ │ ├── DirLeftMenu.vue │ │ │ ├── DirTopPath.vue │ │ │ ├── FileRightMenu.vue │ │ │ ├── FileTopbtn.vue │ │ │ ├── PanTopbtn.vue │ │ │ ├── TrashRightMenu.vue │ │ │ └── TrashTopbtn.vue │ │ ├── pandal.ts │ │ ├── panfilestore.ts │ │ ├── pantreestore.ts │ │ └── topbtns/ │ │ ├── AlphaModal.vue │ │ ├── ArchiveModal.vue │ │ ├── ArchivePasswordModal.vue │ │ ├── CopyFileTreeModal.vue │ │ ├── CreatNewDirModal.vue │ │ ├── CreatNewDirMultiModal.vue │ │ ├── CreatNewFileModal.vue │ │ ├── CreatNewShareLinkModal.vue │ │ ├── DLNAPlayerModal.vue │ │ ├── DaoRuShareLinkModal.vue │ │ ├── DaoRuShareLinkMultiModal.vue │ │ ├── DownloadModal.vue │ │ ├── M3U8DownloadModal.vue │ │ ├── RenameModal.vue │ │ ├── RenameMultiModal.vue │ │ ├── SearchPanModal.vue │ │ ├── SelectPanDirModal.vue │ │ ├── ShuXingModal.vue │ │ ├── ShuXingMultiModal.vue │ │ ├── UploadModal.vue │ │ ├── renamemulti.ts │ │ └── topbtn.ts │ ├── pic/ │ │ ├── PicLeft.vue │ │ ├── PicRight.vue │ │ └── index.vue │ ├── rss/ │ │ ├── ScanDAL.ts │ │ ├── appsame/ │ │ │ ├── AppSame.vue │ │ │ └── same.ts │ │ ├── index.vue │ │ ├── rssdrivecopy/ │ │ │ ├── RssDriveCopy.vue │ │ │ └── drivecopy.ts │ │ ├── rssjiami/ │ │ │ ├── RssJiaMi.vue │ │ │ └── jiami.ts │ │ ├── rssrename/ │ │ │ └── RssRename.vue │ │ ├── rssscanclean/ │ │ │ ├── RssScanClean.vue │ │ │ └── ScanClean.ts │ │ ├── rssscanenmpty/ │ │ │ ├── RssScanEnmpty.vue │ │ │ └── scanenmpty.ts │ │ ├── rssscanpunish/ │ │ │ ├── RssScanPunish.vue │ │ │ └── scanpunish.ts │ │ ├── rssscansame/ │ │ │ ├── RssScanSame.vue │ │ │ └── scansame.ts │ │ ├── rssusercopy/ │ │ │ ├── RssUserCopy.vue │ │ │ └── usercopy.ts │ │ └── rssxima/ │ │ ├── RssXiMa.vue │ │ └── xima.ts │ ├── setting/ │ │ ├── SettingDebug.vue │ │ ├── SettingDown.vue │ │ ├── SettingLog.vue │ │ ├── SettingPan.vue │ │ ├── SettingPlay.vue │ │ ├── SettingProxy.vue │ │ ├── SettingUI.vue │ │ ├── SettingUpload.vue │ │ ├── ShutDown.vue │ │ ├── index.vue │ │ └── settingstore.ts │ ├── share/ │ │ ├── following/ │ │ │ ├── FollowingDAL.ts │ │ │ ├── MyFollowingRight.vue │ │ │ ├── MyFollowingStore.ts │ │ │ ├── OtherFollowingRight.vue │ │ │ └── OtherFollowingStore.ts │ │ ├── index.vue │ │ └── share/ │ │ ├── EditShareLinkModal.vue │ │ ├── MyShareRight.vue │ │ ├── MyShareStore.ts │ │ ├── OtherShareRight.vue │ │ ├── OtherShareStore.ts │ │ ├── ShareDAL.ts │ │ ├── ShareSiteRight.vue │ │ └── ShowShareLinkModal.vue │ ├── store/ │ │ ├── appstore.ts │ │ ├── footstore.ts │ │ ├── index.ts │ │ ├── keyboardstore.ts │ │ ├── logstore.ts │ │ ├── modalstore.ts │ │ ├── protobuf.ts.bak │ │ ├── serverstore.ts │ │ ├── treestore.ts │ │ └── winstore.ts │ ├── transfer/ │ │ ├── uploaddal.ts │ │ ├── uploadingdal.ts │ │ └── uploadingdata.ts │ ├── user/ │ │ ├── UserInfo.vue │ │ ├── UserLogin.vue │ │ ├── UserSpaceModal.vue │ │ ├── userdal.ts │ │ └── userstore.ts │ ├── utils/ │ │ ├── antdtree.ts │ │ ├── appcache.ts │ │ ├── config.ts │ │ ├── db.ts │ │ ├── dbcache.ts │ │ ├── dbdown.ts │ │ ├── dbupload.ts │ │ ├── debounce.ts │ │ ├── debuglog.ts │ │ ├── electronhelper.ts │ │ ├── filehelper.ts │ │ ├── filenameorder.ts │ │ ├── foot.ts │ │ ├── format.ts │ │ ├── idhelper.ts │ │ ├── keyboardhelper.ts │ │ ├── levemap.ts │ │ ├── message.ts │ │ ├── modal.ts │ │ ├── openfile.ts │ │ ├── selecthelper.ts │ │ ├── sha1workerpool.ts │ │ ├── shareurl.ts │ │ ├── utils.ts │ │ └── worker.ts │ └── workerpage/ │ ├── uidownload.ts │ ├── uiupload.ts │ ├── uploader.ts │ └── workercmd.ts ├── tsconfig.json ├── types.d.ts ├── v2.10.19性能测试.md ├── v2.11.11自定义播放软件.md ├── 开源代码统计.md └── 源码开发打包帮助.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules .DS_Store dist dist-ssr *.local .debug.env tmp **/.tmp release ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "printWidth": 260, "semi": false, "quoteProps": "as-needed", "jsxSingleQuote": false, "trailingComma": "none", "bracketSpacing": true, "jsxBracketSameLine": true, "arrowParens": "always", "requirePragma": false, "insertPragma": false, "wrapAttributes": false, "sortAttributes": true, "proseWrap": "preserve", "htmlWhitespaceSensitivity": "css", "endOfLine": "lf", "overrides": [ { "files": ".prettierrc", "options": { "parser": "json" } } ] } ================================================ FILE: README.md ================================================ # 阿里云盘小白羊版 #### 项目说明 基于阿里云盘网页版开发的PC客户端,支持win7-11,macOS,linux > **04.14:[v2.12.14版已发布](https://github.com/liupan1890/aliyunpan/issues/639),适配官网升级** > **2022-01-02:在憋大招,耐心等待v3版**
v1.6.29:[https://wwe.lanzoui.com/b01npsg8h](https://wwe.lanzoui.com/b01npsg8h) v2.12.14:[https://wwe.lanzoui.com/b01nqc4gd](https://wwe.lanzoui.com/b01nqc4gd) MacOS:[https://www.macwk.com/soft/aliyun-drive-xiaobaiyang](https://www.macwk.com/soft/aliyun-drive-xiaobaiyang) Mac版由macwk.com使用自有签名打包dmg,可以简单点击安装了(不需要输入终端命令),推荐下载此版本,已测MacOS10.12-11.4,兼容M1
已经发布在小众软件发现频道,大爱小众[meta.appinn.net](https://meta.appinn.net)
已发布了使用帮助文档 [https://www.yuque.com/liupan1890/xiaobaiyang](https://www.yuque.com/liupan1890/xiaobaiyang) `````` 2021年11月28日 已完成功能: 多账号登录、常用文件操作(新建文件夹、收藏、重命名、复制、移动、删除、详情、视频雪碧图)、 在线播放原始视频、在线播放转码视频、在线预览图片、在线预览文本、在线预览 word/excel/ppt/pdf、 连接到远程 Aria2 下载、上传文件、上传文件夹、批量改名、在线解压、回收站、收藏夹、 分享文件、导入阿里云分享链接、缩略图列表、网盘内文件搜索、视频文件洗码 等待完成的功能: 相册功能、网盘和相册间文件互相复制、文件同步盘、重复文件扫描、帐号间文件复制 ``````
# ![Image](https://raw.githubusercontent.com/liupan1890/aliyunpan/main/doc/v2.10.19.png) # #### 为什么要用小白羊? #### 一:因为更快 ##### 上传和下载4.4万个json格式小文件(共24GB): | 程序 | 总用时 | 用时基准 | | --- | ---: | ---: | | 上传&小白羊版 v2.10 | 24分钟 | :zap:58% | | 上传&PC客户端 v2.2.6 | 41分钟 | 100% | | ... | | | | | | 下载&小白羊版 v2.10 | 25分钟 | :zap:42% | | 下载&PC客户端 v2.2.6 | 59分钟 | 100% | ##### 上传和下载33个大文件(共90GB): | 程序 | 总用时 | 用时基准 | | --- | ---: | ---: | | 上传&小白羊版 v2.10 | 1分10秒 | :zap:44% | | 上传&PC客户端 v2.2.6 | 2分40秒 | 100% | | ... | | | | | | 下载&小白羊版 v2.10 | 38分钟 | :zap:52% | | 下载&PC客户端 v2.2.6 | 72分钟 | 100% |
详情参阅 :[v2.10.19性能测试](https://github.com/liupan1890/aliyunpan/blob/main/v2.10.19%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95.md) 的性能测试文档 #### 二:因为更好 小白羊支持同时登录多个账号管理 小白羊特有文件夹树,可以快速方便的操作 小白羊支持直接在线播放网盘里的各种格式的视频并且是高清原画,支持外挂字幕/音轨/播放速度调整,比官方的格式更多更清晰 小白羊可以显示文件夹体积,可以文件夹和文件混合排序(文件名/体积/时间),并且文件名排序时更准确! 小白羊可以通过远程Aria2功能把文件直接下载到远程的VPS/NAS上 小白羊可以批量的对 大量文件/多层嵌套的文件夹 一键重命名 小白羊可以快速复制文件,可以直接预览视频的雪碧图,可以直接删除文件 小白羊支持数万文件夹和数万文件的管理,支持一次性列出文件夹里包含的全部文件 小白羊支持单次上传/下载 一百万 量级的文件/文件夹 小白羊仍在努力开发新功能,让大家使用起来更方便! # #### 常见问题请参阅帮助文档 #### 特别感谢 @jkqxl @iD2073 @ybbluesky 等为小白羊提供了大量的优化建议 ================================================ FILE: adrive sdk/ReadMe.md ================================================ ### 阿里云盘接口 > 2022-03整理的阿里云盘SDK接口数据 仅用来记录官方提供的接口参数,共整理了144个,比较全了,与编程语言无关,方便大家据此开发 ================================================ FILE: adrive sdk/account.md ================================================ #### 刷新 token POST: `https://auth.aliyundrive.com/v2/account/token` ```json { "grant_type": "refresh_token", "app_id": "pJZInNHN2dZWk8qg", "refresh_token": "c65bf6d104ac510885c0124d74c4a099" } ``` Response: ```json { "default_sbox_drive_id": "9600002", "role": "user", "device_id": "2909000000004f01aa28264bfc30e4ed", "user_name": "151***111", "need_link": false, "expire_time": "2022-03-21T06:33:21Z", "pin_setup": true, "need_rp_verify": false, "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_data": { "DingDingRobotUrl": "https://oapi.dingtalk.com/robot/send?access_token=0b4a936d0e...", "EncourageDesc": "内测期间有效反馈前10名用户将获得终身免费会员", "FeedBackSwitch": true, "FollowingDesc": "34848372", "back_up_config": { "手机备份": { "folder_id": "605c0c29b7acf78b6ee34bf095594f7654e57d68", "photo_folder_id": "605c0c299af37539f3d34879b2f0d1c5543f27d5", "sub_folder": {}, "video_folder_id": "605c0c29e520154c22644bed904b76b25ced317a" } }, "ding_ding_robot_url": "https://oapi.dingtalk.com/robot/send?access_token=0b4a936d0e...", "encourage_desc": "内测期间有效反馈前10名用户将获得终身免费会员", "feed_back_switch": true, "following_desc": "34848372" }, "token_type": "Bearer", "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..................", "default_drive_id": "9600002", "domain_id": "bj29", "refresh_token": "b2d9c244d8a24df38aa1a5dec59e2a92", "is_first_login": false, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "myname", "exist_link": [], "state": "", "expires_in": 7200, "status": "enabled" } ``` #### 退出登录 POST: `https://auth.aliyundrive.com/v2/account/revoke` ```json ``` Response: ```json ``` #### 检查账号是否存在 x POST: `https://auth.aliyundrive.com/v2/account/mobile/check_exist` ```json { "app_id": "pJZInNHN2dZWk8qg", "phone_number": "151***111", "phone_region": "86" } ``` Response: ```json { "is_exist": true } ``` ================================================ FILE: adrive sdk/aims.md ================================================ #### 探索-列出图片分类最多的前几个分类 POST: `https://api.aliyundrive.com/v2/aims/list_hints` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f", "limit": 5 } ``` Response: ```json ["白色", "鞋", "服装", "颜色", "黑色"] ``` #### 探索-列出图片分类(对应的是 label) POST: `https://api.aliyundrive.com/v2/aims/list_tags` ```json { "all": false, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "video_thumbnail_process": "video/snapshot,t_7000,f_jpg,w_800,h_600,ar_auto,m_fast", "drive_id": "9600002" } ``` Response: ```json { "tags": [ { "count": 22, "cover_file_category": "", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_overall_score": 0.7444725632667542, "cover_tag_confidence": 0.9806441068649292, "cover_url": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/HCBUxQOF%2F...", "name": "截图" }, { "count": 6, "cover_file_category": "", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_overall_score": 0.660460352897644, "cover_tag_confidence": 0.8765541911125183, "cover_url": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/HCBUxQOF%2F...", "name": "健身" } ] } ``` #### 探索-列出一个分类(label)的全部图片 POST: `https://api.aliyundrive.com/v2/file/search` ```json { "return_total_count": true, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "last_access_at DESC,updated_at DESC,image_time DESC", "query": "(label = '截图') and category in ['video','image'] and status = 'available' and hidden = false", "limit": 100, "drive_id": "9600002" } ``` Response: ```json filelist ``` #### 探索-列出全部回忆 POST: `https://api.aliyundrive.com/v2/aims/list_stories` ```json { "drive_id": "9600002", "skip_stories_creation": false, "cover_image_thumbnail_process": "image/resize,m_lfit,w_800/format,jpg" } ``` Response: ```json { "items": [ { "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_thumbnail_url": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/aUDpMBAO%2F...", "created_at": "2022-03-13T21:31:47.210563978+08:00", "face_group_ids": ["Group-00000000-1703-4fc8-4f56-369478ed14df"], "story_end_time": "", "story_file_list": [ { "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }, { "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ], "story_id": "903C5705-0000-0000-4fc8-42B97E29C65C", "story_name": "熟悉的TA", "story_start_time": "", "story_sub_type": "ImportantPerson", "story_type": "ImportantPerson", "updated_at": "2022-03-13T21:31:47.21056415+08:00", "cover_file": { "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-09-08T13:45:59.755Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "jpg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "faces": "[{\"FaceConfidence\":0.9646940231323242,\"EmotionConfidence\":0.974002480506897,\"ImageUri\":\"\",\"FaceQuality\":0.8240875005722046,\"Similarity\":0,\"ExternalId\":\"\",\"Attractive\":0.95,\"AttractiveConfidence\":0,\"Age\":19,\"AgeConfidence\":0,\"Gender\":\"FEMALE\",\"Emotion\":\"SAD\",\"GenderConfidence\":1,\"FaceId\":\"45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3\",\"GroupId\":\"Group-00000000-1703-4fc8-5f56-369478ed14df\",\"FaceAttributes\":{\"Glasses\":\"NONE\",\"MaskConfidence\":0.9999961853027344,\"Mask\":\"NONE\",\"GlassesConfidence\":1,\"Beard\":\"NONE\",\"BeardConfidence\":1,\"FaceBoundary\":{\"Width\":558,\"Height\":787,\"Top\":318,\"Left\":1075},\"HeadPose\":{\"Pitch\":8.109945297241211,\"Roll\":-11.779093742370605,\"Yaw\":-12.086345672607422}},\"EmotionDetails\":{\"SURPRISED\":0.0010840623872354627,\"HAPPY\":0.0072783417999744415,\"ANGRY\":0.00025470455875620246,\"DISGUSTED\":0.0018990141106769443,\"SAD\":0.974002480506897,\"CALM\":0.005655393470078707,\"SCARED\":0.006041224580258131},\"SimilarFaces\":null}]", "faces_thumbnail": [ { "face_group_id": "Group-00000000-1703-4fc8-5f56-369478ed14df", "face_id": "45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3", "face_thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ], "height": 3600, "image_quality": { "overall_score": 0.639841616153717 }, "time": "2022-03-13T21:31:47.210563978+08:00", "width": 2400 }, "labels": ["面部", "日常行为"], "mime_extension": "jpg", "mime_type": "image/jpeg", "name": "44.jpg", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 2, "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111", "size": 1974176, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "trashed": false, "type": "file", "updated_at": "2021-09-08T13:46:01.896Z", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } } ] } ``` #### 探索-读取一个回忆的信息(名称、人物、图片) POST: `https://api.aliyundrive.com/v2/aims/get_story` ```json { "drive_id": "9600002", "story_id": "903C5705-0000-0000-4fc8-42B97E29C65C" } ``` Response: ```json { "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_thumbnail_url": "https://bj29.cn-beijing.data.alicloudccp.com/RV5OBihM%2F...", "created_at": "2022-03-13T21:31:47.210563978+08:00", "face_group_ids": ["Group-00000000-1763-4fc8-bf56-369478ed14df"], "story_end_time": "", "story_file_list": [ { "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-09-08T13:45:59.755Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "jpg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "faces": "[{\"FaceConfidence\":0.9646940231323242,\"EmotionConfidence\":0.974002480506897,\"ImageUri\":\"\",\"FaceQuality\":0.8240875005722046,\"Similarity\":0,\"ExternalId\":\"\",\"Attractive\":0.95,\"AttractiveConfidence\":0,\"Age\":19,\"AgeConfidence\":0,\"Gender\":\"FEMALE\",\"Emotion\":\"SAD\",\"GenderConfidence\":1,\"FaceId\":\"45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3\",\"GroupId\":\"Group-00000000-1703-4fc6-bf56-369478ed14df\",\"FaceAttributes\":{\"Glasses\":\"NONE\",\"MaskConfidence\":0.9999961853027344,\"Mask\":\"NONE\",\"GlassesConfidence\":1,\"Beard\":\"NONE\",\"BeardConfidence\":1,\"FaceBoundary\":{\"Width\":558,\"Height\":787,\"Top\":318,\"Left\":1075},\"HeadPose\":{\"Pitch\":8.109945297241211,\"Roll\":-11.779093742370605,\"Yaw\":-12.086345672607422}},\"EmotionDetails\":{\"SURPRISED\":0.0010840623872354627,\"HAPPY\":0.0072783417999744415,\"ANGRY\":0.00025470455875620246,\"DISGUSTED\":0.0018990141106769443,\"SAD\":0.974002480506897,\"CALM\":0.005655393470078707,\"SCARED\":0.006041224580258131},\"SimilarFaces\":null}]", "faces_thumbnail": [ { "face_group_id": "Group-00000000-1703-4fc8-bf56-369478ed14df", "face_id": "45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3", "face_thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ], "height": 3600, "image_quality": { "overall_score": 0.639841616153717 }, "width": 2400 }, "labels": [ "面部", "日常行为" ], "name": "44.jpg", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "size": 1974176, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2021-09-08T13:46:01.896Z", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ], "story_id": "903C5705-0000-0000-4fc8-42B97E29C65C", "story_name": "fang的高光时刻", "story_start_time": "", "story_sub_type": "ImportantPerson", "story_type": "ImportantPerson", "updated_at": "2022-03-13T21:31:47.21056415+08:00" } ``` #### 清理空间-统计数量 POST: `https://api.aliyundrive.com/v2/aims/clutter_removal/count` ```json { "drive_id": "9600002" } ``` Response: ```json { "screenshot": 20, "text": 26 } ``` #### 清理空间-清理屏幕截图 POST: `https://api.aliyundrive.com/v2/aims/clutter_removal/list` ```json { "type": "screenshot", "drive_id": "9600002" } ``` Response: ```json filelist ``` #### 清理空间-清理文本图片 POST: `https://api.aliyundrive.com/v2/aims/clutter_removal/list` ```json { "type": "text", "drive_id": "9600002" } ``` Response: ```json filelist ``` ================================================ FILE: adrive sdk/album.md ================================================ #### 创建相册 POST: `https://api.aliyundrive.com/adrive/v1/album/create` ```json { "name": "未命名", "description": "" } ``` Response: ```json { "owner": "ccff000000004d75b5788a481eed8386", "name": "未命名", "description": "", "album_id": "cfe400000000478599575b69356c5a4962383669", "file_count": 0, "image_count": 0, "video_count": 0, "created_at": 1647851113891, "updated_at": 1647851113891 } ``` #### 修改相册 POST: `https://api.aliyundrive.com/adrive/v1/album/update` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669", "description": "ff", "name": "未命名" } ``` Response: ```json { "owner": "ccff000000004d75b5788a481eed8386", "name": "未命名", "description": "", "album_id": "cfe400000000478599575b69356c5a4962383669", "file_count": 0, "image_count": 0, "video_count": 0, "created_at": 1647851113891, "updated_at": 1647851113891 } ``` #### 删除相册(不会删除相册内文件) POST: `https://api.aliyundrive.com/adrive/v1/album/delete` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669" } ``` Response: ```json {} ``` #### 读取相册 POST: `https://api.aliyundrive.com/adrive/v1/album/get` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669" } ``` Response: ```json { "owner": "ccff000000004d75b5788a481eed8386", "name": "未命名", "description": "", "cover": { "list": [ { "trashed": false, "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2022-03-21T08:27:15.671Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "jpeg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "image_quality": {} }, "mime_type": "image/jpeg", "name": "fa9cb4682043bb141b48dd82.jpeg", "parent_file_id": "root", "punish_flag": 0, "size": 586988, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-03-21T08:27:16.226Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "ex_fields_info": {} } ] }, "album_id": "cfe400000000478599575b69356c5a4962383669", "file_count": 1, "image_count": 1, "video_count": 0, "created_at": 1647851113891, "updated_at": 1647851236638 } ``` #### 添加文件到相册 POST: `https://api.aliyundrive.com/adrive/v1/album/add_files` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] } ``` Response: ```json { "file_list": [ { "trashed": false, "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2022-03-21T08:27:15.671Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "jpeg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "image_quality": {} }, "mime_type": "image/jpeg", "name": "fa9cb4682043bb141b48dd82.jpeg", "parent_file_id": "root", "punish_flag": 0, "size": 586988, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-03-21T08:27:16.226Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "ex_fields_info": {} } ] } ``` #### 从相册移除文件 POST: `https://api.aliyundrive.com/adrive/v1/album/delete_files` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] } ``` Response: ```json {} ``` #### 列出相册内文件 POST: `https://api.aliyundrive.com/adrive/v1/album/list_files` ```json { "album_id": "cfe400000000478599575b69356c5a4962383669", "image_thumbnail_process": "image/resize,w_400/format,jpeg", "video_thumbnail_process": "video/snapshot,t_0,f_jpg,ar_auto,w_1000", "image_url_process": "image/resize,w_1920/format,jpeg", "filter": "", "fields": "*", "limit": 100, "order_by": "file_image_time", "order_direction": "DESC" } ``` Response: ```json { "items": [ { "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2022-03-21T08:27:15.671Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "jpeg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "image_quality": {} }, "name": "fa9cb4682043bb141b48dd82.jpeg", "parent_file_id": "root", "size": 586988, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-03-21T08:27:16.226Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ] } ``` #### 上传文件到相册 POST: `https://api.aliyundrive.com/adrive/v1/biz/albums/file/create` ```json { "drive_id": "9600002", "part_info_list": [{ "part_number": 1 }], "parent_file_id": "root", "name": "fa9cb4682043bb141b48dd82.jpeg", "type": "file", "check_name_mode": "auto_rename", "size": 586988, "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "proof_code": "TIo2j2wSMV4=", "proof_version": "v1" } ``` Response: ```json { "type": "file", "parent_file_id": "root", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "domain_id": "bj29", "trashed_at": null, "file_name": "fa9cb4682043bb141b48dd82.jpeg", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "encrypt_mode": "none", "location": "cn-beijing", "rapid_upload": false, "part_info_list": [ { "part_number": 1, "upload_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "internal_upload_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "content_type": "" } ] } ``` ================================================ FILE: adrive sdk/archive.md ================================================ #### 在线打开压缩包 POST: `https://api.aliyundrive.com/v2/archive/list` ```json { "archive_type": "zip", "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "state": "Running", "file_list": {}, "task_id": "e026000000007f609bcd6aa71b8fde94" } ``` #### 在线打开压缩包进度 POST: `https://api.aliyundrive.com/v2/archive/status` ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "task_id": "e026000000007f609bcd6aa71b8fde94" } ``` Response: ```json { "code": "LimitArchive", "message": "Archive reach limit" } {"code":"BadArchive","message":"Archive is bad"} {"code":"InvalidPassword","message":"Password is invalid"} ``` ```json { "state": "Running", "file_list": {}, "task_id": "e026000000007f609bcd6aa71b8fde94", "progress": 0 } ``` ```json { "state": "Succeed", "file_list": { "filezi": { "is_folder": true, "items": [ { "is_folder": true, "items": [ { "is_folder": false, "items": [], "name": "filezi/electron/electron", "size": 140256360, "updated_at": "2022-03-23T04:11:45.000Z" }, { "is_folder": false, "items": [], "name": "filezi/electron/libvk_swiftshader.so", "size": 4168528, "updated_at": "2022-03-23T04:11:45.000Z" }, { "is_folder": true, "items": [ { "is_folder": false, "items": [], "name": "filezi/electron/swiftshader/libEGL.so", "size": 256032, "updated_at": "2022-03-23T04:11:45.000Z" }, { "is_folder": false, "items": [], "name": "filezi/electron/swiftshader/libGLESv2.so", "size": 2580600, "updated_at": "2022-03-23T04:11:45.000Z" } ], "name": "filezi/electron/swiftshader", "size": 0, "updated_at": "1970-01-01T00:00:00.000Z" } ], "name": "filezi/electron", "size": 0, "updated_at": "1970-01-01T00:00:00.000Z" }, { "is_folder": false, "items": [], "name": "filezi/linux使用帮助.txt", "size": 509, "updated_at": "2022-03-23T04:11:45.000Z" } ], "name": "filezi", "size": 0, "updated_at": "1970-01-01T00:00:00.000Z" } }, "task_id": "e026000000007f609bcd6aa71b8fde94", "progress": 100 } ``` #### 在线打开压缩包(rar 带密码) ```js //第一次,没有文件缓存 //POST: `https://api.aliyundrive.com/v2/archive/list` {"code":"BadArchive","message":"Archive is bad"}//返回文件锁坏 //POST: `https://api.aliyundrive.com/v2/archive/list` "password":"123" //返回正常的 { "state": "Succeed", "file_list": { ... ``` ```js //第二次,有缓存 //POST: `https://api.aliyundrive.com/v2/archive/list` {"code":"InvalidPassword","message":"Password is invalid"}//返回需要密码 //POST: `https://api.aliyundrive.com/v2/archive/list` "password":"123" //返回正常的 { "state": "Succeed", "file_list": { ... ``` #### 在线解压 POST: `https://api.aliyundrive.com/v2/archive/uncompress` ```json { "archive_type": "zip", "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "target_drive_id": "9600002", "target_file_id": "61a300000000e67e5cf8489fab317ef345373b80" } ``` ```json { "archive_type": "zip", "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_list": ["lc-design-demo/assets/views/home.xml", "lc-design-demo/assets/views/layout"], "password": "123", "target_drive_id": "9600002", "target_file_id": "61a300000000e67e5cf8489fab317ef345373b80" } ``` Response: ```json { "state": "Running", "task_id": "e026000000007f609bcd6aa71b8fde94" } ``` #### 在线解压进度 POST: `https://api.aliyundrive.com/v2/archive/status` ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "task_id": "e026000000007f609bcd6aa71b8fde94" } ``` Response: ```json { "state": "Running", "file_list": {}, "task_id": "e026000000007f609bcd6aa71b8fde94", "progress": -1 } ``` ```json { "state": "Running", "file_list": {}, "task_id": "e026000000007f609bcd6aa71b8fde94", "progress": 15 } ``` ```json { "state": "Succeed", "file_list": {}, "task_id": "e026000000007f609bcd6aa71b8fde94", "progress": 100 } ``` #### 打包下载 POST: `https://api.aliyundrive.com/v2/file/archive_files` ```json { "name": "aname.zip", "drive_id": "9600002", "files": [{ "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] } ``` Response: ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb" } ``` #### 打包下载进度 POST: `https://api.aliyundrive.com/v2/async_task/get` ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb" } ``` Response: ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb", "state": "Succeed", "err_code": 200, "total_process": 167238406, "consumed_process": 167238406, "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/archive%2F9fcb1e1d-e9dd-43d0-b30d-387e04dcafcb?response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27aname.zip\u0026x-oss-access-key-id=LTAIsE5mAn2F493Q\u0026x-oss-expires=1648014906\u0026x-oss-signature=5E4UEDoNKoUFDKsH41BQxlsc0BvoTeMjS4QZv5x1U%2B0%3D\u0026x-oss-signature-version=OSS2", "punished_file_count": 0 } ``` ================================================ FILE: adrive sdk/book.md ================================================ #### 列出图书 POST: `https://api.aliyundrive.com/adrive/v2/book/list` ```json { "book_progress_type": "ALL", "limit": 1, "marker": "", "order_by": "name asc", "show_hidden": false } ``` Response: ```json { "items": [ { "category": "doc", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-11-22T03:36:19.680Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "epub", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "name": "Republic.epub", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 128000, "starred": false, "status": "available", "type": "file", "updated_at": "2022-01-12T12:44:16.835Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}", "user_tags": { "book_show": "true" } } ], "next_marker": "" } ``` #### 列出最近阅读的图书 POST: `https://api.aliyundrive.com/adrive/v2/book/recentList` ```json { "book_progress_type": "ALL", "limit": 1, "marker": "", "order_by": "name asc", "show_hidden": false } ``` Response: ```json { "items": [ { "category": "doc", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-09-24T12:50:00.905Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "epub", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "name": "无声告白.epub", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 1027423, "starred": false, "status": "available", "type": "file", "updated_at": "2022-03-22T14:59:12.333Z", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "book_progress": "{\"bookName\":\"无声告白\",\"chapterNumber\":1,\"chapterPercent\":0.0,\"currentPageNumber\":-1,\"progress\":29,\"totalPageNumber\":-1,\"uid\":\"9400000000bc480bbcbbb1e074f55a7f\",\"updateTime\":1647961151874}", "user_tags": { "book_progress": "{\"bookName\":\"无声告白\",\"chapterNumber\":1,\"chapterPercent\":0.0,\"currentPageNumber\":-1,\"progress\":29,\"totalPageNumber\":-1,\"uid\":\"9400000000bc480bbcbbb1e074f55a7f\",\"updateTime\":1647961151874}", "book_progress_percentage": "35", "book_show": "true", "epub_book_progress": "{\"uid\":\"9400000000bc480bbcbbb1e074f55a7f\",\"href\":\"\\/text\\/part0000.html\",\"type\":\"application\\/xhtml+xml\",\"locations\":{\"progression\":0,\"position\":2,\"totalProgression\":8.873114463176575E-4}}", "start_read": "true" }, "book_name": "无声告白", "book_progress_percentage": 29 } ] } ``` #### 添加到阅读室 POST: `https://api.aliyundrive.com/adrive/v2/book/update` ```json { "file_ids": ["623b00000000d89ef21d4118838aed83de7575ba"], "operation": 1 } ``` Response: ```text HTTP/1.1 200 OK ``` #### 从阅读室移除 POST: `https://api.aliyundrive.com/adrive/v2/book/update` ```json { "file_ids": ["623b00000000d89ef21d4118838aed83de7575ba"], "operation": 2 } ``` Response: ```text HTTP/1.1 200 OK ``` ================================================ FILE: adrive sdk/contact.md ================================================ #### 通讯录列出 POST: `https://api.aliyundrive.com/adrive/v1/contact/list` ```json {} ``` Response: ```json { "items": [ { "id": 223963400, "content": { "format": "vcard", "hash": "1a48648e8b140ae80be048f1681cfbe24a7b9579c2ffbabe2686eb79338dfe14", "value": "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:ez-vcard 0.11.2\r\nKIND:individual\r\nFN:高青\r\nN:高;青;;;\r\nTEL;TYPE=cell:15000065001\r\nEND:VCARD\r\n", "version": "4.0" }, "gmt_create": 1647864044589 }, { "id": 224054214, "content": { "format": "vcard", "hash": "978edd2d967b94b34d3a90c00cbd4819e239f21a6f72f6a2f87b522fe81a62f4", "value": "BEGIN:VCARD\r\nVERSION:4.0\r\nPRODID:ez-vcard 0.11.2\r\nKIND:individual\r\nFN:木门\r\nN:木;门;;;\r\nTEL;TYPE=cell:03100000981\r\nEND:VCARD\r\n", "version": "4.0" }, "gmt_create": 1647864055972 } ], "total_count": 2 } ``` #### 通讯录删除 POST: `https://api.aliyundrive.com/adrive/v1/contact/delete` ```json { "ids": [224206708] } ``` Response: ```json {} ``` #### 通讯录备份添加 POST: `https://api.aliyundrive.com/adrive/v1/contact/add` ```json { "items": [ { "hash": "978edd2d967b94b34d3a90c00cbd4819e239f21a6f72f6a2f87b522fe81a62f4", "version": "4.0", "value": "BEGIN:VCARD\r\nVERSION:4.0\r\nN:木;门\r\nTEL;TYPE=cell:03000080981\r\nKIND:individual\r\nEND:VCARD\r\n", "avatar": "", "format": "vcard" } ] } ``` Response: ```json { "items": [{ "id": 223963801, "content": { "format": "vcard", "hash": "978edd2d967b94b34d3a90c00cbd4819e239f21a6f72f6a2f87b522fe81a62f4", "version": "4.0" } }] } ``` ================================================ FILE: adrive sdk/drive.md ================================================ #### 全部 drive POST: `https://api.aliyundrive.com/v2/drive/list` ```json { "owner": "ccff000000004d75b5788a481eed8386" } ``` Response: ```json { "items": [ { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "alibum", "description": "", "creator": "", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 739272268, "total_size": -1, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-03-29T04:02:57.981Z", "permission": null, "subdomain_id": "" }, { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "Default", "description": "Created by system", "creator": "System", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 7186746146291, "total_size": 10737418240, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-03-18T04:55:06.893Z", "permission": null, "subdomain_id": "" }, { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "note_drive", "description": "", "creator": "", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 502382874, "total_size": -1, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-10-24T11:29:12.773Z", "permission": null, "subdomain_id": "" }, { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "Default", "description": "Created by system", "creator": "System", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 227511979353, "total_size": 10737418240, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-03-18T04:55:06.936Z", "permission": null, "subdomain_id": "" } ], "next_marker": "" } ``` #### 全部 drive POST: `https://api.aliyundrive.com/v2/drive/list_my_drives` ```json { "owner": "ccff000000004d75b5788a481eed8386" } ``` Response: ```json 同上 ``` #### 默认 drive(网盘) POST: `https://api.aliyundrive.com/v2/drive/get_default_drive` ```json ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "Default", "description": "Created by system", "creator": "System", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 7186746146291, "total_size": 17536351469568, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-03-18T04:55:06.893Z", "permission": null, "subdomain_id": "" } ``` #### 指定 drive POST: `https://api.aliyundrive.com/v2/drive/get` ```json { "drive_id": "9600002" } ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "drive_name": "alibum", "description": "", "creator": "", "owner": "ccff000000004d75b5788a481eed8386", "owner_type": "user", "drive_type": "normal", "status": "enabled", "used_size": 742962124, "total_size": 17536351469568, "store_id": "b5e90000000041d084733b520ea8b57d", "relative_path": "", "encrypt_mode": "none", "encrypt_data_access": false, "created_at": "2021-03-29T04:02:57.981Z", "permission": null, "subdomain_id": "" } ``` ================================================ FILE: adrive sdk/file.md ================================================ #### 一个文件的信息 POST: `https://api.aliyundrive.com/v2/file/get` ```json { "drive_id": "9600002", "office_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "video_thumbnail_process": "video/snapshot,t_0,f_jpg,m_lfit,w_256,ar_auto,m_fast", "permanently": false, "image_url_process": "image/resize,m_lfit,w_1080/format,webp", "url_expire_sec": 1800 } ``` Response: ```json { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "父文件夹23", "type": "folder", "created_at": "2021-11-05T12:23:02.914Z", "updated_at": "2022-01-24T10:53:36.469Z", "hidden": false, "starred": false, "status": "available", "user_meta": "{\"shares\":[\"2eVphedN4QT\"],\"client\":\"web\"}", "parent_file_id": "root", "encrypt_mode": "none", "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "revision_id": "", "ex_fields_info": { "image_count": 0 }, "trashed": false } ``` #### 一个文件的信息 get_by_path POST: `https://api.aliyundrive.com/v2/file/get_by_path` ```json { "drive_id": "9600002", "file_path": "/zip23" } ``` Response: ```json { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "zip23", "type": "folder", "created_at": "2021-08-28T02:54:02.561Z", "updated_at": "2022-01-24T10:53:36.474Z", "hidden": false, "starred": false, "status": "available", "user_meta": "{\"shares\":[\"mUo000000ka\"]}", "parent_file_id": "root", "encrypt_mode": "none", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "revision_id": "", "trashed": false } ``` #### 一个文件的路径(root[不含] -> file_id 本身) POST: `https://api.aliyundrive.com/adrive/v1/file/get_path` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "items": [ { "trashed": false, "created_at": "2021-11-06T02:51:06.833Z", "domain_id": "bj29", "drive_id": "9600002", "encrypt_mode": "none", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "name": "donghua", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "starred": false, "status": "available", "type": "folder", "updated_at": "2021-11-06T02:51:06.833Z", "user_meta": "{\"client\":\"web\"}", "ex_fields_info": { "image_count": 0 } }, { "trashed": false, "created_at": "2021-11-05T12:23:02.914Z", "domain_id": "bj29", "drive_id": "9600002", "encrypt_mode": "none", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "name": "父文件夹23", "parent_file_id": "root", "starred": false, "status": "available", "type": "folder", "updated_at": "2022-01-24T10:53:36.469Z", "user_meta": "{\"shares\":[\"mUo000000ka\"],\"client\":\"web\"}", "ex_fields_info": { "image_count": 0 } } ] } ``` #### 直接下载 GET: `https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&image_thumbnail_process=image%2Fresize%2Cm_lfit%2Cw_256%2Climit_0%2Fformat%2Cjpg%7Cimage%2Fformat%2Cwebp` ```json ``` Response: ```text Moved Permanently. ``` #### 单个下载地址 GET: `https://api.aliyundrive.com/v2/file/get_download_url` ```json { "drive_id": "9600002", "expires_sec": 0, "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "method": "GET", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "internal_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "expiration": "2022-03-22T14:54:28.057Z", "size": 13, "ratelimit": { "part_speed": -1, "part_size": -1 }, "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1" } ``` #### 打包下载(失效) GET: `https://api.aliyundrive.com/adrive/v1/file/multiDownloadUrl` ```json { "archive_name": "archive_name", "download_infos": [{ "drive_id": "9600002", "files": [{ "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] }] } ``` Response: ```json { "download_url": "https://file.aliyundrive.com/files/archive?task_id=c3f2cd02-0000-0000-8c5a-e80fb1e6f35d&uid=ccff000000004d74b5788a481eed8386" } ``` #### 预览地址(Office) POST: `https://api.aliyundrive.com/v2/file/get_office_preview_url` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "preview_url": "https://office-cn-beijing.imm.aliyuncs.com/office/w/623b00000000d89ef21d4118838aed83de7575ba?_w_tokentype=1&hidecmb=1&simple=1", "access_token": "9eedf665d2464dfcbcabcef640211f0av3" } ``` #### 预览地址(OfficeEdit) POST: `https://api.aliyundrive.com/v2/file/get_office_edit_url` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "option": { "readonly": false } } ``` Response: ```json { "edit_url": "https://office-cn-beijing.imm.aliyuncs.com/office/p/623b00000000d89ef21d4118838aed83de7575ba?_w_tokentype=1", "office_access_token": "75d3976f75a44e4980439ae8ac58ccf1v3", "office_refresh_token": "ca61bb7e51394b62924a09552de868e3v3" } ``` #### 预览地址(Video) POST: `https://api.aliyundrive.com/v2/file/get_video_preview_play_info` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "template_id": "", "url_expire_sec": 3600, "get_subtitle_info": true, "category": "live_transcoding", "drive_id": "9600002" } ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "video_preview_play_info": { "category": "live_transcoding", "meta": { "duration": 6728.747, "width": 3840, "height": 2160, "live_transcoding_meta": { "ts_segment": 10, "ts_total_count": 673, "ts_pre_count": 3 } }, "live_transcoding_task_list": [ { "template_id": "SD", "template_name": "pdsSD", "status": "finished", "stage": "stage_all", "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/lt/E85700000000F9AF45055D714AF43EE744E7262F_51495704429__sha1_bj29/SD/media.m3u8?di=bj29&dr=9600002&f=623b00000000d89ef21d4118838aed83de7575ba&u=9400000000bc480bbcbbb1e074f55a7f&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648039409&x-oss-process=hls%2Fsign&x-oss-signature=qBAS4aI%2F3hT7TFv2mAlgeigtDNtoEK2Vk3BHkCYMXUI%3D&x-oss-signature-version=OSS2" }, { "template_id": "HD", "template_name": "pdsHD", "status": "finished", "stage": "stage_all", "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/lt/E85700000000F9AF45055D714AF43EE744E7262F_51495704429__sha1_bj29/HD/media.m3u8?di=bj29&dr=9600002&f=623b00000000d89ef21d4118838aed83de7575ba&u=9400000000bc480bbcbbb1e074f55a7f&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648039409&x-oss-process=hls%2Fsign&x-oss-signature=xv2x1WcvwqHpadUysuVyG%2FqsC4SGemy8kuXTUQ6G8qA%3D&x-oss-signature-version=OSS2" }, { "template_id": "FHD", "template_name": "pdsFHD", "status": "finished", "stage": "stage_all", "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/lt/E85700000000F9AF45055D714AF43EE744E7262F_51495704429__sha1_bj29/FHD/media.m3u8?di=bj29&dr=9600002&f=623b00000000d89ef21d4118838aed83de7575ba&u=9400000000bc480bbcbbb1e074f55a7f&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648039409&x-oss-process=hls%2Fsign&x-oss-signature=EK6lF3iznE9mW7PHfAQDT5vUZfQRV99aQ%2BS06Ir5P9I%3D&x-oss-signature-version=OSS2" } ], "live_transcoding_subtitle_task_list": [ { "language": "chi", "status": "finished", "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/lt/E85700000000F9AF45055D714AF43EE744E7262F_51495704429__sha1_bj29/subtitle/chi_0.vtt?di=bj29&dr=9600002&f=623b00000000d89ef21d4118838aed83de7575ba&u=9400000000bc480bbcbbb1e074f55a7f&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648039409&x-oss-signature=%2Bywa3xJQWhSbqwhfj0namnSgH0Da5mYg%2F7cEU6hbsOI%3D&x-oss-signature-version=OSS2" } ] } } ``` #### 预览地址(VideoUrl) POST: `https://api.aliyundrive.com/v2/file/get_video_preview_url` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "template_id": "HD", "url_expire_sec": 14400 } ``` Response: ```json { "preview_url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/bj29/sha1_1ADDEFFAB9820EDC1ECEAFA8F9D6511456A4053C_167238406_/HD/master.mp4?di=bj29&dr=9600002&f=623b00000000d89ef21d4118838aed83de7575ba&u=9400000000bc480bbcbbb1e074f55a7f&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648018799&x-oss-signature=KZikIyRSw4c9WkYa2M3Mk4NQjAkdmmg60R6z3I2UJDY%3D&x-oss-signature-version=OSS2" } ``` #### 预览地址(Audio) POST: `https://api.aliyundrive.com/v2/databox/get_audio_play_info` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "template_list": [ { "template_id": "LQ", "status": "finished", "url": "https://ccp-bj29-video-preview.oss-cn-beijing.aliyuncs.com/bj29/sha1_4E2B9BBE6B93AE7DAAF932966EDF43CD307EC5A1_4030744_/LQ/master.mp3?di=bj29\u0026dr=9600002\u0026f=623b00000000d89ef21d4118838aed83de7575ba\u0026u=9400000000bc480bbcbbb1e074f55a7f\u0026x-oss-access-key-id=LTAIsE5mAn2F493Q\u0026x-oss-expires=1647960250\u0026x-oss-signature=S5pC%2BAje9NY4%2FYCYchj%2BC5LnsLZffAezK3%2F24CEjrvk%3D\u0026x-oss-signature-version=OSS2\u0026x-oss-traffic-limit=31457280" } ] } ``` #### 重命名 POST: `https://api.aliyundrive.com/v3/file/update` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "Screenshot_2021-11-23-09-34-20-248_com.tencet.mm.jpg", "check_name_mode": "refuse" } ``` Response: ```json file ``` #### 移动 POST: `https://api.aliyundrive.com/v3/file/move` ```json { "auto_rename": false, "overwrite": false, "drive_id": "9600002", "to_drive_id": "9600002", "to_parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` #### 复制 POST: `https://api.aliyundrive.com/v3/file/copy` ```json { "auto_rename": false, "drive_id": "9600002", "to_drive_id": "9600002", "to_parent_file_id": "root", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "new_name": "" } ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` #### 列表 list POST: `https://api.aliyundrive.com/v2/file/list` ```json { "fields": "*", "drive_id": "9600002", "office_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_direction": "DESC", "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "name", "limit": 50, "video_thumbnail_process": "video/snapshot,t_0,f_jpg,m_lfit,w_256,ar_auto,m_fast", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "all": false, "image_url_process": "image/resize,m_lfit,w_1080/format,webp" } ``` Response: ```json { "items": [ { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "试看版", "type": "folder", "created_at": "2021-11-06T03:15:19.060Z", "updated_at": "2021-11-06T03:15:19.060Z", "hidden": false, "starred": false, "status": "available", "user_meta": "{\"client\":\"web\"}", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "encrypt_mode": "none", "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "creator_name": "myname", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_name": "myname", "revision_id": "" }, { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "压缩包.zip", "type": "file", "content_type": "application/oct-stream", "created_at": "2021-11-06T03:31:13.518Z", "updated_at": "2021-11-06T03:31:13.518Z", "file_extension": "zip", "mime_type": "application/zip", "mime_extension": "zip", "hidden": false, "size": 604818808, "starred": false, "status": "available", "user_meta": "{\"client\":\"web\"}", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "category": "zip", "encrypt_mode": "none", "punish_flag": 0, "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "creator_name": "myname", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_name": "myname", "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111" }, { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "夫知間.jpg", "type": "file", "content_type": "application/oct-stream", "created_at": "2021-11-06T03:16:33.170Z", "updated_at": "2021-11-06T03:16:33.390Z", "file_extension": "jpg", "mime_type": "image/jpeg", "mime_extension": "jpg", "hidden": false, "size": 294767, "starred": false, "status": "available", "user_meta": "{\"client\":\"web\"}", "labels": ["其他事物", "艺术品"], "upload_id": "ED12000000004724833D47B5D5D3C8B9", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "category": "image", "encrypt_mode": "none", "image_media_metadata": { "width": 1627, "height": 2310, "exif": "{\"FileSize\":{\"value\":\"294767\"},\"Format\":{\"value\":\"jpg\"},\"ImageHeight\":{\"value\":\"2310\"},\"ImageWidth\":{\"value\":\"1627\"},\"ResolutionUnit\":{\"value\":\"2\"},\"XResolution\":{\"value\":\"300/1\"},\"YResolution\":{\"value\":\"300/1\"}}", "image_quality": { "overall_score": 0.7194659113883972 } }, "punish_flag": 2, "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_name": "myname", "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111" }, { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "麻冬.zip", "type": "file", "content_type": "application/oct-stream", "created_at": "2021-11-06T03:16:58.189Z", "updated_at": "2021-11-06T03:16:58.189Z", "file_extension": "zip", "mime_type": "application/zip", "mime_extension": "zip", "hidden": false, "size": 575786476, "starred": false, "status": "available", "user_meta": "{\"client\":\"web\"}", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "category": "zip", "encrypt_mode": "none", "punish_flag": 0, "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "creator_name": "myname", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_name": "myname", "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111" } ], "next_marker": "", "punished_file_count": 0 } ``` #### 列表 walk POST: `https://api.aliyundrive.com/v2/file/walk` ```json { "all": false, "drive_id": "9600002", "fields": "*", "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg|image/format,webp", "image_url_process": "image/resize,m_lfit,w_1080/format,webp", "limit": 1000, "marker": "", "office_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg|image/format,webp", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "video_thumbnail_process": "video/snapshot,t_120000,f_jpg,m_lfit,w_256,ar_auto,m_fast" } ``` ```json { "all": false, "drive_id": "9600002", "fields": "*", "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg|image/format,webp", "image_url_process": "image/resize,m_lfit,w_1080/format,webp", "limit": 800, "marker": "", "office_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg|image/format,webp", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "video_thumbnail_process": "video/snapshot,t_120000,f_jpg,m_lfit,w_256,ar_auto,m_fast", "return_total_count": true, "type": "folder" } ``` Response: ```json filelist ``` #### 列表(全量) scan POST: `https://api.aliyundrive.com/v2/file/scan` ```json { "drive_id": "9600002", "category": "image", "limit": 1000 } ``` Response: ```json filelist ``` #### 收藏列表 POST: `https://api.aliyundrive.com/v2/file/list_by_custom_index_key` ```json { "fields": "*", "drive_id": "9600002", "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "limit": 50, "video_thumbnail_process": "video/snapshot,t_0,f_jpg,m_lfit,w_256,ar_auto,m_fast", "parent_file_id": "root", "all": false, "image_url_process": "image/resize,m_lfit,w_1080/format,webp", "custom_index_key": "starred_yes" } ``` Response: ```json filelist ``` #### 收藏文件 POST: `https://api.aliyundrive.com/v3/file/update` ```json { "hidden": false, "drive_id": "9600002", "starred": false, "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "custom_index_key": "" } ``` ```json { "hidden": false, "drive_id": "9600002", "starred": true, "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "custom_index_key": "starred_yes" } ``` Response: ```json file ``` #### 删除文件(从回收站彻底删除) POST: `https://api.aliyundrive.com/v3/file/delete` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002" } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 增加文件 user_tags POST: `https://api.aliyundrive.com/v2/file/put_usertags` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002", "user_tags": [{ "key": "k", "value": "0" }] } ``` Response: ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` #### 删除文件 user_tags POST: `https://api.aliyundrive.com/v2/file/delete_usertags` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002", "key_list": ["k"] } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 未知 list_delta(向相册中上传文件时触发) POST: `https://api.aliyundrive.com/v2/file/list_delta` ```json { "cursor": "MDAwMDAwMDA6MDAwNWRhYjNiYjQ2YTFkMzowMDAwMDAwMQ==", "drive_id": "9600002", "limit": 1000 } ``` Response: ```json { "items": [ { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "op": "create", "file": { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "ic_acloud_launcher.png", "type": "file", "content_type": "image/png", "created_at": "2022-03-22T04:28:47.498Z", "updated_at": "2022-03-22T04:28:47.498Z", "file_extension": "png", "hidden": false, "size": 6414, "starred": false, "status": "available", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "parent_file_id": "root", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "category": "image", "encrypt_mode": "none", "image_media_metadata": { "image_quality": {} }, "characteristic_hash": "e14f000000004eb4ae91b8a4a723c2a11361928f", "revision_id": "" }, "current_category": "image" }, { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "op": "update", "file": { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "labels": ["其他事物", "蓝色"], "category": "image", "image_media_metadata": { "width": 108, "height": 108, "image_quality": { "overall_score": 0.4490000009536743 } }, "revision_id": "" }, "current_category": "image" } ], "has_more": false, "cursor": "MDAwMDAwMDA6MDAwNWRhYzcwYzk2ZTM4OTowMDAwMDAwMQ==" } ``` ================================================ FILE: adrive sdk/filedir.md ================================================ #### 文件夹大小 POST: `https://api.aliyundrive.com/adrive/v1/file/get_folder_size_info` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "size": 67200, "folder_count": 0, "file_count": 600, "reach_limit": true } ``` #### 批量读取文件夹封面 POST: `https://api.aliyundrive.com/adrive/v1/file/cover/batchGet` ```json { "drive_id": "9600002", "file_ids": ["623b00000000d89ef21d4118838aed83de7575ba", "6061000000001af7c3034e3590ea7d5a50f58015"] } ``` Response: ```json { "items": [ { "folder_file_id": "623b00000000d89ef21d4118838aed83de7575ba", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/RV5OBihM%2F...", "cover_file_name": "反贪5.mp4", "cover_file_category": "video" }, { "folder_file_id": "623b00000000d89ef21d4118838aed83de7575ba", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_name": "bbbc", "cover_file_category": "others" } ] } ``` #### 读取文件夹封面 POST: `https://api.aliyundrive.com/adrive/v1/file/cover/get` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```json { "folder_file_id": "623b00000000d89ef21d4118838aed83de7575ba", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/RV5OBihM%2F...", "cover_file_name": "firmware.3911(1).dat", "cover_file_category": "video" } ``` #### 设置-读取开启文件夹封面 POST: `https://api.aliyundrive.com/adrive/v1/file/cover/config/get` ```json {} ``` Response: ```json {"enable":true} ``` #### 设置-保存开启文件夹封面 POST: `https://api.aliyundrive.com/adrive/v1/file/cover/config/set` ```json {"enable":true} ``` Response: ```text HTTP/1.1 200 OK ``` ================================================ FILE: adrive sdk/fileupload.md ================================================ #### 上传文件 pre_hash POST: `https://api.aliyundrive.com/v2/file/create_with_proof` ```json { "auto_rename": true, "content_type": "application/octet-stream", "drive_id": "9600002", "hidden": false, "name": "Version 89", "parent_file_id": "root", "part_info_list": [{ "part_number": 1, "part_size": 4094816 }], "pre_hash": "BF9800000000645AAAE912D616759A7C96CC8BFA", "size": 4094816, "type": "file" } ``` Response: ```json { "parent_file_id": "", "file_name": "Version 89", "pre_hash": "BF9800000000645AAAE912D616759A7C96CC8BFA", "code": "PreHashMatched", "message": "Pre hash matched." } ``` #### 上传文件 POST: `https://api.aliyundrive.com/v2/file/create_with_proof` ```json { "auto_rename": true, "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/octet-stream", "drive_id": "9600002", "hidden": false, "name": "Version 89", "parent_file_id": "root", "part_info_list": [{ "part_number": 1, "part_size": 4094816 }], "proof_code": "h49KOtR0okk=", "proof_version": "v1", "size": 4094816, "type": "file" } ``` Response: ```json //秒传了 { "parent_file_id": "root", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "rapid_upload": true, "type": "file", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "domain_id": "bj29", "drive_id": "9600002", "file_name": "Version 89", "encrypt_mode": "none", "location": "cn-beijing" } ``` ```json //正常上传 { "parent_file_id": "root", "part_info_list": [ { "part_number": 1, "part_size": 950, "upload_url": "https://bj29.cn-beijing.data.alicloudccp.com/AfD0AB6n%2F9600002%2F623b00000000d89ef21d4118838aed83de7575ba%2F623b000000006480042148a5bb586d3c2f053ec8?partNumber=1&uploadId=1382108D9D2C4182B2D4B9AEBB53E2E4&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648043319&x-oss-signature=rIWzJDDihQwWO%2FoAxPPjQV2Y0%2F8FXH3h7rd01w%2Biin8%3D&x-oss-signature-version=OSS2", "internal_upload_url": "http://ccp-bj29-bj-1592982087.oss-cn-beijing-internal.aliyuncs.com/AfD0AB6n%2F9600002%2F623b00000000d89ef21d4118838aed83de7575ba%2F623b000000006480042148a5bb586d3c2f053ec8?partNumber=1&uploadId=1382108D9D2C4182B2D4B9AEBB53E2E4&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648043319&x-oss-signature=rIWzJDDihQwWO%2FoAxPPjQV2Y0%2F8FXH3h7rd01w%2Biin8%3D&x-oss-signature-version=OSS2", "content_type": "" } ], "upload_id": "ED12000000004724833D47B5D5D3C8B9", "rapid_upload": false, "type": "file", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "domain_id": "bj29", "drive_id": "9600002", "file_name": "FiddlerRoot.crt", "encrypt_mode": "none", "location": "cn-beijing" } ``` //循环上传分片数据 PUT `https://bj29.cn-beijing.data.alicloudccp.com/AfD0AB6n%2F9600002%2F623b00000000d89ef21d4118838aed83de7575ba%2F623b000000006480042148a5bb586d3c2f053ec8?partNumber=1&uploadId=1382108D9D2C4182B2D4B9AEBB53E2E4&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-expires=1648043319&x-oss-signature=rIWzJDDihQwWO%2FoAxPPjQV2Y0%2F8FXH3h7rd01w%2Biin8%3D&x-oss-signature-version=OSS2` #### 合并分片 POST: `https://api.aliyundrive.com/v2/file/complete` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "upload_id": "ED12000000004724833D47B5D5D3C8B9" } ``` Response: ```json { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "FiddlerRoot.crt", "type": "file", "content_type": "application/x-x509-ca-cert", "created_at": "2022-03-23T12:48:39.888Z", "updated_at": "2022-03-23T12:48:40.449Z", "file_extension": "crt", "hidden": false, "size": 950, "starred": false, "status": "available", "user_meta": "{\"client\":\"Android\"}", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "parent_file_id": "root", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "category": "others", "encrypt_mode": "none", "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111", "location": "cn-beijing" } ``` ================================================ FILE: adrive sdk/image.md ================================================ #### 探索-人物列表 POST: `https://api.aliyundrive.com/v2/image/list_facegroups` ```json { "drive_id": "9600002", "limit": 100 } ``` Response: ```json { "items": [ { "group_id": "Group-00000000-1703-4fc0-bf56-369478ed14df", "group_name": " ", "image_count": 15, "created_at": "2021-09-08T21:46:02.413048705+08:00", "updated_at": "2021-11-08T13:58:11.452257679+08:00", "group_cover_url": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/nIaV4oIe%2F...", "group_cover_file_id": "613800000000c99442f44b99b93b3bdd40e21836", "group_cover_face_boundary": { "Width": 445, "Height": 532, "Top": 328, "Left": 650 } } ], "next_marker": "" } ``` #### 探索-人物照片列表 POST: `https://api.aliyundrive.com/v2/file/search` ```json { "drive_id": "9600002", "limit": 100, "order_by": "created_at DESC", "query": "type = 'file' and category in ['image', 'video'] and face_group_id = 'Group-00000000-1703-4fc0-bf56-369478ed14df' and status = 'available' and hidden = false", "return_total_count": true } ``` Response: ```json { "items": [ { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "43.jpg", "type": "file", "content_type": "application/oct-stream", "created_at": "2021-09-08T13:46:00.764Z", "updated_at": "2021-09-08T13:46:02.889Z", "file_extension": "jpg", "mime_type": "image/jpeg", "mime_extension": "jpg", "hidden": false, "size": 2178603, "starred": false, "status": "available", "labels": ["日常行为", "职业&角色"], "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "category": "image", "encrypt_mode": "none", "image_media_metadata": { "width": 2400, "height": 3600, "faces": "[{\"FaceConfidence\":0.9466279149055481,\"EmotionConfidence\":0.9990111589431763,\"ImageUri\":\"\",\"FaceQuality\":0.7725782990455627,\"Similarity\":0,\"ExternalId\":\"\",\"Attractive\":0.93,\"AttractiveConfidence\":0,\"Age\":23,\"AgeConfidence\":0,\"Gender\":\"FEMALE\",\"Emotion\":\"HAPPY\",\"GenderConfidence\":1,\"FaceId\":\"45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3\",\"GroupId\":\"Group-00000000-1703-4fc0-bf56-369478ed14df\",\"FaceAttributes\":{\"Glasses\":\"NONE\",\"MaskConfidence\":1,\"Mask\":\"NONE\",\"GlassesConfidence\":1,\"Beard\":\"NONE\",\"BeardConfidence\":1,\"FaceBoundary\":{\"Width\":445,\"Height\":532,\"Top\":328,\"Left\":650},\"HeadPose\":{\"Pitch\":18.937170028686523,\"Roll\":30.32413101196289,\"Yaw\":9.59316635131836}},\"EmotionDetails\":{\"SURPRISED\":0.0000041519870137562975,\"HAPPY\":0.9990111589431763,\"ANGRY\":0.0000027373464490665356,\"DISGUSTED\":0.000007709058991167694,\"SAD\":0.0001263682497665286,\"CALM\":0.0008296924061141908,\"SCARED\":0.0000020987527022953145},\"SimilarFaces\":null}]", "faces_thumbnail": [ { "face_id": "45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3", "face_group_id": "Group-00000000-1703-4fc0-bf56-369478ed14df", "face_thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ], "image_quality": { "overall_score": 0.6911791563034058 } }, "punish_flag": 2, "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111" } ], "next_marker": "", "total_count": 15 } ``` #### 探索-从人物的照片中移除一张 POST: `https://api.aliyundrive.com/v2/albums/unassign_facegroup_item` ```json { "face_group_id": "Group-00000000-1703-4fc0-bf56-369478ed14df", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002" } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 探索-修改人物 name,头像,remarks POST: `https://api.aliyundrive.com/v2/image/update_facegroup_info` ```json { "drive_id": "9600002", "group_cover_face_id": "45f700000000ac19ffbf56adcaa98e3944f28c087cd36b9bc1acde5ae5829fa3", "group_id": "Group-00000000-1703-4fc0-bf56-369478ed14df", "group_name": "fang", "remarks": "-" } ``` Response: ```json { "drive_id": "9600002", "group_id": "Group-00000000-1703-4fc0-bf56-369478ed14df" } ``` #### 探索-地点列表 POST: `https://api.aliyundrive.com/v2/image/list_address_groups` ```json { "all": false, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "video_thumbnail_process": "video/snapshot,t_7000,f_jpg,w_800,h_600,ar_auto,m_fast", "drive_id": "9600002" } ``` Response: ```json { "items": [], "next_marker": "" } ``` #### 探索-地点列表 POST: `https://api.aliyundrive.com/v2/image/list_address_groups` ```json { "drive_id": "9600002", "address_names": ["杭州市", "北京市"] } ``` Response: ```json { "items": [] } ``` #### 探索-标记列表 POST: `https://api.aliyundrive.com/v2/image/list_tags` ```json { "all": false, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "video_thumbnail_process": "video/snapshot,t_7000,f_jpg,w_800,h_600,ar_auto,m_fast", "drive_id": "9600002" } ``` Response: ```json { "tags": [ { "name": "摄影", "count": 75, "cover_url": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/ew5HgHNJ%2F...", "cover_file_id": "6061000000001af7c3034e3590ea7d5a50f58015", "cover_file_category": "", "cover_tag_confidence": 1, "cover_overall_score": 0.7421030402183533 } ] } ``` #### drive 内图片总数 POST: `https://api.aliyundrive.com/v2/image/get_photo_count` ```json { "drive_id": "9600002" } ``` Response: ```json { "image_count": 126 } ``` ================================================ FILE: adrive sdk/member.md ================================================ #### 列出已订阅 POST: `https://api.aliyundrive.com/adrive/v1/member/list_following` ```json { "limit": 50, "order_by": "updated_at", "order_direction": "DESC" } ``` Response: ```json { "items": [ { "description": "中国国家地理景观官方账号,带你领略目酣神醉的壮美景观、发现中国各地独具特色的人文胜迹。", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "中国国家地理景观", "phone": "136***902", "is_following": true, "has_unread_message": true, "latest_messages": [ { "creator": { "description": "中国国家地理景观官方账号,带你领略目酣神醉的壮美景观、发现中国各地独具特色的人文胜迹。", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "中国国家地理景观", "phone": "136***902" }, "action": "sharelink.create", "content": { "share": { "popularity": 6019, "share_id": "6RRP4gDWwzE", "share_msg": "「广东100个最美观景拍摄点-...拍摄季节:四季).jpg」,点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_name": "广东100个最美观景拍摄点-...拍摄季节:四季).jpg", "description": "", "expiration": "", "expired": false, "share_pwd": "", "share_url": "https://www.aliyundrive.com/s/6RRP4gDWwzE", "creator": "01d1ea604d644cfb83ac7e9be530db8e", "drive_id": "347756450", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "preview_count": 2139, "save_count": 802, "download_count": 27, "status": "enabled", "created_at": "2022-03-20T13:55:42.630Z", "updated_at": "2022-03-21T08:04:11.464Z", "first_file": { "trashed": false, "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2022-02-28T09:09:54.329Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "347756450", "encrypt_mode": "none", "file_extension": "jpg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "height": 1464, "image_quality": { "overall_score": 0.6488162279129028 }, "width": 2500 }, "labels": ["旅游&地理", "体育运动", "植物", "徒步", "自然景观", "植被", "高地", "山脊", "山峰", "丘陵", "山", "云", "山中避暑地", "山脉", "雾", "天空", "荒野", "雾景", "森林"], "mime_type": "image/jpeg", "name": "广东100个最美观景拍摄点-油岭瑶寨(最佳拍摄季节:四季).jpg", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 3829229, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-02-28T09:09:57.283Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"desktop\"}" }, "allow_subscribe": false, "current_sync_status": 3, "popularity_str": "6K", "popularity_emoji": "\uD83D\uDD25", "full_share_msg": "「广东100个最美观景拍摄点-...拍摄季节:四季).jpg」https://www.aliyundrive.com/s/6RRP4gDWwzE\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "display_name": "广东100个最美观景拍摄点-油岭瑶寨(最佳拍摄季节:四季).jpg" }, "share_id": "6RRP4gDWwzE", "drive_id": "347756450", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "file_list": [ { "category": "image", "created_at": "2022-02-28T09:09:54.329Z", "domain_id": "bj29", "drive_id": "347756450", "file_extension": "jpg", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "image_media_metadata": { "height": 1464, "width": 2500 }, "mime_type": "image/jpeg", "name": "广东100个最美观景拍摄点-油岭瑶寨(最佳拍摄季节:四季).jpg", "parent_file_id": "root", "punish_flag": 0, "share_id": "6RRP4gDWwzE", "size": 3829229, "thumbnail": "https://pdsapi.aliyundrive.com/v2/redirect?id=5c2b8c638c27409f8516c5fce2c320bc", "type": "file", "updated_at": "2022-02-28T09:09:57.283Z" } ] }, "created": 1647784542657, "creator_id": "01d1ea604d644cfb83ac7e9be530db8e", "sequence_id": 1647784542661000, "display_action": "分享了 广东100个最美观景拍摄点-油岭瑶寨(最佳拍摄季节:四季).jpg" } ] } ], "total_count": 2 } ``` #### 标记已读(订阅的一个用户有动态) POST: `https://api.aliyundrive.com/adrive/v1/member/mark_read` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f" } ``` Response: ```json {} ``` #### 取消订阅 POST: `https://api.aliyundrive.com/adrive/v1/member/unfollow_user` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f" } ``` Response: ```json {} ``` #### 增加订阅 POST: `https://api.aliyundrive.com/adrive/v1/member/follow_user` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f" } ``` Response: ```json {} ``` ================================================ FILE: adrive sdk/note.md ================================================ #### 笔记-drive_id POST: `https://api.aliyundrive.com/anote/v1/drive/info` ```json ``` Response: ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002" } ``` #### 笔记列表 POST: `https://api.aliyundrive.com/anote/v1/note/list` ```json { "order_direction": "desc", "order_by": 2, "media_category_list": ["image"], "limit": 100, "status": 0 } ``` Response: ```json { "result": [ { "status": 0, "top": 0, "title": "高三总复习CETV.mp4", "summary": " 回顾改革\n三生俄文\n", "media": "[]", "type": "common", "value": null, "version": null, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1647859789126, "updated_at": 1647860036653, "media_list": [] }, { "status": 0, "top": 0, "title": "iyvxb", "summary": "", "media": "[]", "type": "common", "value": null, "version": null, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1635075204623, "updated_at": 1635075211182, "media_list": [] }, { "status": 0, "top": 0, "title": "ggg", "summary": "ggc\n", "media": "[]", "type": "common", "value": null, "version": null, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1635074956002, "updated_at": 1635074983777, "media_list": [] }, { "status": 0, "top": 0, "title": "欢迎使用笔记", "summary": "阿里云盘「笔记」是你在数字生活中的又一个伙伴,帮助你随时记录生活、学习、工作中的各种重要信息。你的每一次起心动念,都会留下属于自己的思想痕迹。抓住它们、记录它们,它们会是你在数字世界中重要的资产。 · 笔记能做什么?\n · 阿里云盘「笔记」将有两大核心能力:\n · 1. 在云盘中跨云服务记录想法 · 1. 管理信息、知识 · \uD83D\uDC47下面我们简单为大家介绍一下笔记的具体功能:\n · 灵活强大的编辑器\n", "media": "[]", "type": "common", "value": null, "version": null, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1635074953183, "updated_at": 1635074953183, "media_list": [ { "fileId": "61754388dab29ac982464de485c38a5f67d07bc1", "driveId": "9600002", "resourceType": null, "dataPreviewUrl": null, "dataSrc": null, "dataAppId": null, "dataObjectId": null, "dataCategory": null }, { "fileId": "61754389b1a68525c17d4235af597722dbd32370", "driveId": "9600002", "resourceType": null, "dataPreviewUrl": null, "dataSrc": null, "dataAppId": null, "dataObjectId": null, "dataCategory": null }, { "fileId": "61754389ead68e4cce6b4499b5512585d94a011b", "driveId": "9600002", "resourceType": null, "dataPreviewUrl": null, "dataSrc": null, "dataAppId": null, "dataObjectId": null, "dataCategory": null } ] } ], "marker": "", "total_count": 4 } ``` #### 一个笔记的简介 POST: `https://api.aliyundrive.com/anote/v1/note/getNote` ```json { "exclude_fields": ["value"], "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d" } ``` Response: ```json { "status": 0, "top": 0, "title": "欢迎使用笔记", "summary": "阿里云盘「笔记」是你在数字生活中的又一个伙伴,帮助你随时记录生活、学习、工作中的各种重要信息。你的每一次起心动念,都会留下属于自己的思想痕迹。抓住它们、记录它们,它们会是你在数字世界中重要的资产。 · 笔记能做什么?\n · 阿里云盘「笔记」将有两大核心能力:\n · 1. 在云盘中跨云服务记录想法 · 1. 管理信息、知识 · \uD83D\uDC47下面我们简单为大家介绍一下笔记的具体功能:\n · 灵活强大的编辑器\n", "media": "[]", "type": "common", "value": null, "version": 1, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1635074953183, "updated_at": 1635074953183, "media_list": [ { "fileId": null, "driveId": null, "resourceType": null, "dataPreviewUrl": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "dataSrc": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "dataAppId": "anote", "dataObjectId": "9600002_61754389ead68e4cce6b4499b5512585d94a011b", "dataCategory": "image" } ] } ``` #### 一个笔记的完整内容 POST: `https://api.aliyundrive.com/anote/v1/note/getNote` ```json { "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d" } ``` Response: ```json { "status": 0, "top": 0, "title": "欢迎使用笔记", "summary": "阿里云盘「笔记」是你在数字生活中的又一个伙伴,帮助你随时记录生活、学习、工作中的各种重要信息。你的每一次起心动念,都会留下属于自己的思想痕迹。抓住它们、记录它们,它们会是你在数字世界中重要的资产。 · 笔记能做什么?\n · 阿里云盘「笔记」将有两大核心能力:\n · 1. 在云盘中跨云服务记录想法 · 1. 管理信息、知识 · \uD83D\uDC47下面我们简单为大家介绍一下笔记的具体功能:\n · 灵活强大的编辑器\n", "media": "[]", "type": "common", "value": [ "root", {}, [ "p", {}, [ "span", { "data-type": "text" }, [ "span", { "data-type": "leaf" }, "阿里云盘「笔记」是你在数字生活中的又一个伙伴,帮助你随时记录生活、学习、工作中的各种重要信息。你的每一次起心动念,都会留下属于自己的思想痕迹。抓住它们、记录它们,它们会是你在数字世界中重要的资产。" ] ] ], [ "h2", { "spacing": { "before": 14.666666666666668, "after": 14.666666666666668, "line": 0.8529411764705882 } }, ["span", { "data-type": "text" }, ["span", { "bold": true, "sz": 16, "szUnit": "pt", "data-type": "leaf" }, "笔记能做什么?\n"]] ], ["p", { "ind": { "left": 0 } }, ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, "阿里云盘「笔记」将有两大核心能力:\n"]]], [ "p", { "ind": { "left": 0 }, "list": { "listId": "kak98pl4pzh", "level": 0, "isOrdered": true, "isTaskList": false, "listStyleType": "DEC_LEN_LROM_P", "symbolStyle": {}, "listStyle": { "format": "decimal", "text": "%1.", "align": "left" }, "hideSymbol": false } }, ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, "在云盘中跨"], ["span", { "bold": true, "data-type": "leaf" }, "云服务"], ["span", { "data-type": "leaf" }, "记录想法"]] ], [ "p", {}, ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, ""]], [ "object", { "dataCategory": "image", "dataId": "0079012b-d4c9-43b0-ad46-a394ef944aa4", "dataAppId": "anote", "dataObjectId": "9600002_61754388dab29ac982464de485c38a5f67d07bc1", "dataResourceType": "file", "dataMetadata": { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }, "aslMetadata": {}, "dataPreviewUrl": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "dataSrc": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." }, ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, ""]] ], ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, "\n"]] ] ], "version": 1, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1635074953183, "updated_at": 1635074953183, "media_list": [ { "fileId": null, "driveId": null, "resourceType": null, "dataPreviewUrl": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "dataSrc": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "dataAppId": "anote", "dataObjectId": "9600002_61754389b1a68525c17d4235af597722dbd32370", "dataCategory": "image" } ] } ``` #### 更新一个笔记标题 POST: `https://api.aliyundrive.com/anote/v1/note/updateTitle` ```json { "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "title": "我" } ``` Response: ```text HTTP/1.1 200 OK ``` #### 更新一个笔记内容 POST: `https://api.aliyundrive.com/anote/v1/note/patch` ```json { "ops": [ { "op": "add", "path": "/5", "value": ["p", {}, ["span", { "data-type": "text" }, ["span", { "data-type": "leaf" }, "三生俄文将和 v 将祸福倚伏具有肌肤光滑"]]] }, { "op": "remove", "path": "/6" } ], "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "version": 7, "summary": " 回顾改革\n三生俄文将和 v 将祸福倚伏具有肌肤光滑\n" } ``` Response: ```json { "docId": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "version": 8 } ``` https://www.aliyundrive.com/static/note-mobile-editor?docId=feb4c7c1f55fa0a7f69588aeed0567c8e5c31d1d #### 置顶一个笔记 POST: `https://api.aliyundrive.com/anote/v1/note/batchUpdate` ```json { "doc_ids": ["feb400000000a0a7f69588aeed0567c8e5c31d1d"], "operation": 1 } ``` Response: ```json { "result": [] } ``` #### 删除一个笔记 POST: `https://api.aliyundrive.com/anote/v1/note/batchUpdate` ```json { "doc_ids": ["feb400000000a0a7f69588aeed0567c8e5c31d1d"], "operation": 2 } ``` Response: ```json { "result": [] } ``` #### 新建一个笔记 POST: `https://api.aliyundrive.com/anote/v1/note/create` ```json { "value": ["root", {}], "title": "", "drive_id": "" } ``` Response: ```json { "status": 0, "top": 0, "title": "", "summary": "", "media": "[]", "type": "common", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "doc_id": "feb400000000a0a7f69588aeed0567c8e5c31d1d", "drive_id": "9600002", "created_at": 1647862805027, "updated_at": 1647862805027, "media_list": null } ``` ================================================ FILE: adrive sdk/offline.md ================================================ #### 离线任务列表 POST: `https://api.aliyundrive.com/adrive/v1/offline/jobsList` ```json {} ``` Response: ```json { "maxResults": 10, "nextToken": "", "result": [] } ``` ================================================ FILE: adrive sdk/recyclebin.md ================================================ #### 列出回收站 POST: `https://api.aliyundrive.com/v2/recyclebin/list` ```json { "fields": "*", "all": false, "drive_id": "9600002", "limit": 50 } ``` Response: ```json { "items": [ { "drive_id": "9600002", "domain_id": "bj29", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "name": "[1.3.1].mp4", "type": "file", "content_type": "application/oct-stream", "created_at": "2022-01-19T04:51:12.832Z", "updated_at": "2022-03-10T03:10:04.074Z", "trashed_at": "2022-03-10T03:10:04.074Z", "file_extension": "mp4", "mime_type": "application/octet-stream", "mime_extension": "unknown", "hidden": false, "size": 94814980, "starred": false, "status": "available", "labels": ["艺术品"], "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "crc64_hash": "1548000000008183211", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "category": "video", "encrypt_mode": "none", "video_media_metadata": { "width": 1280, "height": 720, "video_media_video_stream": [{ "duration": "1530.680000", "clarity": "720", "fps": "25/1", "code_name": "h264" }], "video_media_audio_stream": [{ "duration": "1530.581333", "channels": 2, "channel_layout": "stereo", "bit_rate": "143625", "code_name": "aac", "sample_rate": "48000" }], "duration": "1530.701333" }, "punish_flag": 0, "creator_type": "User", "creator_id": "9400000000bc480bbcbbb1e074f55a7f", "creator_name": "myname", "last_modifier_type": "User", "last_modifier_id": "9400000000bc480bbcbbb1e074f55a7f", "last_modifier_name": "myname", "revision_id": "6138000000000b81a8164550b1e7cba1d7fbe111" } ], "next_marker": "" } ``` #### 恢复文件 POST: `https://api.aliyundrive.com/v2/recyclebin/restore` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002" } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 删除文件(放入回收站) POST: `https://api.aliyundrive.com/v2/recyclebin/trash` ```json { "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 删除文件(从回收站彻底删除) POST: `https://api.aliyundrive.com/v3/file/delete` ```json { "permanently": true, "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002" } ``` Response: ```text HTTP/1.1 204 No Content ``` #### 清空回收站 POST: `https://api.aliyundrive.com/v2/recyclebin/clear` ```json { "drive_id": "9600002" } ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "task_id": "e026000000007f609bcd6aa71b8fde94" } ``` ================================================ FILE: adrive sdk/reddot.md ================================================ #### 订阅的账号有更新 POST: `https://api.aliyundrive.com/adrive/v1/reddot/get` ```json {} ``` Response: ```json { "items": [ { "code": "followed_user_has_new_activity", "context": { "creator": { "description": "中国国家地理景观官方账号,带你领略目酣神醉的壮美景观、发现中国各地独具特色的人文胜迹。", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "中国国家地理景观", "phone": "136***902" } } } ] } ``` #### 标记已读 POST: `https://api.aliyundrive.com/adrive/v1/reddot/read` ```json {"code":"followed_user_has_new_activity"} ``` Response: ```json {} ``` ================================================ FILE: adrive sdk/sbox.md ================================================ #### 保险箱 POST: `https://api.aliyundrive.com/v2/sbox/get` ```json {} ``` Response: ```json { "drive_id": "9600002", "sbox_used_size": 0, "sbox_real_used_size": 0, "sbox_total_size": 53687091200, "recommend_vip": "svip", "pin_setup": true, "locked": true, "insurance_enabled": false } ``` #### 解锁 POST: `https://api.aliyundrive.com/v2/sbox/unlock` ```json { "drive_id": "9600002", "app_id": "25dzX3vbYqktVxyX", "encrypted_pin": "pteN00000000/gLZpQaFKA==", "encrypted_key": "nNaV......r13doYbpmJxag==" } ``` Response: ```json { "drive_id": "9600002" } ``` #### 重新锁定 POST: `https://api.aliyundrive.com/v2/sbox/lock` ```json {"drive_id":"9600002"} ``` Response: ```json { "drive_id": "9600002" } ``` ================================================ FILE: adrive sdk/search.md ================================================ #### 首页 widgets POST: `https://api.aliyundrive.com/v2/file/search` ```json //截图 { "return_total_count": true, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "last_access_at DESC,updated_at DESC,image_time DESC", "query": "(label = '手机截图' or label = '截图') and category in ['video','image'] and status = 'available' and hidden = false", "limit": 100, "drive_id": "9600002" } ``` ```json //证件 { "return_total_count": true, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "last_access_at DESC,updated_at DESC,image_time DESC", "query": "(label = '身份证明' or label = '证件' or label = '身份证' or label = '银行卡' or label = '护照') and category in ['video','image'] and status = 'available' and hidden = false", "limit": 100, "drive_id": "9600002" } ``` ```json //最近图片 { "return_total_count": true, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "last_access_at DESC,updated_at DESC,image_time DESC", "query": "category = 'image' and status = 'available' and hidden = false", "limit": 100, "drive_id": "9600002" } ``` ```json //最近视频 { "return_total_count": true, "image_thumbnail_process": "image/resize,m_lfit,w_256,limit_0/format,jpg", "order_by": "last_access_at DESC,updated_at DESC,image_time DESC", "query": "category = 'video' and status = 'available' and hidden = false", "limit": 100, "drive_id": "9600002" } ``` Response: ```json filelist ``` #### 列出人物(face)的图片 POST: `https://api.aliyundrive.com/v2/file/search` ```json { "drive_id": "9600002", "limit": 100, "order_by": "created_at DESC", "query": "type = 'file' and category in ['image', 'video'] and face_group_id = 'Group-00000000-1703-4fc0-bf56-369478ed14df' and status = 'available' and hidden = false", "return_total_count": true } ``` Response: ```json filelist ``` ================================================ FILE: adrive sdk/sfiia.md ================================================ #### 文件中的图片 POST: `https://api.aliyundrive.com/adrive/v1/sfiia/get_recommends` ```json { "drive_id": "9600002" } ``` Response: ```json { "items": [ { "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-10-16T02:10:51.625Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "png", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "labels": ["衣服", "外貌特征", "其他事物", "艺术品", "笑脸", "墨镜", "护目镜", "微笑", "颜色", "动画", "黄色"], "mime_type": "image/png", "name": "cool_11.png", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 80480, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2021-10-16T02:10:51.625Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..." } ], "total_image_count": 28943 } ``` ================================================ FILE: adrive sdk/share.md ================================================ #### 我创建的分享链接 POST: `https://api.aliyundrive.com/adrive/v3/share_link/list` ```json { "category": "file,album", "order_direction": "DESC", "order_by": "created_at", "creator": "9400000000bc480bbcbbb1e074f55a7f", "limit": 100 } ``` Response: ```json { "items": [ { "popularity": 6, "share_id": "9Q00000000L", "share_msg": "「testali.alimc」,点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_name": "testali.alimc", "description": "", "expiration": "2022-04-08T10:29:22.000Z", "expired": false, "share_pwd": "", "share_url": "https://www.aliyundrive.com/s/9Q00000000L", "creator": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "preview_count": 2, "save_count": 0, "download_count": 0, "status": "enabled", "created_at": "2022-03-09T10:29:23.272Z", "updated_at": "2022-03-19T04:54:26.435Z", "first_file": { "trashed": false, "category": "others", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2022-03-09T10:29:02.190Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "alimc", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "mime_type": "text/plain; charset=utf-8", "name": "testali.alimc", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 7318, "starred": false, "status": "available", "type": "file", "updated_at": "2022-03-09T10:29:51.415Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}" }, "current_sync_status": 1, "next_sync_status": 2, "full_share_msg": "「testali.alimc」https://www.aliyundrive.com/s/9Q00000000L\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "popularity_str": "6", "display_name": "testali.alimc" }, { "album": { "owner": "ccff000000004d75b5788a481eed8386", "name": "fff", "description": "", "album_id": "cfe400000000478599575b69356c5a4962383669", "file_count": 0, "image_count": 0, "video_count": 0, "created_at": 1642306691089, "updated_at": 1642306691089, "is_sharing": true }, "popularity": 9, "share_id": "9Q00000000L", "share_msg": "我用阿里云盘分享了相簿「fff」,复制这段内容打开「阿里云盘」APP 即可获取。\n提取码: ni5u", "share_name": "fff", "description": "", "expiration": "2022-04-06T03:56:13.839Z", "expired": false, "share_pwd": "ni5u", "share_url": "https://www.aliyundrive.com/s/9Q00000000L", "creator": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "album_id": "cfe400000000478599575b69356c5a4962383669", "preview_count": 4, "save_count": 0, "download_count": 0, "status": "enabled", "created_at": "2022-03-07T03:56:13.789Z", "updated_at": "2022-03-09T13:37:25.895Z", "full_share_msg": "相簿分享「fff」https://www.aliyundrive.com/s/9Q00000000L 提取码: ni5u\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP,使用相册备份节省手机空间,体验智能分类和回忆自动生成。", "popularity_str": "9", "display_name": "相簿 ∙ fff" } ], "next_marker": "" } ``` #### 读取一条自己的分享链接的信息 POST: `https://api.aliyundrive.com/adrive/v2/share_link/get` ```json { "share_id": "9Q00000000L" } ``` Response: ```json { "popularity": 3, "share_id": "9Q00000000L", "share_msg": "「返回.gif」,点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_name": "返回.gif", "description": "", "expiration": "2022-04-20T04:41:04.509Z", "expired": false, "share_pwd": "", "share_url": "https://www.aliyundrive.com/s/9Q00000000L", "creator": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "preview_count": 0, "save_count": 0, "download_count": 0, "status": "enabled", "created_at": "2021-11-09T17:47:43.516Z", "updated_at": "2022-03-21T04:41:05.159Z", "first_file": { "trashed": false, "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-11-05T13:40:00.994Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "gif", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "exif": "{\"FileSize\":{\"value\":\"58391\"},\"Format\":{\"value\":\"gif\"},\"ImageHeight\":{\"value\":\"556\"},\"ImageWidth\":{\"value\":\"608\"}}", "height": 556, "image_quality": { "overall_score": 0.6453010439872742 }, "width": 608 }, "labels": ["其他场景", "其他事物", "日常用品", "颜色", "文本", "手机截图", "信", "蓝色"], "mime_type": "image/gif", "name": "返回.gif", "parent_file_id": "root", "punish_flag": 0, "size": 58391, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-01-24T10:53:36.473Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}" }, "current_sync_status": 1, "next_sync_status": 2, "popularity_str": "3", "full_share_msg": "「返回.gif」https://www.aliyundrive.com/s/9Q00000000L\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "display_name": "返回.gif" } ``` #### 复制分享链接到剪切板 POST: `https://api.aliyundrive.com/adrive/v2/share_link/get_share_msg` ```json { "share_id": "9Q00000000L" } ``` Response: ```json { "full_share_msg": "「返回.gif」https://www.aliyundrive.com/s/9Q00000000L\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_url": "https://www.aliyundrive.com/s/9Q00000000L" } ``` #### 修改分享链接 POST: `https://api.aliyundrive.com/adrive/v2/share_link/update` ```json { "share_id": "9Q00000000L", "expiration": "2022-04-20T04:41:04.509Z" } ``` Response: ```json { "popularity": 3, "share_id": "9Q00000000L", "share_msg": "「返回.gif」,点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_name": "返回.gif", "description": "", "expiration": "2022-04-20T04:41:04.509Z", "expired": false, "share_pwd": "", "share_url": "https://www.aliyundrive.com/s/9Q00000000L", "creator": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "preview_count": 0, "save_count": 0, "download_count": 0, "status": "enabled", "created_at": "2021-11-09T17:47:43.516Z", "updated_at": "2022-03-21T04:41:05.159Z", "first_file": { "trashed": false, "category": "image", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-11-05T13:40:00.994Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "gif", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "image_media_metadata": { "height": 556, "image_quality": { "overall_score": 0.6453010439872742 }, "width": 608 }, "labels": ["其他场景", "其他事物", "日常用品", "颜色", "文本", "手机截图", "信", "蓝色"], "mime_type": "image/gif", "name": "返回.gif", "parent_file_id": "root", "punish_flag": 0, "size": 58391, "starred": false, "status": "available", "thumbnail": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "type": "file", "updated_at": "2022-01-24T10:53:36.473Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}" }, "current_sync_status": 1, "next_sync_status": 2, "popularity_str": "3", "full_share_msg": "「返回.gif」https://www.aliyundrive.com/s/9Q00000000L\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "display_name": "返回.gif" } ``` #### 删除分享链接 POST: `https://api.aliyundrive.com/adrive/v2/share_link/cancel` ```json { "share_id": "9Q00000000L" } ``` Response: ```text HTTP/1.1 200 OK ``` #### 创建分享链接 POST: `https://api.aliyundrive.com/adrive/v2/share_link/create` ```json { "drive_id": "9600002", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "expiration": "2022-04-20T08:01:05.278Z" } ``` Response: ```json { "popularity": 3, "share_id": "9Q00000000L", "share_msg": "「dotull_x86.exe」,点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "share_name": "dotull_x86.exe", "description": "", "expiration": "2022-04-20T08:01:05.278Z", "expired": false, "share_pwd": "", "share_url": "https://www.aliyundrive.com/s/9Q00000000L", "creator": "9400000000bc480bbcbbb1e074f55a7f", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_id_list": ["6228000000002c31be704ca28671f09712894f4f"], "preview_count": 0, "save_count": 0, "download_count": 0, "status": "enabled", "created_at": "2022-03-21T08:01:03.739Z", "updated_at": "2022-03-21T08:01:03.739Z", "first_file": { "trashed": false, "category": "others", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-12-05T02:05:08.125Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "exe", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "mime_type": "application/vnd.microsoft.portable-executable", "name": "dotull_x86.exe", "parent_file_id": "root", "punish_flag": 0, "size": 50449456, "starred": false, "status": "available", "type": "file", "updated_at": "2021-12-05T02:05:08.125Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}" }, "is_photo_collection": false, "sync_to_homepage": false, "full_share_msg": "「dotull_x86.exe」https://www.aliyundrive.com/s/9Q00000000L\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。", "popularity_str": "3", "display_name": "dotull_x86.exe" } ``` #### 检查是否可以分享 POST: `https://api.aliyundrive.com/adrive/v2/share_link/check_available` ```json { "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] } ``` Response: ```json { "invalid_items": [ { "trashed": false, "category": "others", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "content_hash_name": "sha1", "content_type": "application/oct-stream", "crc64_hash": "1548000000008183211", "created_at": "2021-12-05T02:42:36.249Z", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "drive_id": "9600002", "encrypt_mode": "none", "file_extension": "qrc", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "hidden": false, "mime_type": "application/octet-stream", "name": "赵希予 - 克莱因蓝 - 186 - 克莱因蓝_qm.qrc", "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "punish_flag": 0, "size": 3979, "starred": false, "status": "available", "type": "file", "updated_at": "2022-03-21T13:16:16.209Z", "upload_id": "ED12000000004724833D47B5D5D3C8B9", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}" } ] } ``` #### 分析出 shareid(必须是规范的格式) POST: `https://api.aliyundrive.com/adrive/v2/share_link/extract_code` ```json { "content": "「The.Battle.at.L...获取更多免费资源.mkv」https://www.aliyundrive.com/s/9Q00000000L 提取码: f259\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。" } ``` Response: ```json { "code": "200", "message": "success", "data": { "share_id": "9Q00000000L", "share_pwd": "f259" }, "resultCode": "200" } ``` #### 读取分享链接信息 POST: `https://api.aliyundrive.com/adrive/v2/share_link/get_share_by_anonymous` ```json { "share_id": "9Q00000000L" } ``` Response: ```json { "creator_id": "deb7000972d84bb6bfa74e42b22beb07", "creator_name": "霸***组", "creator_phone": "157***610", "expiration": "", "updated_at": "2022-03-22T03:16:01.088Z", "vip": "non-vip", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "share_name": "军检察官多伯曼犬", "file_count": 1, "allow_subscribe": false, "is_creator_followable": true, "is_following_creator": true, "display_name": "军检察官多伯曼犬", "file_infos": [{ "type": "folder", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_name": "军检察官多伯曼犬" }] } ``` #### 打开分享链接 POST: `https://api.aliyundrive.com/v2/share_link/get_share_token` ```json { "share_id": "9Q00000000L", "share_pwd": "" } ``` Response: ```json { "share_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21Kc29uIjoie1wiZG9tYWluX2lkXCI6XCJiajI5XCIsXCJzaGFyZV9pZFwiOlwiaTJRVllCVVVWQ1dcIixcImNyZWF0b3JcIjpcImNjZmY3ZDYwZWZkZjRkNzRiNTc4OGE0ODFlZWQ4Mzg2XCIsXCJ1c2VyX2lkXCI6XCJhbm9ueW1vdXNcIn0iLCJjdXN0b21UeXBlIjoic2hhcmVfbGluayIsImV4cCI6MTY0Nzg3NjM0MCwiaWF0IjoxNjQ3ODY5MDgwfQ.O-wrga-HmgbN4KUWFEhUDozvFu5qV0sn0ntjzbfGpExWQ9yzPCdxVNi-A-wmXtOHNJ5xwnA2GZnX-FsZZ1EQauaOjSswmcc5xsjEenx1ohJVpXPKgl0iKhd9BmmpURZ_4uByhgXFIcEux-Rob22wyt3_NvvfZotVKrvW-pn0Ne8", "expire_time": "2022-03-21T15:25:40.247Z", "expires_in": 7200 } ``` #### 分享链接内文件的下载地址 POST: `https://api.aliyundrive.com/v2/file/get_share_link_download_url` ```json { "drive_id": "9600002", "share_id": "9Q00000000L", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "expire_sec": 600 } ``` Response: ```json { "download_url": "https://pdsapi.aliyundrive.com/v2/redirect?id=a8c5bda295434d4987610b391010bbd5", "url": "https://pdsapi.aliyundrive.com/v2/redirect?id=8b59b11717984cab801f651f6503f064", "thumbnail": "https://pdsapi.aliyundrive.com/v2/redirect?id=e511a261a19949399d9a2ab7cb0bc31a" } ``` #### 分享链接内文件的预览地址 POST: `https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info` ```json { "share_id": "9Q00000000L", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "category": "live_transcoding", "template_id": "", "get_preview_url": true } ``` Response: ```json { "share_id": "9Q00000000L", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "video_preview_play_info": { "category": "live_transcoding", "meta": { "duration": 1464.669, "width": 672, "height": 504, "live_transcoding_meta": { "ts_segment": 10, "ts_total_count": 147, "ts_pre_count": 3 } }, "live_transcoding_task_list": [ { "template_id": "SD", "template_name": "pdsSD", "status": "finished", "stage": "stage_none", "url": "https://pdsapi.aliyundrive.com/v2/redirect?id=15b59a72f8904636bbca16bfa64fbd6d", "preview_url": "https://pdsapi.aliyundrive.com/v2/redirect?id=467363f46e1e490fa5811ba52c320744", "keep_original_resolution": true } ] } } ``` #### 标记一个分享链接已读 POST: `https://api.aliyundrive.com/adrive/v1/share_link/subscription/update` ```json { "share_id": "9Q00000000L", "update_last_seen": true } ``` Response: ```json {} ``` #### 导入分享 POST: `https://api.aliyundrive.com/adrive/v1/file/copy` ```json {"body":{"auto_rename":true,"addition_data":{"umidtoken":"EmdLeXVLOsU9pTV/tFcskzsD8K4J80Ol"},"to_drive_id":"9600002","to_parent_file_id":"root","share_id":"ob7csMtYs9S","file_id":"619b000000006a42a4c143a99dd261777b2e149d"} ``` Response: ```json { "domain_id": "bj29", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb" } ``` POST: `https://api.aliyundrive.com/v2/async_task/get` ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb" } ``` Response: ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb", "state": "Running", "message": "task is running", "total_process": 0, "consumed_process": 0, "punished_file_count": 0 } ``` ```json { "async_task_id": "9fcb1e1d-0000-0000-b30d-387e04dcafcb", "state": "Succeed", "total_process": 0, "consumed_process": 0, "punished_file_count": 0 } ``` ================================================ FILE: adrive sdk/timeline.md ================================================ #### 用户信息 POST: `https://api.aliyundrive.com/adrive/v1/timeline/user/get` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f" } ``` Response: ```json { "description": "", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "myname", "phone": "151***111", "is_following": false, "follower_count": 0, "homepage_visibility": 1, "latest_messages": [], "homepage_visible_time_range_text": "三个月", "homepage_visible_time_range_in_millis": 7776000000 } ``` #### 用户发布的动态 POST: `https://api.aliyundrive.com/adrive/v1/timeline/homepage/list_message` ```json { "order_direction": "DESC", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "limit": 10 } ``` Response: ```json { "items": [], "pin_items": [] } ``` #### 推荐订阅 POST: `https://api.aliyundrive.com/adrive/v1/timeline/user/recommend` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f", "limit": 20, "order_by": "updated_at", "order_direction": "DESC" } ``` Response: ```json { "items": [ { "description": "Hi~小可爱!感恩关注~盘盘酱会不定时发放福利哦!让盘酱陪伴你更久✧( •˓◞•̀ ) ", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "阿里盘盘酱", "phone": "131***325", "is_following": true }, { "description": "中国国家地理景观官方账号,带你领略目酣神醉的壮美景观、发现中国各地独具特色的人文胜迹。", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "中国国家地理景观", "phone": "136***902", "is_following": true } ], "next_marker": "MjA=" } ``` ================================================ FILE: adrive sdk/token.md ================================================ #### 网页版登录 POST: `https://api.aliyundrive.com/token/get` ```json { "code": "f98788cef51641728f2aad9c64a96a63", "loginType": "normal", "deviceId": "CPH800000000AbfFPI5QSJjO" } ``` Response: ```json { "default_sbox_drive_id": "9600002", "role": "user", "user_name": "151***111", "need_link": false, "expire_time": "2022-03-21T09:48:46Z", "pin_setup": true, "need_rp_verify": false, "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "user_data": { "DingDingRobotUrl": "https://oapi.dingtalk.com/robot/send?access_token=0b4a00000000c08608cd99f693393c18fa905aa0868215485a28497501916fec", "EncourageDesc": "内测期间有效反馈前10名用户将获得终身免费会员", "FeedBackSwitch": true, "FollowingDesc": "34848372", "ding_ding_robot_url": "https://oapi.dingtalk.com/robot/send?access_token=0b4a00000000c08608cd99f693393c18fa905aa0868215485a28497501916fec", "encourage_desc": "内测期间有效反馈前10名用户将获得终身免费会员", "feed_back_switch": true, "following_desc": "34848372" }, "token_type": "Bearer", "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9......aixJ4k", "default_drive_id": "9600002", "domain_id": "bj29", "refresh_token": "82ad000000004fbda61b01b5a5cf103b", "is_first_login": false, "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "mynane", "exist_link": [], "state": "", "expires_in": 7200, "status": "enabled" } ``` ================================================ FILE: adrive sdk/user.md ================================================ #### 首页 widgets POST: `https://api.aliyundrive.com/apps/v1/users/apps/widgets` ```json ``` Response: ```json 最近转存,你订阅的分享者有更新了... ``` #### 用户信息 POST: `https://api.aliyundrive.com/v2/user/get` ```json {} ``` Response: ```json { "domain_id": "bj29", "user_id": "9400000000bc480bbcbbb1e074f55a7f", "avatar": "https://ccp-bj29-bj-1592982087.oss-cn-beijing.aliyuncs.com/2GhCur3G%2F...", "created_at": 1623212076923, "updated_at": 1636164094577, "email": "", "nick_name": "mynane", "phone": "15100000111", "role": "user", "status": "enabled", "user_name": "151***111", "description": "", "default_drive_id": "9600002", "user_data": {}, "deny_change_password_by_self": false, "need_change_password_next_login": false, "creator": "", "permission": null } ``` #### 用户信息 POST: `https://api.aliyundrive.com/v2/user/update` ```json { "user_id": "9400000000bc480bbcbbb1e074f55a7f", "nick_name": "n_mynane4" } //用户可以修改自己的description,nick_name,avatar ``` Response: ```json 同上userinfo ``` #### 已用空间 POST: `https://api.aliyundrive.com/adrive/v1/user/driveCapacityDetails` ```json ``` Response: ```json { "drive_used_size": 7436100078094 } ``` #### 相册 driveId POST: `https://api.aliyundrive.com/adrive/v1/user/albums_info` ```json {} ``` Response: ```json { "code": "200", "message": "success", "data": { "driveId": "9600002", "driveName": "alibum" }, "resultCode": "200" } ``` #### 实名信息 POST: `https://api.aliyundrive.com/adrive/v1/user_verify/get` ```json {} ``` Response: ```json { "name": "*名子", "rp_verify_status": "pass", "card_number": "1****************3" } ``` #### 用户信息(vip+空间) POST: `https://api.aliyundrive.com/v2/databox/get_personal_info` ```json {} ``` Response: ```json { "personal_rights_info": { "spu_id": "non-vip", "name": "普通用户", "is_expires": false, "privileges": [ { "feature_id": "download", "feature_attr_id": "speed_limit", "quota": -1 }, { "feature_id": "drive", "feature_attr_id": "size_limit", "quota": 107374182400 }, { "feature_id": "safe_box", "feature_attr_id": "size_limit", "quota": 53687091200 }, { "feature_id": "upload", "feature_attr_id": "size_limit", "quota": 2199023255552 }, { "feature_id": "video", "feature_attr_id": "backup", "quota": 1 }, { "feature_id": "video", "feature_attr_id": "clarity_limit", "quota": 3 } ] }, "personal_space_info": { "used_size": 7436100078094, "total_size": 8946416877568 } } ``` #### 云服务授权管理 POST: `https://api.aliyundrive.com/apps/v1/users/list_app_permissions` ```json ``` Response: ```json { "result": [] } ``` #### 登录设备列表 POST: `https://api.aliyundrive.com/users/v1/users/device_list` ```json ``` Response: ```json { "result": [ { "deviceId": "q2e900000000ASdqMZ/pXgt7", "deviceName": "Chrome浏览器", "modelName": "Windows网页版", "city": "北京市", "loginTime": "2022-03-20 08:52" }, { "deviceId": "SyQo00000000AbfHgMQi2AXv", "deviceName": "Chrome浏览器", "modelName": "Windows网页版", "city": "北京市", "loginTime": "2022-03-01 08:28" } ] } ``` #### 登录设备列表下线 > 需要先短信验证,获取 umidToken > POST: `https://api.aliyundrive.com/users/v1/users/device_offline` ```json { "deviceId": "q2e900000000ASdqMZ/pXgt7", "token": "CN-SPLIT-AQiE_......zdaLa2BOqAzuwCl3TS5Vp68qw", "umidToken": "dhhL00000000BzV/qXrSsXhU3k6buc1a" } ``` Response: ```json { "result": true } ``` #### 未知(相册合并?) POST: `https://api.aliyundrive.com/adrive/v1/user/albums_migration` ```json {} ``` Response: ```json { "code": "200", "message": "success", "data": { "hasMigrateData": false, "drive": { "driveId": "9600002", "driveName": "alibum" } }, "resultCode": "200" } ``` #### 上报登录设备 POST: `https://api.aliyundrive.com/users/v1/users/device` ```json { "modelName": "iPad4,4", "refreshToken": "3b920000000043f19fbc6b65c8dea11c", "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9......", "deviceName": "iPad" } ``` Response: ```json { "result": true } ``` #### 兑换福利码 POST: `https://member.aliyundrive.com/v1/users/rewards` ```json { "code": "山山水水" } ``` Response: ```json { "success": false, "code": "30002", "message": "请输入有效的福利码", "totalCount": null, "nextToken": null, "maxResults": null, "result": { "message": "请输入有效的福利码" }, "arguments": null } ``` #### 容量明细 https://pages.aliyundrive.com/mobile-page/capacitymanager.html?disableNav=YES POST: `https://api.aliyundrive.com/adrive/v1/user/capacityDetails` ```json ``` Response: ```json { "capacity_details": [ { "type": "MEMBER_TASK", "size": 107374182400, "expired": "2022-10-14T05:01:48.935Z", "description": "完成福利社任务", "latest_receive_time": "2021-07-09T11:15:42.845Z" }, { "type": "NEW_USER", "size": 107374182400, "expired": "permanent", "description": "新用户赠礼", "latest_receive_time": "2021-05-14T07:11:03.521Z" }, { "type": "REWARD_CODE", "size": 536870912000, "expired": "permanent", "description": "兑换福利码", "latest_receive_time": "2022-02-21T12:08:58.000Z" }, { "type": "BETA", "size": 3298534883328, "expired": "permanent_condition", "description": "内测专享", "latest_receive_time": "2021-03-18T05:01:21.118Z" }, { "type": "MEMBER_TASK", "size": 107374182400, "expired": "2021-07-08T11:15:42.905Z", "description": "完成福利社任务", "latest_receive_time": "2021-03-18T05:02:28.160Z" } ] } ``` #### 福利社任务列表 POST: `https://member.aliyundrive.com/v1/users/task_list` ```json ``` Response: ```json { "success": true, "code": null, "message": null, "totalCount": null, "nextToken": null, "maxResults": null, "result": [ { "idempotent": "5dd6000000004283a4be19f4a5ab647a", "position": 10, "id": "51", "name": "邀请好友用云盘", "code": "referral", "actionType": "openLink", "action": "smartdrive://vipcenter/referral", "url": "https://pages.aliyundrive.com/mobile-page/web/invitefriends.html", "appName": null, "description": "+800G/人", "backgroundImage": "https://img.alicdn.com/imgextra/i4/O1CN016LFIjK1SRL72iovyX_!!6000000002243-2-tps-819-456.png", "backgroundColor": "#D9E8FF", "darkBackgroundColor": "#D9E8FF", "textColor": "#6FBEEB", "darkTextColor": "#6FBEEB", "status": "unfinished", "createdAt": 1644718396417, "finishedAt": null, "notice": "容量一年有效", "topRightCorner": "限时任务", "detailName": "", "detailDescription": "https://pages.aliyundrive.com/mobile-page/web/beinvited.html?code=", "detailBackgroundImage": "", "detailIntroduction": null, "rewards": [{ "icon": "https://img.alicdn.com/imgextra/i1/O1CN015KvMU11Yj65cGXGCp_!!6000000003094-2-tps-72-72.png", "name": "", "description": "有效期一年" }], "detailRewardNotice": "", "process": { "current": 0, "max": 0 }, "statusNotice": "", "explain": null, "referral": null, "monthlyCard": null, "popUps": null, "shareFissions": null, "subTasks": null, "shareAction": null, "darenShareViewModel": null }, { "idempotent": "80bf00000000442b90368c27a7ec3443", "position": 3, "id": "66", "name": "第四周·周任务", "code": "adrive", "actionType": "openNative", "action": "smartdrive://vipcenter/opentaskcarddetail?taskId=66", "url": "", "appName": null, "description": "阿里云盘VIP免费领", "backgroundImage": "https://img.alicdn.com/imgextra/i3/O1CN01HK76N21tBlGdfXcjm_!!6000000005864-2-tps-1029-612.png", "backgroundColor": null, "darkBackgroundColor": null, "textColor": "#FFD601", "darkTextColor": "#FFD601", "status": "finished", "createdAt": 1645953637620, "finishedAt": 1647857247562, "notice": "一个月 VIP", "topRightCorner": "周年庆", "detailName": "第四周·周任务", "detailDescription": "阿里云盘VIP免费领", "detailBackgroundImage": "https://img.alicdn.com/imgextra/i3/O1CN01HK76N21tBlGdfXcjm_!!6000000005864-2-tps-1029-612.png", "detailIntroduction": null, "rewards": [{ "icon": "https://gw.alicdn.com/imgextra/i3/O1CN01nl3rNq1PWQc5cpUWQ_!!6000000001848-2-tps-72-72.png", "name": "阿里云盘VIP", "description": "完成两个任务即可获得1个月阿里云盘VIP " }], "detailRewardNotice": "", "process": { "current": 2, "max": 0 }, "statusNotice": "领取阿里云盘VIP", "explain": { "title": "活动说明:\r\n1. 活动期为2022年3月21日-3月27日。\r\n2. 任务福利将于4月30日开启兑换,所有会员福利最晚兑换时间为2022年6月30日,过期后不可兑换。", "description": "" }, "referral": null, "monthlyCard": null, "popUps": null, "shareFissions": null, "subTasks": null, "shareAction": null, "darenShareViewModel": null } ], "arguments": null } ``` #### 福利社任务详情 POST: `https://member.aliyundrive.com/v1/users/task_detail` ```json { "taskId": "51" } ``` Response: ```json { "idempotent": "5dd6000000004283a4be19f4a5ab647a", "position": 10, "id": "51", "name": "邀请好友用云盘", "code": "referral", "actionType": "openLink", "action": "smartdrive://vipcenter/referral", "url": "https://pages.aliyundrive.com/mobile-page/web/invitefriends.html", "appName": null, "description": "+800 GB/人 一年有效", "backgroundImage": "https://img.alicdn.com/imgextra/i4/O1CN016LFIjK1SRL72iovyX_!!6000000002243-2-tps-819-456.png", "backgroundColor": "#D9E8FF", "darkBackgroundColor": "#D9E8FF", "textColor": "#FFD601", "darkTextColor": "#FFD601", "status": "unfinished", "createdAt": 1644718396417, "finishedAt": null, "notice": "", "topRightCorner": "限时任务", "detailName": "", "detailDescription": "https://pages.aliyundrive.com/mobile-page/web/beinvited.html?code=", "detailBackgroundImage": "", "detailIntroduction": null, "rewards": [{ "icon": "https://img.alicdn.com/imgextra/i1/O1CN015KvMU11Yj65cGXGCp_!!6000000003094-2-tps-72-72.png", "name": "", "description": "有效期一年" }], "detailRewardNotice": "", "process": { "current": 0, "max": 0 }, "statusNotice": "", "explain": null, "referral": { "reward": 300, "userSignupAmount": 10, "userAmount": 10, "newUserTask": 10, "availableReward": 0, "verificationReward": 8000, "limitReward": 8000, "shortURL": "https://pages.aliyundrive.com/mobile-page/web/beinvited.html?code=0000007" }, "monthlyCard": null, "popUps": null, "shareFissions": null, "subTasks": null, "shareAction": null, "darenShareViewModel": null } ``` #### 福利社任务批量详情 POST: `https://member.aliyundrive.com/v1/users/batch_task_detail` ```json { "taskIds": ["52", "55", "58", "66", "69"] } ``` Response: ```json [ { "idempotent": "80bf00000000442b90368c27a7ec3443", "position": 3, "id": "66", "name": "第四周·周任务", "code": "adrive", "actionType": "openNative", "action": "smartdrive://vipcenter/opentaskcarddetail?taskId=66", "url": "", "appName": null, "description": "阿里云盘VIP免费领", "backgroundImage": "https://img.alicdn.com/imgextra/i3/O1CN01HK76N21tBlGdfXcjm_!!6000000005864-2-tps-1029-612.png", "backgroundColor": null, "darkBackgroundColor": null, "textColor": "#FFD601", "darkTextColor": "#FFD601", "status": "finished", "createdAt": 1645953637620, "finishedAt": 1647857247562, "notice": "一个月 VIP", "topRightCorner": "周年庆", "detailName": "第四周·周任务", "detailDescription": "阿里云盘VIP免费领", "detailBackgroundImage": "https://img.alicdn.com/imgextra/i3/O1CN01HK76N21tBlGdfXcjm_!!6000000005864-2-tps-1029-612.png", "detailIntroduction": null, "rewards": [{ "icon": "https://gw.alicdn.com/imgextra/i3/O1CN01nl3rNq1PWQc5cpUWQ_!!6000000001848-2-tps-72-72.png", "name": "阿里云盘VIP", "description": "完成两个任务即可获得1个月阿里云盘VIP " }], "detailRewardNotice": "", "process": { "current": 2, "max": 0 }, "statusNotice": "领取阿里云盘VIP", "explain": { "title": "活动说明:\r\n1. 活动期为2022年3月21日-3月27日。\r\n2. 任务福利将于4月30日开启兑换,所有会员福利最晚兑换时间为2022年6月30日,过期后不可兑换。", "description": "" }, "referral": null, "monthlyCard": null, "popUps": null, "shareFissions": null, "subTasks": [ { "id": 67, "name": "订阅一个云盘订阅号", "actionType": "openNative", "action": "smartdrive://app/subscription", "url": "", "idempotent": "0c260000000042d493714b53fc6da210", "status": "finished", "statusNotice": "已完成", "position": 0 }, { "id": 68, "name": "转存一个订阅号分享的文件", "actionType": "openNative", "action": "smartdrive://userpage/openroot?userId=ec11691148db442aa7aa374ca707543c", "url": "", "idempotent": "369f000000004f188d85e7f682f9633f", "status": "finished", "statusNotice": "已完成", "position": 0 } ], "shareAction": null, "darenShareViewModel": null } ] ``` ================================================ FILE: adrive sdk/video.md ================================================ #### 放映室-列出全部专辑 POST: `https://api.aliyundrive.com/adrive/v2/video/list` ```json { "use_compilation": true, "duration": 0, "order_by": "created_at desc", "hidden_type": "NO_HIDDEN", "limit": 50 } ``` Response: ```json { "items": [ { "name": "hotel.2022.mp4", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_120000,f_jpg,w_480,ar_auto,m_fast", "type": "file", "category": "video", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "size": 2623499628, "starred": false, "duration": "0", "independent": true, "parent_file_id": "root", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_extension": "mp4", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"client\":\"web\"}", "content_type": "application/oct-stream", "created_at": "2022-03-20T04:26:18.082+00:00", "updated_at": "2022-03-20T04:26:18.082+00:00", "trashed_at": null, "punish_flag": 1, "video_type": "COMMON", "video_hidden": false, "play_cursor": "0", "video_media_metadata": {}, "video_preview_metadata": { "bitrate": "3996225", "duration": "5251.955000", "height": 1040, "width": 1920, "audio_format": "aac", "frame_rate": "24000/1001" }, "compilation_id": "9600002_6236000000001b86cee34bdab3a5ad1d4d0cd676", "grand_parent_file_id": null }, { "name": "总复习", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_120000,f_jpg,w_480,ar_auto,m_fast", "created_at": "2022-01-23T04:21:54.470+00:00", "updated_at": "2022-01-23T04:21:54.743+00:00", "trashed_at": null, "video_type": "COMPILATION", "video_hidden": false, "video_nums": "7", "compilation_id": "9600002_61ec000000009a6068fe4c67936d781b6c2fced2" } ], "next_marker": "" } ``` #### 放映室-最近播放 POST: `https://api.aliyundrive.com/adrive/v2/video/recentList` ```json {} ``` Response: ```json { "items": [ { "name": "综合复习.mp4", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_125201,f_jpg,w_480,ar_auto,m_fast", "size": 167238406, "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_extension": "mp4", "drive_id": "9600002", "duration": "1800.80", "play_cursor": "125.201", "last_played_at": "2022-03-19T13:46:04.000+00:00", "compilation_id": "9600002_61ec000000009a6068fe4c67936d781b6c2fced2" } ] } ``` #### 列出一个专辑包含的文件 POST: `https://api.aliyundrive.com/adrive/v2/video/compilation/list` ```json { "duration": 0, "hidden_type": "NO_HIDDEN", "name": "总复习", "limit": 50 } ``` Response: ```json { "items": [ { "name": "热点复习.mp4", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_120000,f_jpg,w_480,ar_auto,m_fast", "type": "file", "category": "video", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "size": 181714186, "starred": false, "duration": "1800.080000", "labels": ["其他场景", "内部场景"], "independent": false, "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_extension": "mp4", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "content_type": "application/oct-stream", "created_at": "2022-01-23T04:21:54.563+00:00", "updated_at": "2022-01-23T04:21:54.563+00:00", "trashed_at": null, "punish_flag": 0, "video_type": "COMMON", "video_hidden": false, "play_cursor": "0", "video_media_metadata": { "duration": "1800.080000", "height": 1080, "width": 1920 }, "video_preview_metadata": { "bitrate": "807582", "duration": "1800.080000", "height": 1080, "width": 1920, "audio_format": "aac", "frame_rate": "25/1", "template_list": [{ "status": "finished", "template_id": "HD" }] }, "compilation_id": "9600002_61ec000000009a6068fe4c67936d781b6c2fced2", "grand_parent_file_id": null } ], "next_marker": "" } ``` #### 从专辑里隐藏一个文件 POST: `https://api.aliyundrive.com/adrive/v2/video/update` ```json { "play_cursor": "0", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "drive_id": "9600002", "hidden": true } ``` Response: ```json { "name": "热点复习.mp4", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_0,f_jpg,w_480,ar_auto,m_fast", "type": "file", "category": "video", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "size": 181714186, "starred": false, "duration": "1800.080000", "labels": ["其他场景", "内部场景"], "independent": true, "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_extension": "mp4", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "content_type": "application/oct-stream", "created_at": "2022-01-23T04:21:54.563+00:00", "updated_at": "2022-01-23T04:21:54.563+00:00", "trashed_at": null, "punish_flag": 0, "video_hidden": true, "play_cursor": "0", "video_media_metadata": { "duration": "1800.080000", "height": 1080, "width": 1920 }, "video_preview_metadata": { "bitrate": "807582", "duration": "1800.080000", "height": 1080, "width": 1920, "audio_format": "aac", "frame_rate": "25/1", "template_list": [{ "status": "finished", "template_id": "HD" }] }, "grand_parent_file_id": null } ``` #### 播放列表(根据一个文件,列出同专辑的文件列表) POST: `https://api.aliyundrive.com/adrive/v2/video/compilation/listByFileInfo` ```json { "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "limit": "100", "drive_id": "9600002" } ``` Response: ```json { "items": [ { "name": "热点复习.mp4", "thumbnail": "https://api.aliyundrive.com/v2/file/download?drive_id=9600002&file_id=623b00000000d89ef21d4118838aed83de7575ba&video_thumbnail_process=video/snapshot,t_120000,f_jpg,w_480,ar_auto,m_fast", "type": "file", "category": "video", "url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "size": 181714186, "starred": false, "duration": "1800.080000", "labels": ["其他场景", "内部场景"], "independent": false, "parent_file_id": "613800000000336ae9164455b135a9729a298c9c", "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba", "file_extension": "mp4", "content_hash": "4DBF0000000023E6E756C29AF6AC487217921D53", "domain_id": "bj29", "download_url": "https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F...", "user_meta": "{\"play_cursor\":\"0\"}", "content_type": "application/oct-stream", "created_at": "2022-01-23T04:21:54.563+00:00", "updated_at": "2022-03-21T09:39:07.226+00:00", "trashed_at": null, "punish_flag": 0, "video_type": "COMMON", "video_hidden": true, "play_cursor": "0", "video_media_metadata": { "duration": "1800.080000", "height": 1080, "width": 1920 }, "video_preview_metadata": { "bitrate": "807582", "duration": "1800.080000", "height": 1080, "width": 1920, "audio_format": "aac", "frame_rate": "25/1", "template_list": [{ "status": "finished", "template_id": "HD" }] }, "compilation_id": "9600002_61ec000000009a6068fe4c67936d781b6c2fced2", "grand_parent_file_id": null } ], "next_marker": "" } //警告:无用的next_marker ``` #### 播放-更新播放进度 POST: `https://api.aliyundrive.com/adrive/v2/video/update` ```json {"drive_id":"9600002","duration":"616.235","file_extension":"mp4","file_id":"623b00000000d89ef21d4118838aed83de7575ba","name":"样本.mp4","play_cursor":"148.298","thumbnail":"https://bj29.cn-beijing.data.alicloudccp.com/2GhCur3G%2F..."} ``` Response: ```json file ``` ================================================ FILE: changelog.txt ================================================  #### 2022/10/24 注:因上传下载功能尚未做完,本次仅同步代码不发布安装包 0. 恢复文件上传功能,支持单次上传百万个文件/文件夹,优化上传任务的数据库文件体积过大的问题 1. 优化sha1并发计算逻辑,增加文件sha1的缓存,提升上传大文件的性能 2. Add 上传前弹窗,设置重名冲突(删除/覆盖/自动重命名/不上传) 3. Add 单独的总上传速度限制设置 4. Add 上传文件时只上传可以秒传的文件的设置 5. Add 单独的上传文件时的并发执行数设置(最大50文件同时上传) 6. Add 左侧文件树文件夹对拖放上传的支持 7. Add 上传中列表里文件夹视图 8. Add 优先上传小文件(100M)的支持 9. Fix 按住Ctrl时,点击CheckBox和点击空白处,选中结果不一致的BUG 10. Fix 右键菜单-打开文件位置,没有选中和滚动到指定文件的BUG 11. Fix 断网时,重试上传任务,可能导致上传任务的断点续传进度丢失的BUG #### 2022/09/18 注:因上传下载功能尚未做完,本次仅同步代码不发布安装包 1. Fix v3.5.23alpha中的20余处小BUG 2. Fix 登录时遇到二次短信验证时不能继续登录的BUG 3. 完善批量重命名功能 4. 完善颜色标记功能 5. 优化文件列表加载显示逻辑,现在很优雅了 6. 优化文件名排序,支持中文数字排序,按win习惯英文在前中文在后 7. 优化文件夹树性能(全部文件夹列出速度加快3倍,20万文件夹不卡顿,树内存占用减少60%) 8. 恢复显示文件夹体积(可按大小排序),优化计算文件夹体积的逻辑(速度加快计算量减少) 9. 底部增加网盘空间信息和文件夹内文件总数量 10. 增加复制文件名和复制目录树的功能 11. 适配更新vite3.1.2,更新全部package到最新版 #### 2022/05/23 v3.5.23alpha 开发人员测试版本 1. Fix 偶发的登录后显示空白窗口的 BUG 2. Fix 登录太多账号时切换账号弹窗不能正确显示的 BUG 3. 优化长时间不用后需要重新登录的问题 4. Fix 偶发的下载中显示空白列表的 BUG 5. Fix 多次弹出升级提示窗口的 BUG 6. Fix 目录下超过 200 个文件夹不能显示的 BUG 7. 重制 APP 设置页面,分组设置,配置保存到 setting.config 8. 优化快捷键(现在很多操作都支持键盘快捷键) -- v3.05.23.alpha 新增加的功能 文件恢复,放映室,网页版播放器,彻底删除菜单,文件属性菜单,所有列表支持右键菜单, 整盘高级搜索,文件快速筛选,右侧文件拖放移动,文件标记,文件夹快捷方式,我订阅的公众号, 重复文件清理,扫描大文件,扫描重复文件,扫描违规文件,扫描空文件夹,网盘相册间复制, 批量重命名 #### 2022/04/14 1. 修正因阿里云盘官网升级导致的无法使用 2. 优化访问频次问题 3. 修正违禁视频详情BUG #### 2021/12/05 1. 修正网盘内文件路径过长时下载失败 BUG 2. 优化快捷键功能(帮助文档里有完整的快捷键说明) 3. 增加收藏夹的搜索功能 4. 优化后退按钮(以前是返回父文件夹,现在是后退,最多后退 20 步) 5. 增加优先下载小文件选项 6. 增加雪碧图里视频信息的显示和保存雪碧图按钮 7. 网盘页顶部路径默认隐藏需要在设置里勾选显示 8. 修正m3u8播放链接15分钟后失效的 BUG (现在4小时) 9. 修正之前部分版本代理设置被覆盖的 BUG 10. 增加自定义缓存位置功能 11. 增加帮助文档 #### 2021/11/29 1. 修正 2.11.28 下载显示出错的 BUG 1. 修正登录时遇到二次验证导致点击登录按钮无反应的 BUG 2. 修正自 v2.11.07 开始不能上传体积为 0 的文件的 BUG 3. 修正 v2.11.16 上传文件时占用内存过多的问题 4. 11.16 里 60 文件同时上传会占用大量内存,11.28 里优化为只占用 400MB 以内的内存 5. 修正传输完自动关机触发时机不准确的 BUG 6. 修正上传时遇到没有访问权限的文件/文件夹时上传中队列卡住的 BUG 7. 增加视频文件洗码功能 8. 增加右侧文件拖动到左侧文件夹树(移动文件)功能 9. 优化远程 Aria2 下载功能并修复断线后自动重连 10. 优化本地 Aria2,无法连接时会尝试自动重启一次 Aria2 进程 11. 增加任务栏的下载中上传中进度提示(win/mac) 12. 底部状态栏显示总传输的预估剩余时间 13. 增加上传时跳过同名文件的设置项 14. 优化盘内文件搜索支持选择分类 15. 一些细节优化 #### 2021/11/14 1. 增加创建分享、编辑分享、管理分享功能 2. 完善导入分享功能,支持部分导入和完整导入 3. 增加网盘内文件搜索功能 4. 增加下载时自动过滤违规文件的设置 5. 增加对禁止分享的文件的图标 6. 增加文件/文件夹置顶功能 7. 增加主题跟随系统 8. 增加下载上传完成后自动关机设置 9. 完善 mac 和 linux 下自定义播放软件功能 10. 恢复视频文件雪碧图,增加复制 M3U8 链接和原始视频链接功能 11. 修正 linux 下上传时会自动过滤软链接文件 #### 2021/11/07 1. 优化一次性上传或下载大量文件时的界面卡顿(参阅 挑战一百万.md) 2. 创建日期文件夹支持编号了 3. 新增定时清理回收站功能 4. 新增我创建的分享列表功能(没做完) 5. 增加文件列表显示限制(减少加载中) 6. 恢复导入阿里云盘分享链接功能(仅全部导入) 7. 恢复新建文件功能 8. 恢复版本升级提示功能 9. 修正 windows 下载位置不能选择根目录的 BUG 10. 修正不能上传大于 97.6GB 的文件的问题 11. 修正上传速度显示不准确的 BUG 12. 修正不能同时下载同一个文件(下载到不同的位置)的 BUG 13. 优化部分文件格式图标 #### 2021/10/31 1. 增加文件列表的缩略图模式 2. 修正v2.10.17和v2.10.19版本里一个严重的BUG(删除文件时可能会错误选中父文件夹一起删除) 3. 去除彻底删除按钮 4. 回收站增加清理回收站按钮(一键删除回收站内全部文件) 5. 增加上传和下载的文件过滤功能(自动跳过特定格式的文件) 6. 修正左侧文件夹树和右侧文件列表的互动关联 7. 恢复重命名功能和移动复制功能 #### 2021/10/19 1. 优化文件列出逻辑,节省一半的等待加载中时间 2. 优化v2.9一个文件夹直接包含大量子文件夹时的卡顿和内存剧增问题 一个文件夹里直接包含 17000 个子文件夹时,打开文件夹 v2.9 需要占用 700MB 内存, v2.10 需要占用 190MB 内存 v2.9 当一个文件夹里包含 3000 个以上的子文件夹时,小白羊文件夹树会卡顿 v2.10 无所谓多少个子文件夹,不会卡顿 3. 优化v2.9网盘包含有巨量文件夹时,启动后前几秒会卡顿的问题 4. 优化v2.9上下传记录的本地数据库体积 长期大量上传下载会产生较大的本地记录数据,现在会自动清理 5. 修正v2.9统计文件夹体积功能的本地缓存和运行时CPU内存占用 开启统计文件夹体积功能后,我网盘里有 2 万个文件夹和 31 万个文件,v2.9 会产生 167MB 的缓存,v2.10 会产生 8MB 的缓存 修正了一个会导致 CPU 和内存占用高的 BUG(用户账号 token 失效时,会因为定时统计功能导致 CPU 和内存占用很高) 6. 优化在线预览视频现在支持很多种播放器了 当前只适配了 windows (测试了 MPV,Potplayer,VLC media player,KMPlayer,恒星播放器,SMPlayer) macos 和 linux 稍后会适配,现在仍旧只能用 mpv 播放器 7. 增加在线预览 word/excel/ppt/pdf 文件的功能 当前,大部分音视频格式,大部分图片格式,word/excel/ppt/pdf/txt,200 余种常见文本格式 都可以在线预览了 8. 修正在文件夹里搜索后,拖动搜索结果里的文件上传,上传文件名错误的 BUG 9. 优化上传前的 sha1 校验速度,提升上传速度 10. 美化了一下界面 11. 增加是否按照完整网盘路径保存的设置 12. 增加关闭窗口立即退出的设置 13. 增加双击才打开文件、文件夹的设置 14. 增加清理缓存的设置 15. 增加运行日志的设置 16. 文件夹树的宽度可以拖动调整了 17. 图片、Office、文本预览现在是单独窗口了 18. 修正一些文件格式识别不准确的 BUG #### 2021/09/24 1. 修正上传 20GB 以上的文件时,断点续传时进度不准确的 BUG 2. 取消文件列表的加载中状态提示,快速展现文件列表 3. 更新文件列表缓存方式,数据库文件体积减少 73% (14 万个文件从 240MB 降低为 60MB) 4. 增加是否统计文件夹体积的设置开关,减少网盘内文件过多时的白屏问题 5. 同步 v2.9.24 源码到 github #### 2021/09/19 1. 删除秒传相关功能 2. 修正 v2.8.30 里 aria2 远程模式连接失败的 BUG 3. 修正偶发文件列表只显示占位符不显示文件名的 BUG 4. 修正移动文件后选中文件数显示错误的 BUG 5. 修正批量重命名取消勾选文件夹时子文件名计算错误的 BUG 6. 修正批量重命名点击刷新后因一直加载,不能关闭的 BUG 7. 增加对文件名结尾的点和空格的清理,修正这些文件下载失败的 BUG 8. 修正闲置长时间后上传文件可能出现获取上传地址失败的 BUG 9. 减少因并发数太高容易出现的操作失败 BUG 10. 修正等宽图片预览时,切换下一张后滚动条没有自动回到顶部的 BUG 11. 增加文件列表(F5 键刷新文件,Back 键返回上级文件夹),等宽图片预览(← 上一张,→ 下一张)的快捷键 12. 增加点击头像图片时自动刷新网盘空间用量 13. 增加文件夹独立排序选项 14. 增加直接彻底删除文件的右键菜单 15. 升级数据库架构,提升了加载文件列表的性能,本周重点就是此项,性能提升涉及方方面面的细节,大部分以前加载慢的功能都有了极明显的提升,例如一次性上传包含 10 万个文件的文件夹,不会出现任何卡顿了 16. 修正 v2.9.15 里长时间后上传文件时出现获取上传地址失败的 BUG 17. 增加上传/下载任务出错后等 1 分钟自动重试功能,可以放心挂机下载、挂机上传了 #### 2021/08/30 1. Fix 修正 v1.6.29 大量上传下载后会生成大体积的 数据库 的 BUG 2. Fix 修正 v1.6.29 导入阿里云盘分享链接失败的 BUG 3. Fix 修正 v1.6.29 上传途中重启程序后,重新上传不会断点续传的 BUG 4. Fix 修正部分违规视频不能播放的 BUG,现在可以使用"优先播放转码视频"模式播放了 # 1. Add 增加阿里云盘官方登录接口(手机短信、账号密码、APP 扫码登录) 2. Add 增加多个账号同时登录、切换功能 3. Add 增加 Aria 远程连接设置,可以把文件直接下载到远程电脑/VPS/NAS/Docker 4. Add 增加文件名颜色标记,批量标记功能,观看视频自动标记功能 5. Add 增加文件、文件夹详情功能(文件夹大小,包含文件数),视频文件的雪碧图 6. Add 增加新的图片预览模式,可以放大/缩小/旋转/幻灯片播放 7. Add 增加代码高亮/ json 格式化显示 / txt 在线预览功能 8. Add 增加快速创建日期格式的文件夹 9. Add 增加可选择文件夹是否和文件一起排序了 10. Add 增加所有文件夹体积的显示,可以按照体积排序文件夹了 11. Add windows 上支持 Potplayer 播放器了 12. Add 顶部快捷路径跳转和区间选择功能 # 1. Pro 优化文件复制功能,可极速复制 TB 级/上万文件 到网盘的其他位置 2. Pro 优化导入分享功能,在导入时可以选择网盘里的保存位置,可以勾选要保存的 文件/文件夹 3. Pro 优化上传功能,现在部分不能秒传的大文件,上传前不再需要计算 sha1 了(减少上传时间) 4. Pro 优化 sha1 计算逻辑和性能,同时最多 3 个文件计算 sha1,机械硬盘不会掉速,CPU 不会爆满 5. Pro 现在 windows/macos/linux 都支持拖拽文件、文件夹上传了 6. Pro 优化批量重命名功能,支持勾选文件,支持重命名多级子文件夹,支持 替换/删除/增加/序号/随机字符 等方式 7. Pro 优化在线解压功能,支持全部解压和勾选文件解压,支持有密码的压缩包 #### 2021/06/29 Fix 优化重命名、搜索输入框大小 Fix 修正下载中、上传中页面因进度条动画导致的GPU占用过高的BUG Fix 中文名导致偶有macos启动失败的BUG Add 导入阿里云盘分享链接的功能 Add 导入115网盘分享链接的功能 #### 2021/06/21 Fix 显示用户昵称和头像 Fix 完善对字体的支持(可以随意更换自己喜欢的字体了),完善文字大小设置功能 Fix 完善在线预览图片功能(支持旋转,文件夹内全部图片上一张下一张查看) Fix 文件名是.(点)时导致的创建下载任务失败的BUG Fix 创建文件夹太快偶发点击文件夹名不能进入的BUG Add Windows上支持批量拖拽文件/文件夹上传 Add 选择文件/文件夹计算秒传信息保存到网盘内txt文件的功能 Add 导入txt文件类型的秒传链接(支持文件夹嵌套) Add 新增相册功能(文件可以在相册和网盘之间移动复制) #### 2021/06/13 Fix 在下载大文件时Aria在某些系统上强制分配硬盘BUG导致下载进度卡死 Fix 优化Aria的连接性,减少出错崩溃 Fix Mac版输出大量无用日志的BUG Fix 一堆UI细节上的完善 Add 复制文件到...的功能(官方只有移动到...) Add 批量重命名功能(替换/删除字符,增加前缀,正则表达式替换) Add 聚合搜索功能(当前搜不到什么,要等以后大家主动分享) Add 初步支持在线解压缩(zip,rar) Ver 更新到Flutter2.2.1 #### 2021/06/10 Fix 因阿里云盘API升级导致的无法加载文件列表的BUG Fix 选择上传文件夹时 可能 需要长时间等待的BUG Fix 批量下载大量子文件夹时 可能 需要长时间等待的BUG Fix 修正回收站内文件无法在线播放的BUG Fix 增加一些在线播放视频格式的支持(m2ts/hevc....) Add 增加对违规文件的标识 Add 增加深色模式 Add 下载失败时的一些错误提示 Del 去除创建秒传链接的功能,仅支持导入秒传链接(115:// 、aliyun://) #### 2021/06/06 1. Fix 批量下载时只解析了第一个选中的文件夹的严重BUG 2. Fix 大量操作更新为异步操作,极大的减少了操作等待时间 3. Fix 因阿里云盘升级导致扫码登陆失败的BUG 4. Add 支持导入李恒道版本秒传链接 #### 2021/06/05 1. Add 秒传短链接功能(创建秒传链接、导入别人分享的短链接、短链接本地历史记录) 2. Add 增加115链接批量导入功能(靠运气) 3. Add 增加在线预览文本文件功能 4. Fix 因阿里云盘升级导致扫码登陆失败的BUG 5. Fix 阿里云盘对单次批量操作最多限制100条的限制 6. Fix 在线预览图片时图片大小缩放BUG 7. Fix 按文件名排序时不准确的BUG #### 2021/05/31 1. Add 上传文件、文件夹功能 2. Add 在线预览图片 3. Add 移动文件、文件夹功能 4. Fix 优化启动时启动后台提示 5. Fix 延长下载链接时效(15分钟->4小时) 6. Fix 文件夹内包含大量文件时多次操作可能回重复拉取的BUG #### 2021/05/25 1. 上传第一个开发中版本仅供测试 2. 支持 扫码登录/Cookie登录 3. 支持 阿里云盘基本功能 4. 支持 在线预览全格式原画视频(非转码) 5. 支持 批量下载文件/文件夹,只要阿里云不限速,就是满速下载 ================================================ FILE: crx/devtools.html ================================================ ================================================ FILE: crx/devtools.js ================================================ chrome.devtools.network.onRequestFinished.addListener(function (detail) { let url = detail.request.url; let isbreak = false; if (url.indexOf("api.aliyundrive.com") > 0) isbreak = true; /** 跳过api */ if (url.indexOf("img.aliyundrive.com") > 0) isbreak = true; /** 跳过img */ if (url.indexOf("_tmd_") > 0) isbreak = true; /** 跳过滑动验证 */ if (url.indexOf(".aliyuncs.com") > 0) isbreak = true; /** 跳过滑动验证 */ if (url.indexOf(".aliyun.com") > 0) isbreak = true; /** 跳过滑动验证 */ if (url.indexOf(".taobao.com") > 0) isbreak = true; /** 跳过滑动验证 */ if (url.indexOf(".mmstat.com") > 0) isbreak = true; /** 跳过日志 */ if (url.indexOf(".aliyundrive.com") < 0) isbreak = true; /** 跳过无效域名 */ if (isbreak) return; detail.getContent(function (content, mimeType) { try { if (typeof content == "string" && content.indexOf('"bizExt"') > 0) { let bizExt = ""; try { /** https://passport.aliyundrive.com/newlogin/login.do?appName=aliyun_drive&fromSite=52&_bx-v=2.0.31 */ const data = JSON.parse(content); bizExt = data.content?.data?.bizExt || ""; } catch (e) { bizExt = ""; chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ url, e, content }) + "')" ); } if (!bizExt) { /** https://passport.aliyundrive.com/newlogin/safe/ivCheckLogin.htm?havana_iv_token=... 二次短信验证 */ try { let temp = content.substring( content.indexOf('"bizExt"') + '"bizExt"'.length ); temp = temp.substring(temp.indexOf('"') + 1); // :"eyJ...", temp = temp.substring(0, temp.indexOf('"')); //eyJ... if (temp.startsWith("eyJ")) bizExt = temp; } catch (e) { bizExt = ""; chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ url, e, content }) + "')" ); } } if (bizExt) { chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ bizExt: bizExt }) + "')" ); } } } catch {} }); }); ================================================ FILE: crx/manifest.json ================================================ { "manifest_version": 3, "name": "demo", "version": "1.0.0", "description": "demo", "devtools_page": "devtools.html", "host_permissions": [ "http://*/*", "https://*/*" ] } ================================================ FILE: doc/info.md ================================================ ================================================ FILE: doc/v2.8.x 使用PotPlayer.md ================================================ #### window系统上,在v2.8.15版本开始支持使用Potplayer替换掉默认的MPV播放器 这里是临时的复制文件方式,使用Potplayer,在以后以后的版本中会在设置里增加一个设置,让用户手动选择potplayer.exe文件即可,那时就不需要复制了 #### 具体的操作: 1.下载小白羊v2.8.15 解压到“阿里云盘小白羊版v2” 2.下载Potplayer 不管是解压还是安装,最终找到Potplayer.exe所在的文件夹 (注:如果你已经安装过Potplayer,不需要重新安装,直接找到Potplayer.exe所在的文件夹就行了) 3.把Potplayer的整个文件夹复制到“阿里云盘小白羊版v2\resources\”里面 #### 最终得到: '阿里云盘小白羊版v2\resources\Potplayer\Potplayer.exe' 退出后重新启动小白羊生效 ### 需要注意的是: 第一:Potplayer必须是20210127以后的版本,推荐安装最新版 #### 第二:有的Potplayer文件夹里只有Potplayermini.exe 没有Potplayer.exe 需要手动把Potplayermini.exe 改名成 Potplayer.exe 第三:有的Potplayer文件夹里只有Potplayer64.exe 没有Potplayer.exe 需要手动把Potplayer64.exe 改名成 Potplayer.exe 第四:遇到在线预览视频没有画面只有声音的,请自行安装解码器(OpenCodec/LAVFilters) 安装解码器参阅 http://www.potplayercn.com/course/OpenCodec.html http://www.potplayercn.com/course/2994.html 最后附上最终的文件目录树: `````` 阿里云盘小白羊版v2 │ chrome_100_percent.pak │ chrome_200_percent.pak │ d3dcompiler_47.dll │ ffmpeg.dll │ icudtl.dat │ libEGL.dll │ libGLESv2.dll │ resources.pak │ snapshot_blob.bin │ v2.8.15.txt │ v8_context_snapshot.bin │ vk_swiftshader.dll │ vk_swiftshader_icd.json │ vulkan-1.dll │ 阿里云盘小白羊版v2.exe │ ├─locales ├─resources │ │ app.asar │ │ app.ico │ │ app.png │ │ aria2.conf │ │ aria2c.exe │ │ filehash32.exe │ │ │ ├─MPV │ │ │ d3dcompiler_43.dll │ │ │ mpv.com │ │ │ mpv.exe │ │ │ └─PotPlayer │ │ Alarm.wav │ │ ATextOut.dll │ │ CaptureUWP.dll │ │ CmdLine.txt │ │ d3dcompiler_47.dll │ │ d3dx9_43.dll │ │ DaumCrashHandler.dll │ │ DesktopHook.dll │ │ DesktopHook.exe │ │ DesktopHook64.dll │ │ DesktopHook64.exe │ │ DTDrop.exe │ │ D_Exec.exe │ │ ffcodec.dll │ │ FileList.txt │ │ GameCaptureHook.dll │ │ GameCaptureHook64.dll │ │ KillPot.exe │ │ LGPL.TXT │ │ License.txt │ │ MediaDB.dll │ │ PotIcons.dll │ │ PotPlayer.dll │ │ PotPlayer.exe │ │ PotPlayer.ini │ │ PotPlayerXP.exe │ │ PotScreenSaver.scr │ │ │ ├─AviSynth │ ├─Capture │ ├─Extension │ ├─History │ ├─IconPack │ ├─Language │ ├─Logos │ ├─Menus │ ├─Module │ ├─Playlist │ ├─PxShader │ ├─Skins │ ├─UrlList │ │ │ └─VapourSynth │ Histogram.vpy │ motioninterpolation.vpy │ └─swiftshader libEGL.dll libGLESv2.dll `````` ================================================ FILE: doc/v2.8.x 阿里云盘小白羊版和官方性能测试.md ================================================ 阿里云盘小白羊版和官方性能测试 ==== 阿里云盘小白羊版 v2.8.22终于实现了文件上传所以做个能测试(上传测试和下载测试) >测试方法,就是简单的选择文件上传,用手机人工计时 > >测试平台:联想Y7000笔记本,i5-8300H,16G内存,512GB M2 西数固态硬盘,3TB 外接usb2.0 机械硬盘(13年产西数绿盘) #### 补充说明 1. 所有测试上传的文件都是可以秒传的,既只测试程序性能,不测试网络性能。所有测试均与网络状态无关 2. 只测试一遍没有多次测试取平均值,测试期间电脑不运行其他程序,上传中也不操作电脑 3. 测试基于特定程序版本,人工计时有误差 1-3 秒。结果仅用来展示小白羊的程序功能,并不能说明什么 4. 秒传测试不能体现网络传输性能,但网络传输主要是受限于网络状态,跟程序关系就不大了 #### 测试结果 小白羊对小文件上传,和网页版相差不大,但比客户端快一倍 小白羊对大文件上传,比网页版和客户端都快很多 ------ #### 测试方案一:大量小文件上传 M2.SSD硬盘上的 6.28GB 共2899个文件 每个文件2-3MB 图集(jpg) | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.22 | 12% | 6分35秒 | 395 | 136% | | PC客户端 v2.2.3.788 | 18% | 12分45秒 | 765 | [263%]() | | 网页版 | 36% | 4分50秒 | 290 | 100% |
M2.SSD硬盘上的 98MB 共3863个文件 每个文件10-150KB 文本小文件 | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.22 | 6% | 4分19秒 | 259 | 125% | | PC客户端 v2.2.3.788 | 7% | 14分12秒 | 852 | [411%]() | | 网页版 | 23% | 3分27秒 | 207 | 100% |
------ #### 测试方案二:单个大文件上传 USB机械硬盘 2.54GB [豆瓣5.0]魔唇劫.The.Holy.Virgin.Versus.the.Evil.Dead.1991.泰吉修复剪辑完整版.HD1080P.国粤双语.中字.mp4 | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.22 | 9% | 55秒 | 55 | :zap:100% | | PC客户端 v2.2.3.788 | 22% | 1分20秒 | 80 | 145% | | 网页版 | 18% | 2分40秒 | 160 | [290%]() |
M2.SSD硬盘上的 5.15GB [一只鱼4kyu.cc豆瓣7.6分]少年黄飞鸿之铁马骝.Iron.Monkey.1993.BD1080p.国粤双语.中字.mp4 | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.22 | 22% | 22秒 | 22 | :zap:100% | | PC客户端 v2.2.3.788 | 25% | 1分50秒 | 110 | 500% | | 网页版 | 26% | 3分25秒 | 205 | [931%]() |
------ #### 测试方案三:批量个大文件上传 M2.SSD硬盘上的 50GB 共22个文件 每个文件2-4G 视频大文件 | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.22 | 66% | 1分25秒 | 85 | :zap:100% | | PC客户端 v2.2.3.788 | 94% | 5分23秒 | 323 | 380% | | 网页版 | 25% | 32分10秒 | 1930 | [2270%]() |
------ #### 测试方案四:批量小文件下载 网盘里的一个包含5540个小文件的文件夹(共191MB,每个文件10-200KB,小文件) | 程序 | CPU | 用时 | 用时(s) | 基准 | | --- | :---: | :---: | ---: | ---: | | 小白羊v2.8.1 | 无 | 4分10秒 | 250 | :zap:100% | | PC客户端 v2.2.1.768 | 无 | 24分40秒 | 1480 | [592%]() |
------ #### 测试方案五:批量大文件下载 网盘里的一个包含27个视频的文件夹(共191MB,每个文件700-900MB,视频文件) 小白羊v2.8.1 和 PC客户端 v2.2.1.768 单独下载时,都可以达到我的宽带上限(11MB/s) 小白羊v2.8.1 和 PC客户端 v2.2.1.768 同时下载时,小白羊挤占了更多的宽带(小白羊9MB/s下载,PC客户端2MB/s下载)
================================================ FILE: electron-builder.json ================================================ { "appId": "YouAppID", "asar": true, "directories": { "output": "release" }, "files": [ "dist" ], "mac": { "artifactName": "${productName}_${version}.${ext}", "target": [ "dmg" ] }, "win": { "target": [ { "target": "nsis", "arch": [ "x64" ] } ], "artifactName": "${productName}_${version}.${ext}" }, "nsis": { "oneClick": false, "perMachine": false, "allowToChangeInstallationDirectory": true, "deleteAppDataOnUninstall": false } } ================================================ FILE: nano-staged.mjs ================================================ export default { // eslint '*.{js,ts,tsx,jsx}': ['prettier --write', 'eslint --cache --fix'], '*.{vue}': ['stylelint --fix', 'prettier --write', 'eslint --cache --fix'], '*.{less,css}': ['stylelint --fix', 'prettier --write'], // typecheck 'packages/renderer/**/{*.ts,*.tsx,*.vue,tsconfig.json}': ({ filenames }) => 'npm run typecheck' } ================================================ FILE: package.json ================================================ { "name": "alixby", "version": "3.05.23", "main": "dist/main/index.js", "author": "", "license": "", "scripts": { "dev": "node scripts/watch.mjs", "build": "vue-tsc --noEmit --p packages/renderer/tsconfig.json && node scripts/build.mjs && electron-builder --dir" }, "engines": { "node": ">=14.17.0" }, "dependencies": { "@arco-design/web-vue": "^2.28.0", "@electron/remote": "^2.0.8", "ant-design-vue": "^3.2.3", "axios": "^0.27.2", "dayjs": "^1.11.2", "dexie": "^3.2.2", "dom-to-image": "^2.6.0", "fuzzysort": "^1.9.0", "isomorphic-fetch": "^3.0.0", "jschardet": "^3.0.0", "lodash": "^4.17.21", "pinia": "^2.0.14", "viewerjs": "^1.10.5", "vue": "^3.2.33" }, "devDependencies": { "@types/lodash": "^4.14.182", "@types/node": "^17.0.31", "@vitejs/plugin-vue": "^2.3.2", "@vitejs/plugin-vue-jsx": "^1.3.10", "electron": "14.2.6", "electron-builder": "^23.0.3", "nano-staged": "^0.8.0", "typescript": "^4.6.4", "unplugin-vue-components": "^0.19.5", "vite": "^2.9.9", "vite-plugin-electron-renderer": "^0.3.3", "vite-plugin-resolve": "^2.1.0", "vue": "^3.2.33", "vue-tsc": "^0.34.13" }, "env": { "VITE_DEV_SERVER_HOST": "127.0.0.1", "VITE_DEV_SERVER_PORT": 3344 }, "keywords": [ "electron", "rollup", "vite", "vue3", "vue" ] } ================================================ FILE: public/comlink.js ================================================ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.Comlink = {})); }(this, (function (exports) { 'use strict'; /** * Copyright 2019 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const proxyMarker = Symbol("Comlink.proxy"); const createEndpoint = Symbol("Comlink.endpoint"); const releaseProxy = Symbol("Comlink.releaseProxy"); const throwMarker = Symbol("Comlink.thrown"); const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function"; /** * Internal transfer handle to handle objects marked to proxy. */ const proxyTransferHandler = { canHandle: (val) => isObject(val) && val[proxyMarker], serialize(obj) { const { port1, port2 } = new MessageChannel(); expose(obj, port1); return [port2, [port2]]; }, deserialize(port) { port.start(); return wrap(port); }, }; /** * Internal transfer handler to handle thrown exceptions. */ const throwTransferHandler = { canHandle: (value) => isObject(value) && throwMarker in value, serialize({ value }) { let serialized; if (value instanceof Error) { serialized = { isError: true, value: { message: value.message, name: value.name, stack: value.stack, }, }; } else { serialized = { isError: false, value }; } return [serialized, []]; }, deserialize(serialized) { if (serialized.isError) { throw Object.assign(new Error(serialized.value.message), serialized.value); } throw serialized.value; }, }; /** * Allows customizing the serialization of certain values. */ const transferHandlers = new Map([ ["proxy", proxyTransferHandler], ["throw", throwTransferHandler], ]); function expose(obj, ep = self) { ep.addEventListener("message", function callback(ev) { if (!ev || !ev.data) { return; } const { id, type, path } = Object.assign({ path: [] }, ev.data); const argumentList = (ev.data.argumentList || []).map(fromWireValue); let returnValue; try { const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj); const rawValue = path.reduce((obj, prop) => obj[prop], obj); switch (type) { case "GET" /* GET */: { returnValue = rawValue; } break; case "SET" /* SET */: { parent[path.slice(-1)[0]] = fromWireValue(ev.data.value); returnValue = true; } break; case "APPLY" /* APPLY */: { returnValue = rawValue.apply(parent, argumentList); } break; case "CONSTRUCT" /* CONSTRUCT */: { const value = new rawValue(...argumentList); returnValue = proxy(value); } break; case "ENDPOINT" /* ENDPOINT */: { const { port1, port2 } = new MessageChannel(); expose(obj, port2); returnValue = transfer(port1, [port1]); } break; case "RELEASE" /* RELEASE */: { returnValue = undefined; } break; default: return; } } catch (value) { returnValue = { value, [throwMarker]: 0 }; } Promise.resolve(returnValue) .catch((value) => { return { value, [throwMarker]: 0 }; }) .then((returnValue) => { const [wireValue, transferables] = toWireValue(returnValue); ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables); if (type === "RELEASE" /* RELEASE */) { // detach and deactive after sending release response above. ep.removeEventListener("message", callback); closeEndPoint(ep); } }); }); if (ep.start) { ep.start(); } } function isMessagePort(endpoint) { return endpoint.constructor.name === "MessagePort"; } function closeEndPoint(endpoint) { if (isMessagePort(endpoint)) endpoint.close(); } function wrap(ep, target) { return createProxy(ep, [], target); } function throwIfProxyReleased(isReleased) { if (isReleased) { throw new Error("Proxy has been released and is not useable"); } } function createProxy(ep, path = [], target = function () { }) { let isProxyReleased = false; const proxy = new Proxy(target, { get(_target, prop) { throwIfProxyReleased(isProxyReleased); if (prop === releaseProxy) { return () => { return requestResponseMessage(ep, { type: "RELEASE" /* RELEASE */, path: path.map((p) => p.toString()), }).then(() => { closeEndPoint(ep); isProxyReleased = true; }); }; } if (prop === "then") { if (path.length === 0) { return { then: () => proxy }; } const r = requestResponseMessage(ep, { type: "GET" /* GET */, path: path.map((p) => p.toString()), }).then(fromWireValue); return r.then.bind(r); } return createProxy(ep, [...path, prop]); }, set(_target, prop, rawValue) { throwIfProxyReleased(isProxyReleased); // FIXME: ES6 Proxy Handler `set` methods are supposed to return a // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯ const [value, transferables] = toWireValue(rawValue); return requestResponseMessage(ep, { type: "SET" /* SET */, path: [...path, prop].map((p) => p.toString()), value, }, transferables).then(fromWireValue); }, apply(_target, _thisArg, rawArgumentList) { throwIfProxyReleased(isProxyReleased); const last = path[path.length - 1]; if (last === createEndpoint) { return requestResponseMessage(ep, { type: "ENDPOINT" /* ENDPOINT */, }).then(fromWireValue); } // We just pretend that `bind()` didn’t happen. if (last === "bind") { return createProxy(ep, path.slice(0, -1)); } const [argumentList, transferables] = processArguments(rawArgumentList); return requestResponseMessage(ep, { type: "APPLY" /* APPLY */, path: path.map((p) => p.toString()), argumentList, }, transferables).then(fromWireValue); }, construct(_target, rawArgumentList) { throwIfProxyReleased(isProxyReleased); const [argumentList, transferables] = processArguments(rawArgumentList); return requestResponseMessage(ep, { type: "CONSTRUCT" /* CONSTRUCT */, path: path.map((p) => p.toString()), argumentList, }, transferables).then(fromWireValue); }, }); return proxy; } function myFlat(arr) { return Array.prototype.concat.apply([], arr); } function processArguments(argumentList) { const processed = argumentList.map(toWireValue); return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))]; } const transferCache = new WeakMap(); function transfer(obj, transfers) { transferCache.set(obj, transfers); return obj; } function proxy(obj) { return Object.assign(obj, { [proxyMarker]: true }); } function windowEndpoint(w, context = self, targetOrigin = "*") { return { postMessage: (msg, transferables) => w.postMessage(msg, targetOrigin, transferables), addEventListener: context.addEventListener.bind(context), removeEventListener: context.removeEventListener.bind(context), }; } function toWireValue(value) { for (const [name, handler] of transferHandlers) { if (handler.canHandle(value)) { const [serializedValue, transferables] = handler.serialize(value); return [ { type: "HANDLER" /* HANDLER */, name, value: serializedValue, }, transferables, ]; } } return [ { type: "RAW" /* RAW */, value, }, transferCache.get(value) || [], ]; } function fromWireValue(value) { switch (value.type) { case "HANDLER" /* HANDLER */: return transferHandlers.get(value.name).deserialize(value.value); case "RAW" /* RAW */: return value.value; } } function requestResponseMessage(ep, msg, transfers) { return new Promise((resolve) => { const id = generateUUID(); ep.addEventListener("message", function l(ev) { if (!ev.data || !ev.data.id || ev.data.id !== id) { return; } ep.removeEventListener("message", l); resolve(ev.data); }); if (ep.start) { ep.start(); } ep.postMessage(Object.assign({ id }, msg), transfers); }); } function generateUUID() { return new Array(4) .fill(0) .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)) .join("-"); } exports.createEndpoint = createEndpoint; exports.expose = expose; exports.proxy = proxy; exports.proxyMarker = proxyMarker; exports.releaseProxy = releaseProxy; exports.transfer = transfer; exports.transferHandlers = transferHandlers; exports.windowEndpoint = windowEndpoint; exports.wrap = wrap; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=comlink.js.map ================================================ FILE: public/iconfont.css ================================================ @font-face { font-family: 'iconfont'; src: url('iconfont.woff2') format('woff2'); } .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .iconlist:before { content: "\e685"; } .iconzhongmingming:before { content: "\e686"; } .icona-juzhongduiqi3x:before { content: "\e687"; } .iconLocation:before { content: "\e68e"; } .iconlocation:before { content: "\e684"; } .icondingwei:before { content: "\ec32"; } .icontupianyulan:before { content: "\e683"; } .iconkuaisukaidian:before { content: "\e6ea"; } .iconmiaosha:before { content: "\e681"; } .iconae:before { content: "\e682"; } .iconpic2:before { content: "\e680"; } .iconpiliangxuanze:before { content: "\e67e"; } .iconpiliangbianji:before { content: "\e67f"; } .iconpaixu2:before { content: "\e67c"; } .iconpaixu11:before { content: "\e67d"; } .iconpaixu1:before { content: "\e67a"; } .iconwbiaoqian:before { content: "\e67b"; } .icondakaiwenjianjia:before { content: "\e6bc"; } .icondakaiwenjianjia1:before { content: "\e679"; } .iconmoveto:before { content: "\e78a"; } .iconyidong:before { content: "\e678"; } .iconyidong1:before { content: "\e708"; } .iconqingkong:before { content: "\e677"; } .icontouping2:before { content: "\e675"; } .iconluxiang:before { content: "\efff"; } .iconshipin:before { content: "\e6bb"; } .iconfangkuang:before { content: "\e674"; } .iconattribute:before { content: "\e6b0"; } .iconshuxing:before { content: "\e723"; } .iconshuxing1:before { content: "\e91c"; } .iconjietu:before { content: "\e673"; } .icongengduo1:before { content: "\e672"; } .iconcrown3:before { content: "\e66c"; } .iconshuzhuangtu:before { content: "\e670"; } .iconchuanshu2:before { content: "\e66f"; } .icontree-map:before { content: "\e66d"; } .iconnode-tree1:before { content: "\e7c2"; } .iconyuanduanfuzhi:before { content: "\e66e"; } .iconchrome:before { content: "\eaa9"; } .icondingyueno:before { content: "\e66b"; } .iconchakan:before { content: "\e66a"; } .icontuijian:before { content: "\e68d"; } .icondingyue:before { content: "\e668"; } .iconxiaotumoshi:before { content: "\e65d"; } .iconweixiang:before { content: "\e671"; } .iconxia:before { content: "\e694"; } .iconxia1:before { content: "\e796"; } .icontongzhiblue:before { content: "\e702"; } .icontongzhi1:before { content: "\e669"; } .iconyibu:before { content: "\e666"; } .iconquxiaozhiding:before { content: "\e918"; } .iconzhiding:before { content: "\e676"; } .iconshousuo:before { content: "\e819"; } .iconshousuo1:before { content: "\e689"; } .iconfile-apk:before { content: "\e665"; } .iconshangchuansudu:before { content: "\e663"; } .iconxiazaisudu:before { content: "\e664"; } .iconarrow-bottom-2-icon-copy:before { content: "\e93d"; } .iconarrow-left-1-icon:before { content: "\e923"; } .iconarrow-left-2-icon:before { content: "\e924"; } .iconarrow-right-1-icon:before { content: "\e925"; } .iconarrow-right-2-icon:before { content: "\e926"; } .iconreload-1-icon:before { content: "\e93b"; } .iconarrow-top-2-icon-copy:before { content: "\e93c"; } .iconDebug2:before { content: "\e662"; } .icondebug:before { content: "\e716"; } .iconyonghu:before { content: "\e661"; } .iconright:before { content: "\e660"; } .iconfenzhi1:before { content: "\e65f"; } .iconcheckbox-full:before { content: "\e65e"; } .icondian:before { content: "\e602"; } .iconfanhui:before { content: "\e65c"; } .iconwifi:before { content: "\e65b"; } .iconyouxian:before { content: "\e698"; } .iconcrown2:before { content: "\e659"; } .icontxt:before { content: "\e6a6"; } .iconpubuliumoshi:before { content: "\e65a"; } .icongengduo:before { content: "\e63a"; } .iconliebiaomoshi:before { content: "\e700"; } .iconpaixu:before { content: "\e706"; } .iconsuoluetumoshi:before { content: "\e636"; } .iconArrow-Down2:before { content: "\e740"; } .iconArrow-Right2:before { content: "\e742"; } .iconxiaoxituisong:before { content: "\e638"; } .iconfenxiang1:before { content: "\e635"; } .iconbiaozhang:before { content: "\e6af"; } .iconfenxiang:before { content: "\e6c9"; } .iconmenuoff:before { content: "\e77c"; } .iconmenuon:before { content: "\e77d"; } .iconxuanzhuan:before { content: "\e68a"; } .iconsafebox:before { content: "\e634"; } .iconweifa:before { content: "\e601"; } .iconchuanbo:before { content: "\e745"; } .iconui:before { content: "\e600"; } .iconali:before { content: "\e631"; } .iconrss:before { content: "\e62f"; } .iconchuanshu:before { content: "\e630"; } .iconanlixiangqinganniu:before { content: "\e633"; } .iconinfo_circle:before { content: "\e77e"; } .iconrpasswoed:before { content: "\e6fa"; } .iconnight:before { content: "\e62d"; } .iconday:before { content: "\e62e"; } .iconrss_music:before { content: "\e7ca"; } .iconrss_game:before { content: "\e7ce"; } .iconrstop:before { content: "\e770"; } .iconrsearch:before { content: "\e775"; } .iconrvip:before { content: "\e776"; } .iconrpic:before { content: "\e778"; } .iconrsuccess:before { content: "\e77b"; } .iconclose:before { content: "\e7fd"; } .iconzuixiaohua:before { content: "\e7ff"; } .iconleft_circle:before { content: "\e77f"; } .iconright_circle:before { content: "\e783"; } .iconfullscreen:before { content: "\e7ec"; } .iconfolderadd:before { content: "\e7d2"; } .iconnotification:before { content: "\e7df"; } .iconsync:before { content: "\e786"; } .iconpiechart:before { content: "\e78f"; } .iconuser:before { content: "\e7ae"; } .iconcheck:before { content: "\e7fc"; } .iconsort_ascend:before { content: "\e62a"; } .iconsort_descend:before { content: "\e62b"; } .iconsort:before { content: "\e62c"; } .iconsearch:before { content: "\e8f0"; } .icondown:before { content: "\e7eb"; } .iconempty:before { content: "\e629"; } .iconfile_img2:before { content: "\e628"; } .iconfile_xci:before { content: "\e626"; } .iconfile_nsp:before { content: "\e627"; } .iconfile_bin:before { content: "\e624"; } .iconfile_dmg:before { content: "\e625"; } .iconcalendar:before { content: "\e7d3"; } .icondesktop:before { content: "\e843"; } .iconstart:before { content: "\e658"; } .iconfile_txt2:before { content: "\e622"; } .iconfile_video:before { content: "\e621"; } .iconcloud_success:before { content: "\e620"; } .iconcopy:before { content: "\e61b"; } .iconpercentage:before { content: "\e7e3"; } .iconscissor:before { content: "\e7e6"; } .iconcomment:before { content: "\e8e8"; } .iconhourglass:before { content: "\e7c7"; } .iconrss_video:before { content: "\e90f"; } .iconfail:before { content: "\e6e1"; } .iconlogoff:before { content: "\e61d"; } .iconjindu:before { content: "\e667"; } .iconcloud_error:before { content: "\e63b"; } .iconlink2:before { content: "\e61e"; } .iconrecover:before { content: "\e61f"; } .iconfile_ts:before { content: "\e61c"; } .iconfile_ssa:before { content: "\e61a"; } .iconfile_wmv:before { content: "\e619"; } .iconfile_asf:before { content: "\e613"; } .iconfile_ass:before { content: "\e614"; } .iconfile_rmvb:before { content: "\e615"; } .iconfile_srt:before { content: "\e616"; } .iconfile_stl:before { content: "\e617"; } .iconfile-scc:before { content: "\e618"; } .iconfile-god:before { content: "\e60d"; } .iconfile-vmdk:before { content: "\e60e"; } .iconfile-gho:before { content: "\e60f"; } .iconfile-iso:before { content: "\e610"; } .iconfile-mds:before { content: "\e611"; } .iconfile-vhd:before { content: "\e612"; } .iconfile-cue:before { content: "\e60a"; } .iconfile-ogg:before { content: "\e60c"; } .iconfile-wav:before { content: "\e607"; } .iconfile-ape:before { content: "\e608"; } .iconfile-flac:before { content: "\e609"; } .iconfile-mkv:before { content: "\e606"; } .iconfile-bt:before { content: "\e605"; } .iconfile-file:before { content: "\e604"; } .iconfile-image:before { content: "\e603"; } .iconrss-item:before { content: "\e910"; } .iconrss-xby:before { content: "\e911"; } .iconpoweroff:before { content: "\e78c"; } .iconlogout:before { content: "\e78d"; } .iconsetting:before { content: "\e78e"; } .iconbulb:before { content: "\e7c5"; } .iconcluster:before { content: "\e7d7"; } .iconcamera:before { content: "\e7dd"; } .iconlink:before { content: "\e7e2"; } .iconinstagram:before { content: "\e87f"; } .iconwechat:before { content: "\e883"; } .iconapartment:before { content: "\e897"; } .iconrobot:before { content: "\e898"; } .iconcameraadd:before { content: "\e8ea"; } .iconlogin:before { content: "\e8ef"; } .iconplus:before { content: "\e8fe"; } .iconclear:before { content: "\e900"; } .iconpartition:before { content: "\e90e"; } .iconrest:before { content: "\e7c4"; } .iconhome:before { content: "\e7c6"; } .iconcloud-server:before { content: "\e7dc"; } .iconcloud-sync:before { content: "\e7de"; } .iconupload:before { content: "\e7f0"; } .iconpause:before { content: "\e7fe"; } .iconcrown:before { content: "\e842"; } .iconset:before { content: "\e623"; } .iconwenjian:before { content: "\e637"; } .iconfolder:before { content: "\e7d1"; } .iconedit-square:before { content: "\e791"; } .icondelete:before { content: "\e7c3"; } .iconcloud-upload:before { content: "\e7d9"; } .iconcloud:before { content: "\e7da"; } .iconcloud-download:before { content: "\e7db"; } .icondownload:before { content: "\e7ef"; } .iconfile-img:before { content: "\e639"; } .iconfile-folder:before { content: "\e60b"; } .iconfile-audio:before { content: "\e632"; } .iconfile-7z:before { content: "\e63c"; } .iconfile-ai:before { content: "\e63d"; } .iconfile-avi:before { content: "\e63e"; } .iconfile-bmp:before { content: "\e63f"; } .iconfile-eps:before { content: "\e640"; } .iconfile-exe:before { content: "\e641"; } .iconfile-flv:before { content: "\e642"; } .iconfile-doc:before { content: "\e643"; } .iconfile-gif:before { content: "\e644"; } .iconfile-mov:before { content: "\e645"; } .iconfile-html:before { content: "\e646"; } .iconfile-mp4:before { content: "\e647"; } .iconfile-pdf:before { content: "\e648"; } .iconfile-mp3:before { content: "\e649"; } .iconfile-ppt:before { content: "\e64a"; } .iconfile-png:before { content: "\e64b"; } .iconfile-psd:before { content: "\e64c"; } .iconfile-rar:before { content: "\e64d"; } .iconfile-svg:before { content: "\e64e"; } .iconfile-swf:before { content: "\e64f"; } .iconfile-rp:before { content: "\e650"; } .iconfile-tif:before { content: "\e651"; } .iconfile-txt:before { content: "\e652"; } .iconfile-zip:before { content: "\e653"; } .iconfile-jpg:before { content: "\e654"; } .iconfile-wps:before { content: "\e655"; } .iconfile-tar:before { content: "\e656"; } .iconfile-xsl:before { content: "\e657"; } ================================================ FILE: public/lang/en.js ================================================ videojs.addLanguage('en', { "Audio Player": "Audio Player", "Video Player": "Video Player", "Play": "Play", "Pause": "Pause", "Replay": "Replay", "Current Time": "Current Time", "Duration": "Duration", "Remaining Time": "Remaining Time", "Stream Type": "Stream Type", "LIVE": "LIVE", "Seek to live, currently behind live": "Seek to live, currently behind live", "Seek to live, currently playing live": "Seek to live, currently playing live", "Loaded": "Loaded", "Progress": "Progress", "Progress Bar": "Progress Bar", "progress bar timing: currentTime={1} duration={2}": "{1} of {2}", "Fullscreen": "Fullscreen", "Non-Fullscreen": "Exit Fullscreen", "Mute": "Mute", "Unmute": "Unmute", "Playback Rate": "Playback Rate", "Subtitles": "Subtitles", "subtitles off": "subtitles off", "Captions": "Captions", "captions off": "captions off", "Chapters": "Chapters", "Descriptions": "Descriptions", "descriptions off": "descriptions off", "Audio Track": "Audio Track", "Volume Level": "Volume Level", "You aborted the media playback": "You aborted the media playback", "A network error caused the media download to fail part-way.": "A network error caused the media download to fail part-way.", "The media could not be loaded, either because the server or network failed or because the format is not supported.": "The media could not be loaded, either because the server or network failed or because the format is not supported.", "The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "The media playback was aborted due to a corruption problem or because the media used features your browser did not support.", "No compatible source was found for this media.": "No compatible source was found for this media.", "The media is encrypted and we do not have the keys to decrypt it.": "The media is encrypted and we do not have the keys to decrypt it.", "Play Video": "Play Video", "Close": "Close", "Close Modal Dialog": "Close Modal Dialog", "Modal Window": "Modal Window", "This is a modal window": "This is a modal window", "This modal can be closed by pressing the Escape key or activating the close button.": "This modal can be closed by pressing the Escape key or activating the close button.", ", opens captions settings dialog": ", opens captions settings dialog", ", opens subtitles settings dialog": ", opens subtitles settings dialog", ", opens descriptions settings dialog": ", opens descriptions settings dialog", ", selected": ", selected", "captions settings": "captions settings", "subtitles settings": "subtitles settings", "descriptions settings": "descriptions settings", "Text": "Text", "White": "White", "Black": "Black", "Red": "Red", "Green": "Green", "Blue": "Blue", "Yellow": "Yellow", "Magenta": "Magenta", "Cyan": "Cyan", "Background": "Background", "Window": "Window", "Transparent": "Transparent", "Semi-Transparent": "Semi-Transparent", "Opaque": "Opaque", "Font Size": "Font Size", "Text Edge Style": "Text Edge Style", "None": "None", "Raised": "Raised", "Depressed": "Depressed", "Uniform": "Uniform", "Dropshadow": "Dropshadow", "Font Family": "Font Family", "Proportional Sans-Serif": "Proportional Sans-Serif", "Monospace Sans-Serif": "Monospace Sans-Serif", "Proportional Serif": "Proportional Serif", "Monospace Serif": "Monospace Serif", "Casual": "Casual", "Script": "Script", "Small Caps": "Small Caps", "Reset": "Reset", "restore all settings to the default values": "restore all settings to the default values", "Done": "Done", "Caption Settings Dialog": "Caption Settings Dialog", "Beginning of dialog window. Escape will cancel and close the window.": "Beginning of dialog window. Escape will cancel and close the window.", "End of dialog window.": "End of dialog window.", "{1} is loading.": "{1} is loading.", "Exit Picture-in-Picture": "Exit Picture-in-Picture", "Picture-in-Picture": "Picture-in-Picture" }); ================================================ FILE: public/lang/zh-CN.js ================================================ videojs.addLanguage('zh-CN', { "Play": "播放", "Pause": "暂停", "Current Time": "当前时间", "Duration": "时长", "Remaining Time": "剩余时间", "Stream Type": "媒体流类型", "LIVE": "直播", "Loaded": "加载完成", "Progress": "进度", "Fullscreen": "全屏", "Non-Fullscreen": "退出全屏", "Picture-in-Picture": "画中画", "Exit Picture-in-Picture": "退出画中画", "Mute": "静音", "Unmute": "取消静音", "Playback Rate": "播放速度", "Subtitles": "字幕", "subtitles off": "关闭字幕", "Captions": "内嵌字幕", "captions off": "关闭内嵌字幕", "Chapters": "节目段落", "Close Modal Dialog": "关闭弹窗", "Descriptions": "描述", "descriptions off": "关闭描述", "Audio Track": "音轨", "You aborted the media playback": "视频播放被终止", "A network error caused the media download to fail part-way.": "网络错误导致视频下载中途失败。", "The media could not be loaded, either because the server or network failed or because the format is not supported.": "视频因格式不支持或者服务器或网络的问题无法加载。", "The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "由于视频文件损坏或是该视频使用了你的浏览器不支持的功能,播放终止。", "No compatible source was found for this media.": "无法找到此视频兼容的源。", "The media is encrypted and we do not have the keys to decrypt it.": "视频已加密,无法解密。", "Play Video": "播放视频", "Close": "关闭", "Modal Window": "弹窗", "This is a modal window": "这是一个弹窗", "This modal can be closed by pressing the Escape key or activating the close button.": "可以按ESC按键或启用关闭按钮来关闭此弹窗。", ", opens captions settings dialog": ", 开启标题设置弹窗", ", opens subtitles settings dialog": ", 开启字幕设置弹窗", ", opens descriptions settings dialog": ", 开启描述设置弹窗", ", selected": ", 选择", "captions settings": "字幕设定", "Audio Player": "音频播放器", "Video Player": "视频播放器", "Replay": "重新播放", "Progress Bar": "进度条", "Volume Level": "音量", "subtitles settings": "字幕设定", "descriptions settings": "描述设定", "Text": "文字", "White": "白", "Black": "黑", "Red": "红", "Green": "绿", "Blue": "蓝", "Yellow": "黄", "Magenta": "紫红", "Cyan": "青", "Background": "背景", "Window": "窗口", "Transparent": "透明", "Semi-Transparent": "半透明", "Opaque": "不透明", "Font Size": "字体尺寸", "Text Edge Style": "字体边缘样式", "None": "无", "Raised": "浮雕", "Depressed": "压低", "Uniform": "均匀", "Dropshadow": "下阴影", "Font Family": "字体库", "Proportional Sans-Serif": "比例无细体", "Monospace Sans-Serif": "单间隔无细体", "Proportional Serif": "比例细体", "Monospace Serif": "单间隔细体", "Casual": "舒适", "Script": "手写体", "Small Caps": "小型大写字体", "Reset": "重置", "restore all settings to the default values": "恢复全部设定至预设值", "Done": "完成", "Caption Settings Dialog": "字幕设定窗口", "Beginning of dialog window. Escape will cancel and close the window.": "打开对话窗口。Escape键将取消并关闭对话窗口", "End of dialog window.": "结束对话窗口", "Seek to live, currently behind live": "尝试直播,当前为延时播放", "Seek to live, currently playing live": "尝试直播,当前为实时播放", "progress bar timing: currentTime={1} duration={2}": "{1}/{2}", "{1} is loading.": "正在加载 {1}。", "Open quality selector menu":"选择清晰度" }); ================================================ FILE: public/main.html ================================================ 阿里云盘小白羊版
================================================ FILE: public/main2.html ================================================ 阿里云盘小白羊版
================================================ FILE: public/prism-vsc-dark-plus.css ================================================ pre[class*='language-'], code[class*='language-'] { color: #e4e4e4; font-size: 14px; text-shadow: none; font-family: Menlo, Monaco, Consolas, 'Andale Mono', 'Ubuntu Mono', 'Courier New', monospace, Segoe WPC, Segoe UI, Microsoft YaHei, sans-serif; font-feature-settings: 'liga' 0, 'calt' 0; direction: ltr; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; line-height: 1.5; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*='language-']::selection, code[class*='language-']::selection, pre[class*='language-'] *::selection, code[class*='language-'] *::selection { text-shadow: none; background: #75a7ca; } @media print { pre[class*='language-'], code[class*='language-'] { text-shadow: none; } } pre[class*='language-'] { padding: 1em; margin: 0.5em 0; overflow: auto; background: #1e1e1e; } :not(pre) > code[class*='language-'] { padding: 0.1em 0.3em; border-radius: 0.3em; color: #db4c69; background: #f9f2f4; } /********************************************************* * Tokens */ .namespace { opacity: 0.7; } .token.doctype .token.doctype-tag { color: #569cd6; } .token.doctype .token.name { color: #9cdcfe; } .token.comment, .token.prolog { color: #6a9955; } .token.punctuation, .language-html .language-css .token.punctuation, .language-html .language-javascript .token.punctuation { color: #d4d4d4; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.inserted, .token.unit { color: #b5cea8; } .token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.deleted { color: #ffa726; } .language-css .token.string.url { text-decoration: underline; } .token.operator, .token.entity { color: #d4d4d4; } .token.operator.arrow { color: #569cd6; } .token.atrule { color: #f3a281; } .token.atrule .token.rule { color: #c586c0; } .token.atrule .token.url { color: #9cdcfe; } .token.atrule .token.url .token.function { color: #dcdcaa; } .token.atrule .token.url .token.punctuation { color: #d4d4d4; } .token.keyword { color: #569cd6; } .token.keyword.module, .token.keyword.control-flow { color: #c586c0; } .token.function, .token.function .token.maybe-class-name { color: #dcdcaa; } .token.regex { color: #d16969; } .token.important { color: #569cd6; } .token.italic { font-style: italic; } .token.constant { color: #9cdcfe; } .token.class-name, .token.maybe-class-name { color: #4ec9b0; } .token.console { color: #9cdcfe; } .token.parameter { color: #9cdcfe; } .token.interpolation { color: #9cdcfe; } .token.punctuation.interpolation-punctuation { color: #569cd6; } .token.boolean { color: #569cd6; } .token.property, .token.variable, .token.imports .token.maybe-class-name, .token.exports .token.maybe-class-name { color: #9cdcfe; } .token.selector { color: #d7ba7d; } .token.escape { color: #d7ba7d; } .token.tag { color: #569cd6; } .token.tag .token.punctuation { color: #808080; } .token.cdata { color: #808080; } .token.attr-name { color: #9cdcfe; } .token.attr-value, .token.attr-value .token.punctuation { color: #f3a281; } .token.attr-value .token.punctuation.attr-equals { color: #d4d4d4; } .token.entity { color: #569cd6; } .token.namespace { color: #4ec9b0; } /********************************************************* * Language Specific */ pre[class*='language-javascript'], code[class*='language-javascript'], pre[class*='language-jsx'], code[class*='language-jsx'], pre[class*='language-typescript'], code[class*='language-typescript'], pre[class*='language-tsx'], code[class*='language-tsx'] { color: #9cdcfe; } pre[class*='language-css'], code[class*='language-css'] { color: #f3a281; } pre[class*='language-html'], code[class*='language-html'] { color: #d4d4d4; } .language-regex .token.anchor { color: #dcdcaa; } .language-html .token.punctuation { color: #808080; } /********************************************************* * Line highlighting */ pre[data-line] { position: relative; } pre[class*='language-'] > code[class*='language-'] { position: relative; z-index: 1; } .line-highlight { position: absolute; left: 0; right: 0; padding: inherit 0; margin-top: 1em; background: #f7ebc6; box-shadow: inset 5px 0 0 #f7d87c; z-index: 0; pointer-events: none; line-height: inherit; white-space: pre; } /* works for line-numbers below 1000 lines */ pre[class*='language-'].line-numbers { position: relative; padding-left: 3.8em; counter-reset: linenumber; } pre[class*='language-'].line-numbers > code { position: relative; white-space: inherit; } .line-numbers .line-numbers-rows { position: absolute; pointer-events: none; top: 0; font-size: 100%; left: -3.8em; width: 3em; /* works for line-numbers below 1000 lines */ letter-spacing: -1px; border-right: 1px solid #999; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .line-numbers-rows > span { display: block; counter-increment: linenumber; } .line-numbers-rows > span:before { content: counter(linenumber); color: #999; display: block; padding-right: 0.8em; text-align: right; } ================================================ FILE: public/prism.js ================================================ /* PrismJS 1.24.1 https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+abap+abnf+actionscript+ada+agda+al+antlr4+apacheconf+apex+apl+applescript+aql+arduino+arff+asciidoc+aspnet+asm6502+autohotkey+autoit+bash+basic+batch+bbcode+birb+bison+bnf+brainfuck+brightscript+bro+bsl+c+csharp+cpp+cfscript+chaiscript+cil+clojure+cmake+cobol+coffeescript+concurnas+csp+coq+crystal+css-extras+csv+cypher+d+dart+dataweave+dax+dhall+diff+django+dns-zone-file+docker+dot+ebnf+editorconfig+eiffel+ejs+elixir+elm+etlua+erb+erlang+excel-formula+fsharp+factor+false+firestore-security-rules+flow+fortran+ftl+gml+gcode+gdscript+gedcom+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+hcl+hlsl+hoon+http+hpkp+hsts+ichigojam+icon+icu-message-format+idris+ignore+inform7+ini+io+j+java+javadoc+javadoclike+javastacktrace+jexl+jolie+jq+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+julia+keyman+kotlin+kumir+latex+latte+less+lilypond+liquid+lisp+livescript+llvm+log+lolcode+lua+makefile+markdown+markup-templating+matlab+mel+mizar+mongodb+monkey+moonscript+n1ql+n4js+nand2tetris-hdl+naniscript+nasm+neon+nevod+nginx+nim+nix+nsis+objectivec+ocaml+opencl+openqasm+oz+parigp+parser+pascal+pascaligo+psl+pcaxis+peoplecode+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+processing+prolog+promql+properties+protobuf+pug+puppet+pure+purebasic+purescript+python+qsharp+q+qml+qore+r+racket+jsx+tsx+reason+regex+rego+renpy+rest+rip+roboconf+robotframework+ruby+rust+sas+sass+scss+scala+scheme+shell-session+smali+smalltalk+smarty+sml+solidity+solution-file+soy+sparql+splunk-spl+sqf+sql+squirrel+stan+iecst+stylus+swift+t4-templating+t4-cs+t4-vb+tap+tcl+tt2+textile+toml+turtle+twig+typescript+typoscript+unrealscript+uri+v+vala+vbnet+velocity+verilog+vhdl+vim+visual-basic+warpscript+wasm+wiki+wolfram+xeora+xml-doc+xojo+xquery+yaml+yang+zig&plugins=line-numbers+show-invisibles+normalize-whitespace+treeview */ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,e={},M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);y+=m.value.length,m=m.next){var b=m.value;if(t.length>n.length)return;if(!(b instanceof W)){var k,x=1;if(h){if(!(k=z(v,y,n,f)))break;var w=k.index,A=k.index+k[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var E=m;E!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=I(t,j,O),y+=O.length),q(t,j,x);var C=new W(o,g?M.tokenize(S,g):S,d,S);if(m=I(t,j,C),L&&I(t,m,L),1l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function z(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function q(e,n,t){for(var r=n.next,a=0;a"+a.content+""},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var t=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(t&&(M.filename=t.src,t.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var a=document.readyState;"loading"===a||"interactive"===a&&t&&t.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; !function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; Prism.languages.abap={comment:/^\*.*/m,string:/(`|')(?:\\.|(?!\1)[^\\\r\n])*\1/m,"string-template":{pattern:/([|}])(?:\\.|[^\\|{\r\n])*(?=[|{])/,lookbehind:!0,alias:"string"},"eol-comment":{pattern:/(^|\s)".*/m,lookbehind:!0,alias:"comment"},keyword:{pattern:/(\s|\.|^)(?:SCIENTIFIC_WITH_LEADING_ZERO|SCALE_PRESERVING_SCIENTIFIC|RMC_COMMUNICATION_FAILURE|END-ENHANCEMENT-SECTION|MULTIPLY-CORRESPONDING|SUBTRACT-CORRESPONDING|VERIFICATION-MESSAGE|DIVIDE-CORRESPONDING|ENHANCEMENT-SECTION|CURRENCY_CONVERSION|RMC_SYSTEM_FAILURE|START-OF-SELECTION|MOVE-CORRESPONDING|RMC_INVALID_STATUS|CUSTOMER-FUNCTION|END-OF-DEFINITION|ENHANCEMENT-POINT|SYSTEM-EXCEPTIONS|ADD-CORRESPONDING|SCALE_PRESERVING|SELECTION-SCREEN|CURSOR-SELECTION|END-OF-SELECTION|LOAD-OF-PROGRAM|SCROLL-BOUNDARY|SELECTION-TABLE|EXCEPTION-TABLE|IMPLEMENTATIONS|PARAMETER-TABLE|RIGHT-JUSTIFIED|UNIT_CONVERSION|AUTHORITY-CHECK|LIST-PROCESSING|SIGN_AS_POSTFIX|COL_BACKGROUND|IMPLEMENTATION|INTERFACE-POOL|TRANSFORMATION|IDENTIFICATION|ENDENHANCEMENT|LINE-SELECTION|INITIALIZATION|LEFT-JUSTIFIED|SELECT-OPTIONS|SELECTION-SETS|COMMUNICATION|CORRESPONDING|DECIMAL_SHIFT|PRINT-CONTROL|VALUE-REQUEST|CHAIN-REQUEST|FUNCTION-POOL|FIELD-SYMBOLS|FUNCTIONALITY|INVERTED-DATE|SELECTION-SET|CLASS-METHODS|OUTPUT-LENGTH|CLASS-CODING|COL_NEGATIVE|ERRORMESSAGE|FIELD-GROUPS|HELP-REQUEST|NO-EXTENSION|NO-TOPOFPAGE|REDEFINITION|DISPLAY-MODE|ENDINTERFACE|EXIT-COMMAND|FIELD-SYMBOL|NO-SCROLLING|SHORTDUMP-ID|ACCESSPOLICY|CLASS-EVENTS|COL_POSITIVE|DECLARATIONS|ENHANCEMENTS|FILTER-TABLE|SWITCHSTATES|SYNTAX-CHECK|TRANSPORTING|ASYNCHRONOUS|SYNTAX-TRACE|TOKENIZATION|USER-COMMAND|WITH-HEADING|ABAP-SOURCE|BREAK-POINT|CHAIN-INPUT|COMPRESSION|FIXED-POINT|NEW-SECTION|NON-UNICODE|OCCURRENCES|RESPONSIBLE|SYSTEM-CALL|TRACE-TABLE|ABBREVIATED|CHAR-TO-HEX|END-OF-FILE|ENDFUNCTION|ENVIRONMENT|ASSOCIATION|COL_HEADING|EDITOR-CALL|END-OF-PAGE|ENGINEERING|IMPLEMENTED|INTENSIFIED|RADIOBUTTON|SYSTEM-EXIT|TOP-OF-PAGE|TRANSACTION|APPLICATION|CONCATENATE|DESTINATION|ENHANCEMENT|IMMEDIATELY|NO-GROUPING|PRECOMPILED|REPLACEMENT|TITLE-LINES|ACTIVATION|BYTE-ORDER|CLASS-POOL|CONNECTION|CONVERSION|DEFINITION|DEPARTMENT|EXPIRATION|INHERITING|MESSAGE-ID|NO-HEADING|PERFORMING|QUEUE-ONLY|RIGHTSPACE|SCIENTIFIC|STATUSINFO|STRUCTURES|SYNCPOINTS|WITH-TITLE|ATTRIBUTES|BOUNDARIES|CLASS-DATA|COL_NORMAL|DD\/MM\/YYYY|DESCENDING|INTERFACES|LINE-COUNT|MM\/DD\/YYYY|NON-UNIQUE|PRESERVING|SELECTIONS|STATEMENTS|SUBROUTINE|TRUNCATION|TYPE-POOLS|ARITHMETIC|BACKGROUND|ENDPROVIDE|EXCEPTIONS|IDENTIFIER|INDEX-LINE|OBLIGATORY|PARAMETERS|PERCENTAGE|PUSHBUTTON|RESOLUTION|COMPONENTS|DEALLOCATE|DISCONNECT|DUPLICATES|FIRST-LINE|HEAD-LINES|NO-DISPLAY|OCCURRENCE|RESPECTING|RETURNCODE|SUBMATCHES|TRACE-FILE|ASCENDING|BYPASSING|ENDMODULE|EXCEPTION|EXCLUDING|EXPORTING|INCREMENT|MATCHCODE|PARAMETER|PARTIALLY|PREFERRED|REFERENCE|REPLACING|RETURNING|SELECTION|SEPARATED|SPECIFIED|STATEMENT|TIMESTAMP|TYPE-POOL|ACCEPTING|APPENDAGE|ASSIGNING|COL_GROUP|COMPARING|CONSTANTS|DANGEROUS|IMPORTING|INSTANCES|LEFTSPACE|LOG-POINT|QUICKINFO|READ-ONLY|SCROLLING|SQLSCRIPT|STEP-LOOP|TOP-LINES|TRANSLATE|APPENDING|AUTHORITY|CHARACTER|COMPONENT|CONDITION|DIRECTORY|DUPLICATE|MESSAGING|RECEIVING|SUBSCREEN|ACCORDING|COL_TOTAL|END-LINES|ENDMETHOD|ENDSELECT|EXPANDING|EXTENSION|INCLUDING|INFOTYPES|INTERFACE|INTERVALS|LINE-SIZE|PF-STATUS|PROCEDURE|PROTECTED|REQUESTED|RESUMABLE|RIGHTPLUS|SAP-SPOOL|SECONDARY|STRUCTURE|SUBSTRING|TABLEVIEW|NUMOFCHAR|ADJACENT|ANALYSIS|ASSIGNED|BACKWARD|CHANNELS|CHECKBOX|CONTINUE|CRITICAL|DATAINFO|DD\/MM\/YY|DURATION|ENCODING|ENDCLASS|FUNCTION|LEFTPLUS|LINEFEED|MM\/DD\/YY|OVERFLOW|RECEIVED|SKIPPING|SORTABLE|STANDARD|SUBTRACT|SUPPRESS|TABSTRIP|TITLEBAR|TRUNCATE|UNASSIGN|WHENEVER|ANALYZER|COALESCE|COMMENTS|CONDENSE|DECIMALS|DEFERRED|ENDWHILE|EXPLICIT|KEYWORDS|MESSAGES|POSITION|PRIORITY|RECEIVER|RENAMING|TIMEZONE|TRAILING|ALLOCATE|CENTERED|CIRCULAR|CONTROLS|CURRENCY|DELETING|DESCRIBE|DISTANCE|ENDCATCH|EXPONENT|EXTENDED|GENERATE|IGNORING|INCLUDES|INTERNAL|MAJOR-ID|MODIFIER|NEW-LINE|OPTIONAL|PROPERTY|ROLLBACK|STARTING|SUPPLIED|ABSTRACT|CHANGING|CONTEXTS|CREATING|CUSTOMER|DATABASE|DAYLIGHT|DEFINING|DISTINCT|DIVISION|ENABLING|ENDCHAIN|ESCAPING|HARMLESS|IMPLICIT|INACTIVE|LANGUAGE|MINOR-ID|MULTIPLY|NEW-PAGE|NO-TITLE|POS_HIGH|SEPARATE|TEXTPOOL|TRANSFER|SELECTOR|DBMAXLEN|ITERATOR|ARCHIVE|BIT-XOR|BYTE-CO|COLLECT|COMMENT|CURRENT|DEFAULT|DISPLAY|ENDFORM|EXTRACT|LEADING|LISTBOX|LOCATOR|MEMBERS|METHODS|NESTING|POS_LOW|PROCESS|PROVIDE|RAISING|RESERVE|SECONDS|SUMMARY|VISIBLE|BETWEEN|BIT-AND|BYTE-CS|CLEANUP|COMPUTE|CONTROL|CONVERT|DATASET|ENDCASE|FORWARD|HEADERS|HOTSPOT|INCLUDE|INVERSE|KEEPING|NO-ZERO|OBJECTS|OVERLAY|PADDING|PATTERN|PROGRAM|REFRESH|SECTION|SUMMING|TESTING|VERSION|WINDOWS|WITHOUT|BIT-NOT|BYTE-CA|BYTE-NA|CASTING|CONTEXT|COUNTRY|DYNAMIC|ENABLED|ENDLOOP|EXECUTE|FRIENDS|HANDLER|HEADING|INITIAL|\*-INPUT|LOGFILE|MAXIMUM|MINIMUM|NO-GAPS|NO-SIGN|PRAGMAS|PRIMARY|PRIVATE|REDUCED|REPLACE|REQUEST|RESULTS|UNICODE|WARNING|ALIASES|BYTE-CN|BYTE-NS|CALLING|COL_KEY|COLUMNS|CONNECT|ENDEXEC|ENTRIES|EXCLUDE|FILTERS|FURTHER|HELP-ID|LOGICAL|MAPPING|MESSAGE|NAMETAB|OPTIONS|PACKAGE|PERFORM|RECEIVE|STATICS|VARYING|BINDING|CHARLEN|GREATER|XSTRLEN|ACCEPT|APPEND|DETAIL|ELSEIF|ENDING|ENDTRY|FORMAT|FRAMES|GIVING|HASHED|HEADER|IMPORT|INSERT|MARGIN|MODULE|NATIVE|OBJECT|OFFSET|REMOTE|RESUME|SAVING|SIMPLE|SUBMIT|TABBED|TOKENS|UNIQUE|UNPACK|UPDATE|WINDOW|YELLOW|ACTUAL|ASPECT|CENTER|CURSOR|DELETE|DIALOG|DIVIDE|DURING|ERRORS|EVENTS|EXTEND|FILTER|HANDLE|HAVING|IGNORE|LITTLE|MEMORY|NO-GAP|OCCURS|OPTION|PERSON|PLACES|PUBLIC|REDUCE|REPORT|RESULT|SINGLE|SORTED|SWITCH|SYNTAX|TARGET|VALUES|WRITER|ASSERT|BLOCKS|BOUNDS|BUFFER|CHANGE|COLUMN|COMMIT|CONCAT|COPIES|CREATE|DDMMYY|DEFINE|ENDIAN|ESCAPE|EXPAND|KERNEL|LAYOUT|LEGACY|LEVELS|MMDDYY|NUMBER|OUTPUT|RANGES|READER|RETURN|SCREEN|SEARCH|SELECT|SHARED|SOURCE|STABLE|STATIC|SUBKEY|SUFFIX|TABLES|UNWIND|YYMMDD|ASSIGN|BACKUP|BEFORE|BINARY|BIT-OR|BLANKS|CLIENT|CODING|COMMON|DEMAND|DYNPRO|EXCEPT|EXISTS|EXPORT|FIELDS|GLOBAL|GROUPS|LENGTH|LOCALE|MEDIUM|METHOD|MODIFY|NESTED|OTHERS|REJECT|SCROLL|SUPPLY|SYMBOL|ENDFOR|STRLEN|ALIGN|BEGIN|BOUND|ENDAT|ENTRY|EVENT|FINAL|FLUSH|GRANT|INNER|SHORT|USING|WRITE|AFTER|BLACK|BLOCK|CLOCK|COLOR|COUNT|DUMMY|EMPTY|ENDDO|ENDON|GREEN|INDEX|INOUT|LEAVE|LEVEL|LINES|MODIF|ORDER|OUTER|RANGE|RESET|RETRY|RIGHT|SMART|SPLIT|STYLE|TABLE|THROW|UNDER|UNTIL|UPPER|UTF-8|WHERE|ALIAS|BLANK|CLEAR|CLOSE|EXACT|FETCH|FIRST|FOUND|GROUP|LLANG|LOCAL|OTHER|REGEX|SPOOL|TITLE|TYPES|VALID|WHILE|ALPHA|BOXED|CATCH|CHAIN|CHECK|CLASS|COVER|ENDIF|EQUIV|FIELD|FLOOR|FRAME|INPUT|LOWER|MATCH|NODES|PAGES|PRINT|RAISE|ROUND|SHIFT|SPACE|SPOTS|STAMP|STATE|TASKS|TIMES|TRMAC|ULINE|UNION|VALUE|WIDTH|EQUAL|LOG10|TRUNC|BLOB|CASE|CEIL|CLOB|COND|EXIT|FILE|GAPS|HOLD|INCL|INTO|KEEP|KEYS|LAST|LINE|LONG|LPAD|MAIL|MODE|OPEN|PINK|READ|ROWS|TEST|THEN|ZERO|AREA|BACK|BADI|BYTE|CAST|EDIT|EXEC|FAIL|FIND|FKEQ|FONT|FREE|GKEQ|HIDE|INIT|ITNO|LATE|LOOP|MAIN|MARK|MOVE|NEXT|NULL|RISK|ROLE|UNIT|WAIT|ZONE|BASE|CALL|CODE|DATA|DATE|FKGE|GKGE|HIGH|KIND|LEFT|LIST|MASK|MESH|NAME|NODE|PACK|PAGE|POOL|SEND|SIGN|SIZE|SOME|STOP|TASK|TEXT|TIME|USER|VARY|WITH|WORD|BLUE|CONV|COPY|DEEP|ELSE|FORM|FROM|HINT|ICON|JOIN|LIKE|LOAD|ONLY|PART|SCAN|SKIP|SORT|TYPE|UNIX|VIEW|WHEN|WORK|ACOS|ASIN|ATAN|COSH|EACH|FRAC|LESS|RTTI|SINH|SQRT|TANH|AVG|BIT|DIV|ISO|LET|OUT|PAD|SQL|ALL|CI_|CPI|END|LOB|LPI|MAX|MIN|NEW|OLE|RUN|SET|\?TO|YES|ABS|ADD|AND|BIG|FOR|HDB|JOB|LOW|NOT|SAP|TRY|VIA|XML|ANY|GET|IDS|KEY|MOD|OFF|PUT|RAW|RED|REF|SUM|TAB|XSD|CNT|COS|EXP|LOG|SIN|TAN|XOR|AT|CO|CP|DO|GT|ID|IF|NS|OR|BT|CA|CS|GE|NA|NB|EQ|IN|LT|NE|NO|OF|ON|PF|TO|AS|BY|CN|IS|LE|NP|UP|E|I|M|O|Z|C|X)\b/i,lookbehind:!0},number:/\b\d+\b/,operator:{pattern:/(\s)(?:\*\*?|<[=>]?|>=?|\?=|[-+\/=])(?=\s)/,lookbehind:!0},"string-operator":{pattern:/(\s)&&?(?=\s)/,lookbehind:!0,alias:"keyword"},"token-operator":[{pattern:/(\w)(?:->?|=>|[~|{}])(?=\w)/,lookbehind:!0,alias:"punctuation"},{pattern:/[|{}]/,alias:"punctuation"}],punctuation:/[,.:()]/}; !function(n){var i="(?:ALPHA|BIT|CHAR|CR|CRLF|CTL|DIGIT|DQUOTE|HEXDIG|HTAB|LF|LWSP|OCTET|SP|VCHAR|WSP)";Prism.languages.abnf={comment:/;.*/,string:{pattern:/(?:%[is])?"[^"\n\r]*"/,greedy:!0,inside:{punctuation:/^%[is]/}},range:{pattern:/%(?:b[01]+-[01]+|d\d+-\d+|x[A-F\d]+-[A-F\d]+)/i,alias:"number"},terminal:{pattern:/%(?:b[01]+(?:\.[01]+)*|d\d+(?:\.\d+)*|x[A-F\d]+(?:\.[A-F\d]+)*)/i,alias:"number"},repetition:{pattern:/(^|[^\w-])(?:\d*\*\d*|\d+)/,lookbehind:!0,alias:"operator"},definition:{pattern:/(^[ \t]*)(?:[a-z][\w-]*|<[^<>\r\n]*>)(?=\s*=)/m,lookbehind:!0,alias:"keyword",inside:{punctuation:/<|>/}},"core-rule":{pattern:RegExp("(?:(^|[^<\\w-])"+i+"|<"+i+">)(?![\\w-])","i"),lookbehind:!0,alias:["rule","constant"],inside:{punctuation:/<|>/}},rule:{pattern:/(^|[^<\w-])[a-z][\w-]*|<[^<>\r\n]*>/i,lookbehind:!0,inside:{punctuation:/<|>/}},operator:/=\/?|\//,punctuation:/[()\[\]]/}}(); Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:Prism.languages.markup}}); Prism.languages.ada={comment:/--.*/,string:/"(?:""|[^"\r\f\n])*"/i,number:[{pattern:/\b\d(?:_?\d)*#[\dA-F](?:_?[\dA-F])*(?:\.[\dA-F](?:_?[\dA-F])*)?#(?:E[+-]?\d(?:_?\d)*)?/i},{pattern:/\b\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:E[+-]?\d(?:_?\d)*)?\b/i}],"attr-name":/\b'\w+/i,keyword:/\b(?:abort|abs|abstract|accept|access|aliased|all|and|array|at|begin|body|case|constant|declare|delay|delta|digits|do|else|new|return|elsif|end|entry|exception|exit|for|function|generic|goto|if|in|interface|is|limited|loop|mod|not|null|of|others|out|overriding|package|pragma|private|procedure|protected|raise|range|record|rem|renames|requeue|reverse|select|separate|some|subtype|synchronized|tagged|task|terminate|then|type|until|use|when|while|with|xor)\b/i,boolean:/\b(?:true|false)\b/i,operator:/<[=>]?|>=?|=>?|:=|\/=?|\*\*?|[&+-]/,punctuation:/\.\.?|[,;():]/,char:/'.'/,variable:/\b[a-z](?:\w)*\b/i}; Prism.languages.agda={comment:/\{-[\s\S]*?(?:-\}|$)|--.*/,string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},punctuation:/[(){}⦃⦄.;@]/,"class-name":{pattern:/((?:data|record) +)\S+/,lookbehind:!0},function:{pattern:/(^[ \t]*)(?!\s)[^:\r\n]+(?=:)/m,lookbehind:!0},operator:{pattern:/(^\s*|\s)(?:[=|:∀→λ\\?_]|->)(?=\s)/,lookbehind:!0},keyword:/\b(?:Set|abstract|constructor|data|eta-equality|field|forall|hiding|import|in|inductive|infix|infixl|infixr|instance|let|macro|module|mutual|no-eta-equality|open|overlap|pattern|postulate|primitive|private|public|quote|quoteContext|quoteGoal|quoteTerm|record|renaming|rewrite|syntax|tactic|unquote|unquoteDecl|unquoteDef|using|variable|where|with)\b/}; Prism.languages.al={comment:/\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/'(?:''|[^'\r\n])*'(?!')|"(?:""|[^"\r\n])*"(?!")/,greedy:!0},function:{pattern:/(\b(?:event|procedure|trigger)\s+|(?:^|[^.])\.\s*)[a-z_]\w*(?=\s*\()/i,lookbehind:!0},keyword:[/\b(?:array|asserterror|begin|break|case|do|downto|else|end|event|exit|for|foreach|function|if|implements|in|indataset|interface|internal|local|of|procedure|program|protected|repeat|runonclient|securityfiltering|suppressdispose|temporary|then|to|trigger|until|var|while|with|withevents)\b/i,/\b(?:action|actions|addafter|addbefore|addfirst|addlast|area|assembly|chartpart|codeunit|column|controladdin|cuegroup|customizes|dataitem|dataset|dotnet|elements|enum|enumextension|extends|field|fieldattribute|fieldelement|fieldgroup|fieldgroups|fields|filter|fixed|grid|group|key|keys|label|labels|layout|modify|moveafter|movebefore|movefirst|movelast|page|pagecustomization|pageextension|part|profile|query|repeater|report|requestpage|schema|separator|systempart|table|tableelement|tableextension|textattribute|textelement|type|usercontrol|value|xmlport)\b/i],number:/\b(?:0x[\da-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)(?:F|U(?:LL?)?|LL?)?\b/i,boolean:/\b(?:false|true)\b/i,variable:/\b(?:Curr(?:FieldNo|Page|Report)|RequestOptionsPage|x?Rec)\b/,"class-name":/\b(?:automation|biginteger|bigtext|blob|boolean|byte|char|clienttype|code|completiontriggererrorlevel|connectiontype|database|dataclassification|datascope|date|dateformula|datetime|decimal|defaultlayout|dialog|dictionary|dotnetassembly|dotnettypedeclaration|duration|errorinfo|errortype|executioncontext|executionmode|fieldclass|fieldref|fieldtype|file|filterpagebuilder|guid|httpclient|httpcontent|httpheaders|httprequestmessage|httpresponsemessage|instream|integer|joker|jsonarray|jsonobject|jsontoken|jsonvalue|keyref|list|moduledependencyinfo|moduleinfo|none|notification|notificationscope|objecttype|option|outstream|pageresult|record|recordid|recordref|reportformat|securityfilter|sessionsettings|tableconnectiontype|tablefilter|testaction|testfield|testfilterfield|testpage|testpermissions|testrequestpage|text|textbuilder|textconst|textencoding|time|transactionmodel|transactiontype|variant|verbosity|version|view|views|webserviceactioncontext|webserviceactionresultcode|xmlattribute|xmlattributecollection|xmlcdata|xmlcomment|xmldeclaration|xmldocument|xmldocumenttype|xmlelement|xmlnamespacemanager|xmlnametable|xmlnode|xmlnodelist|xmlprocessinginstruction|xmlreadoptions|xmltext|xmlwriteoptions)\b/i,operator:/\.\.|:[=:]|[-+*/]=?|<>|[<>]=?|=|\b(?:and|div|mod|not|or|xor)\b/i,punctuation:/[()\[\]{}:.;,]/}; Prism.languages.antlr4={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,string:{pattern:/'(?:\\.|[^\\'\r\n])*'/,greedy:!0},"character-class":{pattern:/\[(?:\\.|[^\\\]\r\n])*\]/,greedy:!0,alias:"regex",inside:{range:{pattern:/([^[]|(?:^|[^\\])(?:\\\\)*\\\[)-(?!\])/,lookbehind:!0,alias:"punctuation"},escape:/\\(?:u(?:[a-fA-F\d]{4}|\{[a-fA-F\d]+\})|[pP]\{[=\w-]+\}|[^\r\nupP])/,punctuation:/[\[\]]/}},action:{pattern:/\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\}/,greedy:!0,inside:{content:{pattern:/(\{)[\s\S]+(?=\})/,lookbehind:!0},punctuation:/[{}]/}},command:{pattern:/(->\s*(?!\s))(?:\s*(?:,\s*)?\b[a-z]\w*(?:\s*\([^()\r\n]*\))?)+(?=\s*;)/i,lookbehind:!0,inside:{function:/\b\w+(?=\s*(?:[,(]|$))/,punctuation:/[,()]/}},annotation:{pattern:/@\w+(?:::\w+)*/,alias:"keyword"},label:{pattern:/#[ \t]*\w+/,alias:"punctuation"},keyword:/\b(?:catch|channels|finally|fragment|grammar|import|lexer|locals|mode|options|parser|returns|throws|tokens)\b/,definition:[{pattern:/\b[a-z]\w*(?=\s*:)/,alias:["rule","class-name"]},{pattern:/\b[A-Z]\w*(?=\s*:)/,alias:["token","constant"]}],constant:/\b[A-Z][A-Z_]*\b/,operator:/\.\.|->|[|~]|[*+?]\??/,punctuation:/[;:()=]/},Prism.languages.g4=Prism.languages.antlr4; Prism.languages.apacheconf={comment:/#.*/,"directive-inline":{pattern:/(^[\t ]*)\b(?:AcceptFilter|AcceptPathInfo|AccessFileName|Action|Add(?:Alt|AltByEncoding|AltByType|Charset|DefaultCharset|Description|Encoding|Handler|Icon|IconByEncoding|IconByType|InputFilter|Language|ModuleInfo|OutputFilter|OutputFilterByType|Type)|Alias|AliasMatch|Allow(?:CONNECT|EncodedSlashes|Methods|Override|OverrideList)?|Anonymous(?:_LogEmail|_MustGiveEmail|_NoUserID|_VerifyEmail)?|AsyncRequestWorkerFactor|Auth(?:BasicAuthoritative|BasicFake|BasicProvider|BasicUseDigestAlgorithm|DBDUserPWQuery|DBDUserRealmQuery|DBMGroupFile|DBMType|DBMUserFile|Digest(?:Algorithm|Domain|NonceLifetime|Provider|Qop|ShmemSize)|Form(?:Authoritative|Body|DisableNoStore|FakeBasicAuth|Location|LoginRequiredLocation|LoginSuccessLocation|LogoutLocation|Method|Mimetype|Password|Provider|SitePassphrase|Size|Username)|GroupFile|LDAP(?:AuthorizePrefix|BindAuthoritative|BindDN|BindPassword|CharsetConfig|CompareAsUser|CompareDNOnServer|DereferenceAliases|GroupAttribute|GroupAttributeIsDN|InitialBindAsUser|InitialBindPattern|MaxSubGroupDepth|RemoteUserAttribute|RemoteUserIsDN|SearchAsUser|SubGroupAttribute|SubGroupClass|Url)|Merging|Name|Type|UserFile|nCache(?:Context|Enable|ProvideFor|SOCache|Timeout)|nzFcgiCheckAuthnProvider|nzFcgiDefineProvider|zDBDLoginToReferer|zDBDQuery|zDBDRedirectQuery|zDBMType|zSendForbiddenOnFailure)|BalancerGrowth|BalancerInherit|BalancerMember|BalancerPersist|BrowserMatch|BrowserMatchNoCase|BufferSize|BufferedLogs|CGIDScriptTimeout|CGIMapExtension|Cache(?:DefaultExpire|DetailHeader|DirLength|DirLevels|Disable|Enable|File|Header|IgnoreCacheControl|IgnoreHeaders|IgnoreNoLastMod|IgnoreQueryString|IgnoreURLSessionIdentifiers|KeyBaseURL|LastModifiedFactor|Lock|LockMaxAge|LockPath|MaxExpire|MaxFileSize|MinExpire|MinFileSize|NegotiatedDocs|QuickHandler|ReadSize|ReadTime|Root|Socache(?:MaxSize|MaxTime|MinTime|ReadSize|ReadTime)?|StaleOnError|StoreExpired|StoreNoStore|StorePrivate)|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckCaseOnly|CheckSpelling|ChrootDir|ContentDigest|CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|DBDExptime|DBDInitSQL|DBDKeep|DBDMax|DBDMin|DBDParams|DBDPersist|DBDPrepareSQL|DBDriver|DTracePrivileges|Dav|DavDepthInfinity|DavGenericLockDB|DavLockDB|DavMinTimeout|DefaultIcon|DefaultLanguage|DefaultRuntimeDir|DefaultType|Define|Deflate(?:BufferSize|CompressionLevel|FilterNote|InflateLimitRequestBody|InflateRatio(?:Burst|Limit)|MemLevel|WindowSize)|Deny|DirectoryCheckHandler|DirectoryIndex|DirectoryIndexRedirect|DirectorySlash|DocumentRoot|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|Error|ErrorDocument|ErrorLog|ErrorLogFormat|Example|ExpiresActive|ExpiresByType|ExpiresDefault|ExtFilterDefine|ExtFilterOptions|ExtendedStatus|FallbackResource|FileETag|FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace|ForceLanguagePriority|ForceType|ForensicLog|GprofDir|GracefulShutdownTimeout|Group|Header|HeaderName|Heartbeat(?:Address|Listen|MaxServers|Storage)|HostnameLookups|ISAPI(?:AppendLogToErrors|AppendLogToQuery|CacheFile|FakeAsync|LogNotSupported|ReadAheadBuffer)|IdentityCheck|IdentityCheckTimeout|ImapBase|ImapDefault|ImapMenu|Include|IncludeOptional|Index(?:HeadInsert|Ignore|IgnoreReset|Options|OrderDefault|StyleSheet)|InputSed|KeepAlive|KeepAliveTimeout|KeptBodySize|LDAP(?:CacheEntries|CacheTTL|ConnectionPoolTTL|ConnectionTimeout|LibraryDebug|OpCacheEntries|OpCacheTTL|ReferralHopLimit|Referrals|Retries|RetryDelay|SharedCacheFile|SharedCacheSize|Timeout|TrustedClientCert|TrustedGlobalCert|TrustedMode|VerifyServerCert)|LanguagePriority|Limit(?:InternalRecursion|Request(?:Body|FieldSize|Fields|Line)|XMLRequestBody)|Listen|ListenBackLog|LoadFile|LoadModule|LogFormat|LogLevel|LogMessage|LuaAuthzProvider|LuaCodeCache|Lua(?:Hook(?:AccessChecker|AuthChecker|CheckUserID|Fixups|InsertFilter|Log|MapToStorage|TranslateName|TypeChecker)|Inherit|InputFilter|MapHandler|OutputFilter|PackageCPath|PackagePath|QuickHandler|Root|Scope)|MMapFile|Max(?:ConnectionsPerChild|KeepAliveRequests|MemFree|RangeOverlaps|RangeReversals|Ranges|RequestWorkers|SpareServers|SpareThreads|Threads)|MergeTrailers|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads|ModMimeUsePathInfo|ModemStandard|MultiviewsMatch|Mutex|NWSSLTrustedCerts|NWSSLUpgradeable|NameVirtualHost|NoProxy|Options|Order|OutputSed|PassEnv|PidFile|PrivilegesMode|Protocol|ProtocolEcho|Proxy(?:AddHeaders|BadHeader|Block|Domain|ErrorOverride|ExpressDBMFile|ExpressDBMType|ExpressEnable|FtpDirCharset|FtpEscapeWildcards|FtpListOnWildcard|HTML(?:BufSize|CharsetOut|DocType|Enable|Events|Extended|Fixups|Interp|Links|Meta|StripComments|URLMap)|IOBufferSize|MaxForwards|Pass(?:Inherit|InterpolateEnv|Match|Reverse|ReverseCookieDomain|ReverseCookiePath)?|PreserveHost|ReceiveBufferSize|Remote|RemoteMatch|Requests|SCGIInternalRedirect|SCGISendfile|Set|SourceAddress|Status|Timeout|Via)|RLimitCPU|RLimitMEM|RLimitNPROC|ReadmeName|ReceiveBufferSize|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ReflectorHeader|RemoteIP(?:Header|InternalProxy|InternalProxyList|ProxiesHeader|TrustedProxy|TrustedProxyList)|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader|RequestReadTimeout|Require|Rewrite(?:Base|Cond|Engine|Map|Options|Rule)|SSIETag|SSIEndTag|SSIErrorMsg|SSILastModified|SSILegacyExprParser|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSL(?:CACertificateFile|CACertificatePath|CADNRequestFile|CADNRequestPath|CARevocationCheck|CARevocationFile|CARevocationPath|CertificateChainFile|CertificateFile|CertificateKeyFile|CipherSuite|Compression|CryptoDevice|Engine|FIPS|HonorCipherOrder|InsecureRenegotiation|OCSP(?:DefaultResponder|Enable|OverrideResponder|ResponderTimeout|ResponseMaxAge|ResponseTimeSkew|UseRequestNonce)|OpenSSLConfCmd|Options|PassPhraseDialog|Protocol|Proxy(?:CACertificateFile|CACertificatePath|CARevocation(?:Check|File|Path)|CheckPeer(?:CN|Expire|Name)|CipherSuite|Engine|MachineCertificate(?:ChainFile|File|Path)|Protocol|Verify|VerifyDepth)|RandomSeed|RenegBufferSize|Require|RequireSSL|SRPUnknownUserSeed|SRPVerifierFile|Session(?:Cache|CacheTimeout|TicketKeyFile|Tickets)|Stapling(?:Cache|ErrorCacheTimeout|FakeTryLater|ForceURL|ResponderTimeout|ResponseMaxAge|ResponseTimeSkew|ReturnResponderErrors|StandardCacheTimeout)|StrictSNIVHostCheck|UseStapling|UserName|VerifyClient|VerifyDepth)|Satisfy|ScoreBoardFile|Script(?:Alias|AliasMatch|InterpreterSource|Log|LogBuffer|LogLength|Sock)?|SecureListen|SeeRequestTail|SendBufferSize|Server(?:Admin|Alias|Limit|Name|Path|Root|Signature|Tokens)|Session(?:Cookie(?:Name|Name2|Remove)|Crypto(?:Cipher|Driver|Passphrase|PassphraseFile)|DBD(?:CookieName|CookieName2|CookieRemove|DeleteLabel|InsertLabel|PerUser|SelectLabel|UpdateLabel)|Env|Exclude|Header|Include|MaxAge)?|SetEnv|SetEnvIf|SetEnvIfExpr|SetEnvIfNoCase|SetHandler|SetInputFilter|SetOutputFilter|StartServers|StartThreads|Substitute|Suexec|SuexecUserGroup|ThreadLimit|ThreadStackSize|ThreadsPerChild|TimeOut|TraceEnable|TransferLog|TypesConfig|UnDefine|UndefMacro|UnsetEnv|Use|UseCanonicalName|UseCanonicalPhysicalPort|User|UserDir|VHostCGIMode|VHostCGIPrivs|VHostGroup|VHostPrivs|VHostSecure|VHostUser|Virtual(?:DocumentRoot|ScriptAlias)(?:IP)?|WatchdogInterval|XBitHack|xml2EncAlias|xml2EncDefault|xml2StartParse)\b/im,lookbehind:!0,alias:"property"},"directive-block":{pattern:/<\/?\b(?:Auth[nz]ProviderAlias|Directory|DirectoryMatch|Else|ElseIf|Files|FilesMatch|If|IfDefine|IfModule|IfVersion|Limit|LimitExcept|Location|LocationMatch|Macro|Proxy|Require(?:All|Any|None)|VirtualHost)\b.*>/i,inside:{"directive-block":{pattern:/^<\/?\w+/,inside:{punctuation:/^<\/?/},alias:"tag"},"directive-block-parameter":{pattern:/.*[^>]/,inside:{punctuation:/:/,string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}}},alias:"attr-value"},punctuation:/>/},alias:"tag"},"directive-flags":{pattern:/\[(?:[\w=],?)+\]/,alias:"keyword"},string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}},variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/,regex:/\^?.*\$|\^.*\$?/}; Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:S|ING)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|IN|ILIKE|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; !function(e){var t=/\b(?:abstract|activate|and|any|array|as|asc|autonomous|begin|bigdecimal|blob|boolean|break|bulk|by|byte|case|cast|catch|char|class|collect|commit|const|continue|currency|date|datetime|decimal|default|delete|desc|do|double|else|end|enum|exception|exit|export|extends|final|finally|float|for|from|global|goto|group|having|hint|if|implements|import|in|inner|insert|instanceof|int|integer|interface|into|join|like|limit|list|long|loop|map|merge|new|not|null|nulls|number|object|of|on|or|outer|override|package|parallel|pragma|private|protected|public|retrieve|return|rollback|select|set|short|sObject|sort|static|string|super|switch|synchronized|system|testmethod|then|this|throw|time|transaction|transient|trigger|try|undelete|update|upsert|using|virtual|void|webservice|when|where|while|get(?=\s*[{};])|(?:after|before)(?=\s+[a-z])|(?:inherited|with|without)\s+sharing)\b/i,n="\\b(?:(?=[a-z_]\\w*\\s*[<\\[])|(?!))[A-Z_]\\w*(?:\\s*\\.\\s*[A-Z_]\\w*)*\\b(?:\\s*(?:\\[\\s*\\]|<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>))*".replace(//g,function(){return t.source});function i(e){return RegExp(e.replace(//g,function(){return n}),"i")}var a={keyword:t,punctuation:/[()\[\]{};,:.<>]/};e.languages.apex={comment:e.languages.clike.comment,string:e.languages.clike.string,sql:{pattern:/((?:[=,({:]|\breturn)\s*)\[[^\[\]]*\]/i,lookbehind:!0,greedy:!0,alias:"language-sql",inside:e.languages.sql},annotation:{pattern:/@\w+\b/,alias:"punctuation"},"class-name":[{pattern:i("(\\b(?:class|enum|extends|implements|instanceof|interface|new|trigger\\s+\\w+\\s+on)\\s+)"),lookbehind:!0,inside:a},{pattern:i("(\\(\\s*)(?=\\s*\\)\\s*[\\w(])"),lookbehind:!0,inside:a},{pattern:i("(?=\\s*\\w+\\s*[;=,(){:])"),inside:a}],trigger:{pattern:/(\btrigger\s+)\w+\b/i,lookbehind:!0,alias:"class-name"},keyword:t,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/i,number:/(?:\B\.\d+|\b\d+(?:\.\d+|L)?)\b/i,operator:/[!=](?:==?)?|\?\.?|&&|\|\||--|\+\+|[-+*/^&|]=?|:|<{1,3}=?/,punctuation:/[()\[\]{};,.]/}}(Prism); Prism.languages.apl={comment:/(?:⍝|#[! ]).*$/m,string:{pattern:/'(?:[^'\r\n]|'')*'/,greedy:!0},number:/¯?(?:\d*\.?\b\d+(?:e[+¯]?\d+)?|¯|∞)(?:j¯?(?:(?:\d+(?:\.\d+)?|\.\d+)(?:e[+¯]?\d+)?|¯|∞))?/i,statement:/:[A-Z][a-z][A-Za-z]*\b/,"system-function":{pattern:/⎕[A-Z]+/i,alias:"function"},constant:/[⍬⌾#⎕⍞]/,function:/[-+×÷⌈⌊∣|⍳⍸?*⍟○!⌹<≤=>≥≠≡≢∊⍷∪∩~∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⊆⊇⌷⍋⍒⊤⊥⍕⍎⊣⊢⍁⍂≈⍯↗¤→]/,"monadic-operator":{pattern:/[\\\/⌿⍀¨⍨⌶&∥]/,alias:"operator"},"dyadic-operator":{pattern:/[.⍣⍠⍤∘⌸@⌺⍥]/,alias:"operator"},assignment:{pattern:/←/,alias:"keyword"},punctuation:/[\[;\]()◇⋄]/,dfn:{pattern:/[{}⍺⍵⍶⍹∇⍫:]/,alias:"builtin"}}; Prism.languages.applescript={comment:[/\(\*(?:\(\*(?:[^*]|\*(?!\)))*\*\)|(?!\(\*)[\s\S])*?\*\)/,/--.+/,/#.+/],string:/"(?:\\.|[^"\\\r\n])*"/,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e-?\d+)?\b/i,operator:[/[&=≠≤≥*+\-\/÷^]|[<>]=?/,/\b(?:(?:start|begin|end)s? with|(?:(?:does not|doesn't) contain|contains?)|(?:is|isn't|is not) (?:in|contained by)|(?:(?:is|isn't|is not) )?(?:greater|less) than(?: or equal)?(?: to)?|(?:(?:does not|doesn't) come|comes) (?:before|after)|(?:is|isn't|is not) equal(?: to)?|(?:(?:does not|doesn't) equal|equals|equal to|isn't|is not)|(?:a )?(?:ref(?: to)?|reference to)|(?:and|or|div|mod|as|not))\b/],keyword:/\b(?:about|above|after|against|apart from|around|aside from|at|back|before|beginning|behind|below|beneath|beside|between|but|by|considering|continue|copy|does|eighth|else|end|equal|error|every|exit|false|fifth|first|for|fourth|from|front|get|given|global|if|ignoring|in|instead of|into|is|it|its|last|local|me|middle|my|ninth|of|on|onto|out of|over|prop|property|put|repeat|return|returning|second|set|seventh|since|sixth|some|tell|tenth|that|the|then|third|through|thru|timeout|times|to|transaction|true|try|until|where|while|whose|with|without)\b/,class:{pattern:/\b(?:alias|application|boolean|class|constant|date|file|integer|list|number|POSIX file|real|record|reference|RGB color|script|text|centimetres|centimeters|feet|inches|kilometres|kilometers|metres|meters|miles|yards|square feet|square kilometres|square kilometers|square metres|square meters|square miles|square yards|cubic centimetres|cubic centimeters|cubic feet|cubic inches|cubic metres|cubic meters|cubic yards|gallons|litres|liters|quarts|grams|kilograms|ounces|pounds|degrees Celsius|degrees Fahrenheit|degrees Kelvin)\b/,alias:"builtin"},punctuation:/[{}():,¬«»《》]/}; Prism.languages.aql={comment:/\/\/.*|\/\*[\s\S]*?\*\//,property:{pattern:/([{,]\s*)(?:(?!\d)\w+|(["'´`])(?:(?!\2)[^\\\r\n]|\\.)*\2)(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(["'´`])(?:(?!\1)[^\\\r\n]|\\.)*\1/,greedy:!0},variable:/@@?\w+/,keyword:[{pattern:/(\bWITH\s+)COUNT(?=\s+INTO\b)/i,lookbehind:!0},/\b(?:AGGREGATE|ALL|AND|ANY|ASC|COLLECT|DESC|DISTINCT|FILTER|FOR|GRAPH|IN|INBOUND|INSERT|INTO|K_PATHS|K_SHORTEST_PATHS|LET|LIKE|LIMIT|NONE|NOT|NULL|OR|OUTBOUND|REMOVE|REPLACE|RETURN|SHORTEST_PATH|SORT|UPDATE|UPSERT|WINDOW|WITH)\b/i,{pattern:/(^|[^\w.[])(?:KEEP|PRUNE|SEARCH|TO)\b/i,lookbehind:!0},{pattern:/(^|[^\w.[])(?:CURRENT|NEW|OLD)\b/,lookbehind:!0},{pattern:/\bOPTIONS(?=\s*\{)/i}],function:/\b(?!\d)\w+(?=\s*\()/,boolean:/\b(?:true|false)\b/i,range:{pattern:/\.\./,alias:"operator"},number:[/\b0b[01]+/i,/\b0x[0-9a-f]+/i,/(?:\B\.\d+|\b(?:0|[1-9]\d*)(?:\.\d+)?)(?:e[+-]?\d+)?/i],operator:/\*{2,}|[=!]~|[!=<>]=?|&&|\|\||[-+*/%]/,punctuation:/::|[?.:,;()[\]{}]/}; Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; !function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,function(){return n})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); Prism.languages.arduino=Prism.languages.extend("cpp",{constant:/\b(?:DIGITAL_MESSAGE|FIRMATA_STRING|ANALOG_MESSAGE|REPORT_DIGITAL|REPORT_ANALOG|INPUT_PULLUP|SET_PIN_MODE|INTERNAL2V56|SYSTEM_RESET|LED_BUILTIN|INTERNAL1V1|SYSEX_START|INTERNAL|EXTERNAL|DEFAULT|OUTPUT|INPUT|HIGH|LOW)\b/,keyword:/\b(?:setup|if|else|while|do|for|return|in|instanceof|default|function|loop|goto|switch|case|new|try|throw|catch|finally|null|break|continue|boolean|bool|void|byte|word|string|String|array|int|long|integer|double)\b/,builtin:/\b(?:KeyboardController|MouseController|SoftwareSerial|EthernetServer|EthernetClient|LiquidCrystal|LiquidCrystal_I2C|RobotControl|GSMVoiceCall|EthernetUDP|EsploraTFT|HttpClient|RobotMotor|WiFiClient|GSMScanner|FileSystem|Scheduler|GSMServer|YunClient|YunServer|IPAddress|GSMClient|GSMModem|Keyboard|Ethernet|Console|GSMBand|Esplora|Stepper|Process|WiFiUDP|GSM_SMS|Mailbox|USBHost|Firmata|PImage|Client|Server|GSMPIN|FileIO|Bridge|Serial|EEPROM|Stream|Mouse|Audio|Servo|File|Task|GPRS|WiFi|Wire|TFT|GSM|SPI|SD|runShellCommandAsynchronously|analogWriteResolution|retrieveCallingNumber|printFirmwareVersion|analogReadResolution|sendDigitalPortPair|noListenOnLocalhost|readJoystickButton|setFirmwareVersion|readJoystickSwitch|scrollDisplayRight|getVoiceCallStatus|scrollDisplayLeft|writeMicroseconds|delayMicroseconds|beginTransmission|getSignalStrength|runAsynchronously|getAsynchronously|listenOnLocalhost|getCurrentCarrier|readAccelerometer|messageAvailable|sendDigitalPorts|lineFollowConfig|countryNameWrite|runShellCommand|readStringUntil|rewindDirectory|readTemperature|setClockDivider|readLightSensor|endTransmission|analogReference|detachInterrupt|countryNameRead|attachInterrupt|encryptionType|readBytesUntil|robotNameWrite|readMicrophone|robotNameRead|cityNameWrite|userNameWrite|readJoystickY|readJoystickX|mouseReleased|openNextFile|scanNetworks|noInterrupts|digitalWrite|beginSpeaker|mousePressed|isActionDone|mouseDragged|displayLogos|noAutoscroll|addParameter|remoteNumber|getModifiers|keyboardRead|userNameRead|waitContinue|processInput|parseCommand|printVersion|readNetworks|writeMessage|blinkVersion|cityNameRead|readMessage|setDataMode|parsePacket|isListening|setBitOrder|beginPacket|isDirectory|motorsWrite|drawCompass|digitalRead|clearScreen|serialEvent|rightToLeft|setTextSize|leftToRight|requestFrom|keyReleased|compassRead|analogWrite|interrupts|WiFiServer|disconnect|playMelody|parseFloat|autoscroll|getPINUsed|setPINUsed|setTimeout|sendAnalog|readSlider|analogRead|beginWrite|createChar|motorsStop|keyPressed|tempoWrite|readButton|subnetMask|debugPrint|macAddress|writeGreen|randomSeed|attachGPRS|readString|sendString|remotePort|releaseAll|mouseMoved|background|getXChange|getYChange|answerCall|getResult|voiceCall|endPacket|constrain|getSocket|writeJSON|getButton|available|connected|findUntil|readBytes|exitValue|readGreen|writeBlue|startLoop|isPressed|sendSysex|pauseMode|gatewayIP|setCursor|getOemKey|tuneWrite|noDisplay|loadImage|switchPIN|onRequest|onReceive|changePIN|playFile|noBuffer|parseInt|overflow|checkPIN|knobRead|beginTFT|bitClear|updateIR|bitWrite|position|writeRGB|highByte|writeRed|setSpeed|readBlue|noStroke|remoteIP|transfer|shutdown|hangCall|beginSMS|endWrite|attached|maintain|noCursor|checkReg|checkPUK|shiftOut|isValid|shiftIn|pulseIn|connect|println|localIP|pinMode|getIMEI|display|noBlink|process|getBand|running|beginSD|drawBMP|lowByte|setBand|release|bitRead|prepare|pointTo|readRed|setMode|noFill|remove|listen|stroke|detach|attach|noTone|exists|buffer|height|bitSet|circle|config|cursor|random|IRread|setDNS|endSMS|getKey|micros|millis|begin|print|write|ready|flush|width|isPIN|blink|clear|press|mkdir|rmdir|close|point|yield|image|BSSID|click|delay|read|text|move|peek|beep|rect|line|open|seek|fill|size|turn|stop|home|find|step|tone|sqrt|RSSI|SSID|end|bit|tan|cos|sin|pow|map|abs|max|min|get|run|put)\b/}); Prism.languages.arff={comment:/%.*/,string:{pattern:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/@(?:attribute|data|end|relation)\b/i,number:/\b\d+(?:\.\d+)?\b/,punctuation:/[{},]/}; !function(t){var n={pattern:/(^[ \t]*)\[(?!\[)(?:(["'$`])(?:(?!\2)[^\\]|\\.)*\2|\[(?:[^\[\]\\]|\\.)*\]|[^\[\]\\"'$`]|\\.)*\]/m,lookbehind:!0,inside:{quoted:{pattern:/([$`])(?:(?!\1)[^\\]|\\.)*\1/,inside:{punctuation:/^[$`]|[$`]$/}},interpreted:{pattern:/'(?:[^'\\]|\\.)*'/,inside:{punctuation:/^'|'$/}},string:/"(?:[^"\\]|\\.)*"/,variable:/\w+(?==)/,punctuation:/^\[|\]$|,/,operator:/=/,"attr-value":/(?!^\s+$).+/}},a=t.languages.asciidoc={"comment-block":{pattern:/^(\/{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1/m,alias:"comment"},table:{pattern:/^\|={3,}(?:(?:\r?\n|\r(?!\n)).*)*?(?:\r?\n|\r)\|={3,}$/m,inside:{specifiers:{pattern:/(?!\|)(?:(?:(?:\d+(?:\.\d+)?|\.\d+)[+*])?(?:[<^>](?:\.[<^>])?|\.[<^>])?[a-z]*)(?=\|)/,alias:"attr-value"},punctuation:{pattern:/(^|[^\\])[|!]=*/,lookbehind:!0}}},"passthrough-block":{pattern:/^(\+{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^\++|\++$/}},"literal-block":{pattern:/^(-{4,}|\.{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\.+)|(?:-+|\.+)$/}},"other-block":{pattern:/^(--|\*{4,}|_{4,}|={4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\*+|_+|=+)|(?:-+|\*+|_+|=+)$/}},"list-punctuation":{pattern:/(^[ \t]*)(?:-|\*{1,5}|\.{1,5}|(?:[a-z]|\d+)\.|[xvi]+\))(?= )/im,lookbehind:!0,alias:"punctuation"},"list-label":{pattern:/(^[ \t]*)[a-z\d].+(?::{2,4}|;;)(?=\s)/im,lookbehind:!0,alias:"symbol"},"indented-block":{pattern:/((\r?\n|\r)\2)([ \t]+)\S.*(?:(?:\r?\n|\r)\3.+)*(?=\2{2}|$)/,lookbehind:!0},comment:/^\/\/.*/m,title:{pattern:/^.+(?:\r?\n|\r)(?:={3,}|-{3,}|~{3,}|\^{3,}|\+{3,})$|^={1,5} .+|^\.(?![\s.]).*/m,alias:"important",inside:{punctuation:/^(?:\.|=+)|(?:=+|-+|~+|\^+|\++)$/}},"attribute-entry":{pattern:/^:[^:\r\n]+:(?: .*?(?: \+(?:\r?\n|\r).*?)*)?$/m,alias:"tag"},attributes:n,hr:{pattern:/^'{3,}$/m,alias:"punctuation"},"page-break":{pattern:/^<{3,}$/m,alias:"punctuation"},admonition:{pattern:/^(?:TIP|NOTE|IMPORTANT|WARNING|CAUTION):/m,alias:"keyword"},callout:[{pattern:/(^[ \t]*)/m,lookbehind:!0,alias:"symbol"},{pattern:/<\d+>/,alias:"symbol"}],macro:{pattern:/\b[a-z\d][a-z\d-]*::?(?:[^\s\[\]]*\[(?:[^\]\\"']|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:{function:/^[a-z\d-]+(?=:)/,punctuation:/^::?/,attributes:{pattern:/(?:\[(?:[^\]\\"']|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:n.inside}}},inline:{pattern:/(^|[^\\])(?:(?:\B\[(?:[^\]\\"']|(["'])(?:(?!\2)[^\\]|\\.)*\2|\\.)*\])?(?:\b_(?!\s)(?: _|[^_\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: _|[^_\\\r\n]|\\.)+)*_\b|\B``(?!\s).+?(?:(?:\r?\n|\r).+?)*''\B|\B`(?!\s)(?:[^`'\s]|\s+\S)+['`]\B|\B(['*+#])(?!\s)(?: \3|(?!\3)[^\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: \3|(?!\3)[^\\\r\n]|\\.)+)*\3\B)|(?:\[(?:[^\]\\"']|(["'])(?:(?!\4)[^\\]|\\.)*\4|\\.)*\])?(?:(__|\*\*|\+\+\+?|##|\$\$|[~^]).+?(?:(?:\r?\n|\r).+?)*\5|\{[^}\r\n]+\}|\[\[\[?.+?(?:(?:\r?\n|\r).+?)*\]?\]\]|<<.+?(?:(?:\r?\n|\r).+?)*>>|\(\(\(?.+?(?:(?:\r?\n|\r).+?)*\)?\)\)))/m,lookbehind:!0,inside:{attributes:n,url:{pattern:/^(?:\[\[\[?.+?\]?\]\]|<<.+?>>)$/,inside:{punctuation:/^(?:\[\[\[?|<<)|(?:\]\]\]?|>>)$/}},"attribute-ref":{pattern:/^\{.+\}$/,inside:{variable:{pattern:/(^\{)[a-z\d,+_-]+/,lookbehind:!0},operator:/^[=?!#%@$]|!(?=[:}])/,punctuation:/^\{|\}$|::?/}},italic:{pattern:/^(['_])[\s\S]+\1$/,inside:{punctuation:/^(?:''?|__?)|(?:''?|__?)$/}},bold:{pattern:/^\*[\s\S]+\*$/,inside:{punctuation:/^\*\*?|\*\*?$/}},punctuation:/^(?:``?|\+{1,3}|##?|\$\$|[~^]|\(\(\(?)|(?:''?|\+{1,3}|##?|\$\$|[~^`]|\)?\)\))$/}},replacement:{pattern:/\((?:C|TM|R)\)/,alias:"builtin"},entity:/&#?[\da-z]{1,8};/i,"line-continuation":{pattern:/(^| )\+$/m,lookbehind:!0,alias:"punctuation"}};function i(t){for(var n={},i=0,e=(t=t.split(" ")).length;i>/g,function(e,n){return"(?:"+s[+n]+")"})}function t(e,n,s){return RegExp(a(e,n),s||"")}function e(e,n){for(var s=0;s>/g,function(){return"(?:"+e+")"});return e.replace(/<>/g,"[^\\s\\S]")}var n="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var d=l(r),p=RegExp(l(n+" "+r+" "+i+" "+o)),c=l(r+" "+i+" "+o),u=l(n+" "+r+" "+o),g=e("<(?:[^<>;=+\\-*/%&|^]|<>)*>",2),b=e("\\((?:[^()]|<>)*\\)",2),h="@?\\b[A-Za-z_]\\w*\\b",f=a("<<0>>(?:\\s*<<1>>)?",[h,g]),m=a("(?!<<0>>)<<1>>(?:\\s*\\.\\s*<<1>>)*",[c,f]),k="\\[\\s*(?:,\\s*)*\\]",y=a("<<0>>(?:\\s*(?:\\?\\s*)?<<1>>)*(?:\\s*\\?)?",[m,k]),w=a("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[a("\\(<<0>>+(?:,<<0>>+)+\\)",[a("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k])]),m,k]),v={keyword:p,punctuation:/[<>()?,.:[\]]/},x="'(?:[^\r\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",$='"(?:\\\\.|[^\\\\"\r\n])*"';s.languages.csharp=s.languages.extend("clike",{string:[{pattern:t("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:t("(^|[^@$\\\\])<<0>>",[$]),lookbehind:!0,greedy:!0},{pattern:RegExp(x),greedy:!0,alias:"character"}],"class-name":[{pattern:t("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:v},{pattern:t("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,w]),lookbehind:!0,inside:v},{pattern:t("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:t("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:v},{pattern:t("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:v},{pattern:t("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:t("(\\b(?:is(?:\\s+not)?|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:v},{pattern:t("\\b<<0>>(?=\\s+(?!<<1>>|with\\s*\\{)<<2>>(?:\\s*[=,;:{)\\]]|\\s+(?:in|when)\\b))",[w,u,h]),inside:v}],keyword:p,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),s.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),s.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:t("([(,]\\s*)<<0>>(?=\\s*:)",[h]),lookbehind:!0,alias:"punctuation"}}),s.languages.insertBefore("csharp","class-name",{namespace:{pattern:t("(\\b(?:namespace|using)\\s+)<<0>>(?:\\s*\\.\\s*<<0>>)*(?=\\s*[;{])",[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:t("(\\b(?:default|typeof|sizeof)\\s*\\(\\s*(?!\\s))(?:[^()\\s]|\\s(?!\\s)|<<0>>)*(?=\\s*\\))",[b]),lookbehind:!0,alias:"class-name",inside:v},"return-type":{pattern:t("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[w,m]),inside:v,alias:"class-name"},"constructor-invocation":{pattern:t("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[w]),lookbehind:!0,inside:v,alias:"class-name"},"generic-method":{pattern:t("<<0>>\\s*<<1>>(?=\\s*\\()",[h,g]),inside:{function:t("^<<0>>",[h]),generic:{pattern:RegExp(g),alias:"class-name",inside:v}}},"type-list":{pattern:t("\\b((?:<<0>>\\s+<<1>>|record\\s+<<1>>\\s*<<5>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>|<<1>>\\s*<<5>>|<<6>>)(?:\\s*,\\s*(?:<<3>>|<<4>>|<<6>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,w,p.source,b,"\\bnew\\s*\\(\\s*\\)"]),lookbehind:!0,inside:{"record-arguments":{pattern:t("(^(?!new\\s*\\()<<0>>\\s*)<<1>>",[f,b]),lookbehind:!0,greedy:!0,inside:s.languages.csharp},keyword:p,"class-name":{pattern:RegExp(w),greedy:!0,inside:v},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var _=$+"|"+x,B=a("/(?![*/])|//[^\r\n]*[\r\n]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>",[_]),E=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[B]),2),R="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",P=a("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,E]);s.languages.insertBefore("csharp","class-name",{attribute:{pattern:t("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[R,P]),lookbehind:!0,greedy:!0,inside:{target:{pattern:t("^<<0>>(?=\\s*:)",[R]),alias:"keyword"},"attribute-arguments":{pattern:t("\\(<<0>>*\\)",[E]),inside:s.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var z=":[^}\r\n]+",S=e(a("[^\"'/()]|<<0>>|\\(<>*\\)",[B]),2),j=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[S,z]),A=e(a("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[_]),2),F=a("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[A,z]);function U(e,n){return{interpolation:{pattern:t("((?:^|[^{])(?:\\{\\{)*)<<0>>",[e]),lookbehind:!0,inside:{"format-string":{pattern:t("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[n,z]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:s.languages.csharp}}},string:/[\s\S]+/}}s.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:t('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[j]),lookbehind:!0,greedy:!0,inside:U(j,S)},{pattern:t('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[F]),lookbehind:!0,greedy:!0,inside:U(F,A)}]})}(Prism),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp; Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive":{pattern:/<%\s*@.*%>/i,alias:"tag",inside:{"page-directive":{pattern:/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,alias:"tag"},rest:Prism.languages.markup.tag.inside}},directive:{pattern:/<%.*%>/i,alias:"tag",inside:{directive:{pattern:/<%\s*?[$=%#:]{0,2}|%>/i,alias:"tag"},rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{directive:Prism.languages.aspnet.directive},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp-comment":{pattern:/<%--[\s\S]*?--%>/,alias:["asp","comment"]}}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp-script":{pattern:/(]*>)[\s\S]*?(?=<\/script>)/i,lookbehind:!0,alias:["asp","script"],inside:Prism.languages.csharp||{}}}); Prism.languages.asm6502={comment:/;.*/,directive:{pattern:/\.\w+(?= )/,alias:"keyword"},string:/(["'`])(?:\\.|(?!\1)[^\\\r\n])*\1/,opcode:{pattern:/\b(?:adc|and|asl|bcc|bcs|beq|bit|bmi|bne|bpl|brk|bvc|bvs|clc|cld|cli|clv|cmp|cpx|cpy|dec|dex|dey|eor|inc|inx|iny|jmp|jsr|lda|ldx|ldy|lsr|nop|ora|pha|php|pla|plp|rol|ror|rti|rts|sbc|sec|sed|sei|sta|stx|sty|tax|tay|tsx|txa|txs|tya|ADC|AND|ASL|BCC|BCS|BEQ|BIT|BMI|BNE|BPL|BRK|BVC|BVS|CLC|CLD|CLI|CLV|CMP|CPX|CPY|DEC|DEX|DEY|EOR|INC|INX|INY|JMP|JSR|LDA|LDX|LDY|LSR|NOP|ORA|PHA|PHP|PLA|PLP|ROL|ROR|RTI|RTS|SBC|SEC|SED|SEI|STA|STX|STY|TAX|TAY|TSX|TXA|TXS|TYA)\b/,alias:"property"},hexnumber:{pattern:/#?\$[\da-f]{2,4}\b/i,alias:"string"},binarynumber:{pattern:/#?%[01]+\b/,alias:"string"},decimalnumber:{pattern:/#?\b\d+\b/,alias:"string"},register:{pattern:/\b[xya]\b/i,alias:"variable"}}; Prism.languages.autohotkey={comment:[{pattern:/(^|\s);.*/,lookbehind:!0},{pattern:/(^[\t ]*)\/\*(?:[\r\n](?![ \t]*\*\/)|[^\r\n])*(?:[\r\n][ \t]*\*\/)?/m,lookbehind:!0,greedy:!0}],tag:{pattern:/^([ \t]*)[^\s,`":]+(?=:[ \t]*$)/m,lookbehind:!0},string:/"(?:[^"\n\r]|"")*"/m,variable:/%\w+%/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/\?|\/\/?=?|:=|\|[=|]?|&[=&]?|\+[=+]?|-[=-]?|\*[=*]?|<(?:<=?|>|=)?|>>?=?|[.^!=~]=?|\b(?:AND|NOT|OR)\b/,boolean:/\b(?:true|false)\b/,selector:/\b(?:AutoTrim|BlockInput|Break|Click|ClipWait|Continue|Control|ControlClick|ControlFocus|ControlGet|ControlGetFocus|ControlGetPos|ControlGetText|ControlMove|ControlSend|ControlSendRaw|ControlSetText|CoordMode|Critical|DetectHiddenText|DetectHiddenWindows|Drive|DriveGet|DriveSpaceFree|EnvAdd|EnvDiv|EnvGet|EnvMult|EnvSet|EnvSub|EnvUpdate|Exit|ExitApp|FileAppend|FileCopy|FileCopyDir|FileCreateDir|FileCreateShortcut|FileDelete|FileEncoding|FileGetAttrib|FileGetShortcut|FileGetSize|FileGetTime|FileGetVersion|FileInstall|FileMove|FileMoveDir|FileRead|FileReadLine|FileRecycle|FileRecycleEmpty|FileRemoveDir|FileSelectFile|FileSelectFolder|FileSetAttrib|FileSetTime|FormatTime|GetKeyState|Gosub|Goto|GroupActivate|GroupAdd|GroupClose|GroupDeactivate|Gui|GuiControl|GuiControlGet|Hotkey|ImageSearch|IniDelete|IniRead|IniWrite|Input|InputBox|KeyWait|ListHotkeys|ListLines|ListVars|Loop|Menu|MouseClick|MouseClickDrag|MouseGetPos|MouseMove|MsgBox|OnExit|OutputDebug|Pause|PixelGetColor|PixelSearch|PostMessage|Process|Progress|Random|RegDelete|RegRead|RegWrite|Reload|Repeat|Return|Run|RunAs|RunWait|Send|SendEvent|SendInput|SendMessage|SendMode|SendPlay|SendRaw|SetBatchLines|SetCapslockState|SetControlDelay|SetDefaultMouseSpeed|SetEnv|SetFormat|SetKeyDelay|SetMouseDelay|SetNumlockState|SetRegView|SetScrollLockState|SetStoreCapslockMode|SetTimer|SetTitleMatchMode|SetWinDelay|SetWorkingDir|Shutdown|Sleep|Sort|SoundBeep|SoundGet|SoundGetWaveVolume|SoundPlay|SoundSet|SoundSetWaveVolume|SplashImage|SplashTextOff|SplashTextOn|SplitPath|StatusBarGetText|StatusBarWait|StringCaseSense|StringGetPos|StringLeft|StringLen|StringLower|StringMid|StringReplace|StringRight|StringSplit|StringTrimLeft|StringTrimRight|StringUpper|Suspend|SysGet|Thread|ToolTip|Transform|TrayTip|URLDownloadToFile|WinActivate|WinActivateBottom|WinClose|WinGet|WinGetActiveStats|WinGetActiveTitle|WinGetClass|WinGetPos|WinGetText|WinGetTitle|WinHide|WinKill|WinMaximize|WinMenuSelectItem|WinMinimize|WinMinimizeAll|WinMinimizeAllUndo|WinMove|WinRestore|WinSet|WinSetTitle|WinShow|WinWait|WinWaitActive|WinWaitClose|WinWaitNotActive)\b/i,constant:/\b(?:a_ahkpath|a_ahkversion|a_appdata|a_appdatacommon|a_autotrim|a_batchlines|a_caretx|a_carety|a_computername|a_controldelay|a_cursor|a_dd|a_ddd|a_dddd|a_defaultmousespeed|a_desktop|a_desktopcommon|a_detecthiddentext|a_detecthiddenwindows|a_endchar|a_eventinfo|a_exitreason|a_fileencoding|a_formatfloat|a_formatinteger|a_gui|a_guievent|a_guicontrol|a_guicontrolevent|a_guiheight|a_guiwidth|a_guix|a_guiy|a_hour|a_iconfile|a_iconhidden|a_iconnumber|a_icontip|a_index|a_ipaddress1|a_ipaddress2|a_ipaddress3|a_ipaddress4|a_is64bitos|a_isadmin|a_iscompiled|a_iscritical|a_ispaused|a_issuspended|a_isunicode|a_keydelay|a_language|a_lasterror|a_linefile|a_linenumber|a_loopfield|a_loopfileattrib|a_loopfiledir|a_loopfileext|a_loopfilefullpath|a_loopfilelongpath|a_loopfilename|a_loopfileshortname|a_loopfileshortpath|a_loopfilesize|a_loopfilesizekb|a_loopfilesizemb|a_loopfiletimeaccessed|a_loopfiletimecreated|a_loopfiletimemodified|a_loopreadline|a_loopregkey|a_loopregname|a_loopregsubkey|a_loopregtimemodified|a_loopregtype|a_mday|a_min|a_mm|a_mmm|a_mmmm|a_mon|a_mousedelay|a_msec|a_mydocuments|a_now|a_nowutc|a_numbatchlines|a_ostype|a_osversion|a_priorhotkey|a_priorkey|programfiles|a_programfiles|a_programs|a_programscommon|a_ptrsize|a_regview|a_screendpi|a_screenheight|a_screenwidth|a_scriptdir|a_scriptfullpath|a_scripthwnd|a_scriptname|a_sec|a_space|a_startmenu|a_startmenucommon|a_startup|a_startupcommon|a_stringcasesense|a_tab|a_temp|a_thisfunc|a_thishotkey|a_thislabel|a_thismenu|a_thismenuitem|a_thismenuitempos|a_tickcount|a_timeidle|a_timeidlephysical|a_timesincepriorhotkey|a_timesincethishotkey|a_titlematchmode|a_titlematchmodespeed|a_username|a_wday|a_windelay|a_windir|a_workingdir|a_yday|a_year|a_yweek|a_yyyy|clipboard|clipboardall|comspec|errorlevel)\b/i,builtin:/\b(?:abs|acos|asc|asin|atan|ceil|chr|class|comobjactive|comobjarray|comobjconnect|comobjcreate|comobjerror|comobjflags|comobjget|comobjquery|comobjtype|comobjvalue|cos|dllcall|exp|fileexist|Fileopen|floor|format|il_add|il_create|il_destroy|instr|substr|isfunc|islabel|IsObject|ln|log|lv_add|lv_delete|lv_deletecol|lv_getcount|lv_getnext|lv_gettext|lv_insert|lv_insertcol|lv_modify|lv_modifycol|lv_setimagelist|ltrim|rtrim|mod|onmessage|numget|numput|registercallback|regexmatch|regexreplace|round|sin|tan|sqrt|strlen|strreplace|sb_seticon|sb_setparts|sb_settext|strsplit|tv_add|tv_delete|tv_getchild|tv_getcount|tv_getnext|tv_get|tv_getparent|tv_getprev|tv_getselection|tv_gettext|tv_modify|varsetcapacity|winactive|winexist|__New|__Call|__Get|__Set)\b/i,symbol:/\b(?:alt|altdown|altup|appskey|backspace|browser_back|browser_favorites|browser_forward|browser_home|browser_refresh|browser_search|browser_stop|bs|capslock|ctrl|ctrlbreak|ctrldown|ctrlup|del|delete|down|end|enter|esc|escape|f1|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f2|f20|f21|f22|f23|f24|f3|f4|f5|f6|f7|f8|f9|home|ins|insert|joy1|joy10|joy11|joy12|joy13|joy14|joy15|joy16|joy17|joy18|joy19|joy2|joy20|joy21|joy22|joy23|joy24|joy25|joy26|joy27|joy28|joy29|joy3|joy30|joy31|joy32|joy4|joy5|joy6|joy7|joy8|joy9|joyaxes|joybuttons|joyinfo|joyname|joypov|joyr|joyu|joyv|joyx|joyy|joyz|lalt|launch_app1|launch_app2|launch_mail|launch_media|lbutton|lcontrol|lctrl|left|lshift|lwin|lwindown|lwinup|mbutton|media_next|media_play_pause|media_prev|media_stop|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadadd|numpadclear|numpaddel|numpaddiv|numpaddot|numpaddown|numpadend|numpadenter|numpadhome|numpadins|numpadleft|numpadmult|numpadpgdn|numpadpgup|numpadright|numpadsub|numpadup|pgdn|pgup|printscreen|ralt|rbutton|rcontrol|rctrl|right|rshift|rwin|rwindown|rwinup|scrolllock|shift|shiftdown|shiftup|space|tab|up|volume_down|volume_mute|volume_up|wheeldown|wheelleft|wheelright|wheelup|xbutton1|xbutton2)\b/i,important:/#\b(?:AllowSameLineComments|ClipboardTimeout|CommentFlag|DerefChar|ErrorStdOut|EscapeChar|HotkeyInterval|HotkeyModifierTimeout|Hotstring|If|IfTimeout|IfWinActive|IfWinExist|IfWinNotActive|IfWinNotExist|Include|IncludeAgain|InputLevel|InstallKeybdHook|InstallMouseHook|KeyHistory|MaxHotkeysPerInterval|MaxMem|MaxThreads|MaxThreadsBuffer|MaxThreadsPerHotkey|MenuMaskKey|NoEnv|NoTrayIcon|Persistent|SingleInstance|UseHook|Warn|WinActivateForce)\b/i,keyword:/\b(?:Abort|AboveNormal|Add|ahk_class|ahk_exe|ahk_group|ahk_id|ahk_pid|All|Alnum|Alpha|AltSubmit|AltTab|AltTabAndMenu|AltTabMenu|AltTabMenuDismiss|AlwaysOnTop|AutoSize|Background|BackgroundTrans|BelowNormal|between|BitAnd|BitNot|BitOr|BitShiftLeft|BitShiftRight|BitXOr|Bold|Border|Button|ByRef|Checkbox|Checked|CheckedGray|Choose|ChooseString|Close|Color|ComboBox|Contains|ControlList|Count|Date|DateTime|Days|DDL|Default|DeleteAll|Delimiter|Deref|Destroy|Digit|Disable|Disabled|DropDownList|Edit|Eject|Else|Enable|Enabled|Error|Exist|Expand|ExStyle|FileSystem|First|Flash|Float|FloatFast|Focus|Font|for|global|Grid|Group|GroupBox|GuiClose|GuiContextMenu|GuiDropFiles|GuiEscape|GuiSize|Hdr|Hidden|Hide|High|HKCC|HKCR|HKCU|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_LOCAL_MACHINE|HKEY_USERS|HKLM|HKU|Hours|HScroll|Icon|IconSmall|ID|IDLast|If|IfEqual|IfExist|IfGreater|IfGreaterOrEqual|IfInString|IfLess|IfLessOrEqual|IfMsgBox|IfNotEqual|IfNotExist|IfNotInString|IfWinActive|IfWinExist|IfWinNotActive|IfWinNotExist|Ignore|ImageList|in|Integer|IntegerFast|Interrupt|is|italic|Join|Label|LastFound|LastFoundExist|Limit|Lines|List|ListBox|ListView|local|Lock|Logoff|Low|Lower|Lowercase|MainWindow|Margin|Maximize|MaximizeBox|MaxSize|Minimize|MinimizeBox|MinMax|MinSize|Minutes|MonthCal|Mouse|Move|Multi|NA|No|NoActivate|NoDefault|NoHide|NoIcon|NoMainWindow|norm|Normal|NoSort|NoSortHdr|NoStandard|Not|NoTab|NoTimers|Number|Off|Ok|On|OwnDialogs|Owner|Parse|Password|Picture|Pixel|Pos|Pow|Priority|ProcessName|Radio|Range|Read|ReadOnly|Realtime|Redraw|REG_BINARY|REG_DWORD|REG_EXPAND_SZ|REG_MULTI_SZ|REG_SZ|Region|Relative|Rename|Report|Resize|Restore|Retry|RGB|Screen|Seconds|Section|Serial|SetLabel|ShiftAltTab|Show|Single|Slider|SortDesc|Standard|static|Status|StatusBar|StatusCD|strike|Style|Submit|SysMenu|Tab2|TabStop|Text|Theme|Tile|ToggleCheck|ToggleEnable|ToolWindow|Top|Topmost|TransColor|Transparent|Tray|TreeView|TryAgain|Throw|Try|Catch|Finally|Type|UnCheck|underline|Unicode|Unlock|Until|UpDown|Upper|Uppercase|UseErrorLevel|Vis|VisFirst|Visible|VScroll|Wait|WaitClose|WantCtrlA|WantF2|WantReturn|While|Wrap|Xdigit|xm|xp|xs|Yes|ym|yp|ys)\b/i,function:/[^(); \t,\n+*\-=?>:\\\/<&%\[\]]+(?=\()/m,punctuation:/[{}[\]():,]/}; Prism.languages.autoit={comment:[/;.*/,{pattern:/(^[\t ]*)#(?:comments-start|cs)[\s\S]*?^[ \t]*#(?:comments-end|ce)/m,lookbehind:!0}],url:{pattern:/(^[\t ]*#include\s+)(?:<[^\r\n>]+>|"[^\r\n"]+")/m,lookbehind:!0},string:{pattern:/(["'])(?:\1\1|(?!\1)[^\r\n])*\1/,greedy:!0,inside:{variable:/([%$@])\w+\1/}},directive:{pattern:/(^[\t ]*)#\w+/m,lookbehind:!0,alias:"keyword"},function:/\b\w+(?=\()/,variable:/[$@]\w+/,keyword:/\b(?:Case|Const|Continue(?:Case|Loop)|Default|Dim|Do|Else(?:If)?|End(?:Func|If|Select|Switch|With)|Enum|Exit(?:Loop)?|For|Func|Global|If|In|Local|Next|Null|ReDim|Select|Static|Step|Switch|Then|To|Until|Volatile|WEnd|While|With)\b/i,number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,boolean:/\b(?:True|False)\b/i,operator:/<[=>]?|[-+*\/=&>]=?|[?^]|\b(?:And|Or|Not)\b/i,punctuation:/[\[\]().,:]/}; !function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],i=a.variable[1].inside,o=0;o?^\w +\-.])*"/i,greedy:!0},number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,keyword:/\b(?:AS|BEEP|BLOAD|BSAVE|CALL(?: ABSOLUTE)?|CASE|CHAIN|CHDIR|CLEAR|CLOSE|CLS|COM|COMMON|CONST|DATA|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DIM|DO|DOUBLE|ELSE|ELSEIF|END|ENVIRON|ERASE|ERROR|EXIT|FIELD|FILES|FOR|FUNCTION|GET|GOSUB|GOTO|IF|INPUT|INTEGER|IOCTL|KEY|KILL|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|MKDIR|NAME|NEXT|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPTION BASE|OUT|POKE|PUT|READ|REDIM|REM|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SHARED|SINGLE|SELECT CASE|SHELL|SLEEP|STATIC|STEP|STOP|STRING|SUB|SWAP|SYSTEM|THEN|TIMER|TO|TROFF|TRON|TYPE|UNLOCK|UNTIL|USING|VIEW PRINT|WAIT|WEND|WHILE|WRITE)(?:\$|\b)/i,function:/\b(?:ABS|ACCESS|ACOS|ANGLE|AREA|ARITHMETIC|ARRAY|ASIN|ASK|AT|ATN|BASE|BEGIN|BREAK|CAUSE|CEIL|CHR|CLIP|COLLATE|COLOR|CON|COS|COSH|COT|CSC|DATE|DATUM|DEBUG|DECIMAL|DEF|DEG|DEGREES|DELETE|DET|DEVICE|DISPLAY|DOT|ELAPSED|EPS|ERASABLE|EXLINE|EXP|EXTERNAL|EXTYPE|FILETYPE|FIXED|FP|GO|GRAPH|HANDLER|IDN|IMAGE|IN|INT|INTERNAL|IP|IS|KEYED|LBOUND|LCASE|LEFT|LEN|LENGTH|LET|LINE|LINES|LOG|LOG10|LOG2|LTRIM|MARGIN|MAT|MAX|MAXNUM|MID|MIN|MISSING|MOD|NATIVE|NUL|NUMERIC|OF|OPTION|ORD|ORGANIZATION|OUTIN|OUTPUT|PI|POINT|POINTER|POINTS|POS|PRINT|PROGRAM|PROMPT|RAD|RADIANS|RANDOMIZE|RECORD|RECSIZE|RECTYPE|RELATIVE|REMAINDER|REPEAT|REST|RETRY|REWRITE|RIGHT|RND|ROUND|RTRIM|SAME|SEC|SELECT|SEQUENTIAL|SET|SETTER|SGN|SIN|SINH|SIZE|SKIP|SQR|STANDARD|STATUS|STR|STREAM|STYLE|TAB|TAN|TANH|TEMPLATE|TEXT|THERE|TIME|TIMEOUT|TRACE|TRANSFORM|TRUNCATE|UBOUND|UCASE|USE|VAL|VARIABLE|VIEWPORT|WHEN|WINDOW|WITH|ZER|ZONEWIDTH)(?:\$|\b)/i,operator:/<[=>]?|>=?|[+\-*\/^=&]|\b(?:AND|EQV|IMP|NOT|OR|XOR)\b/i,punctuation:/[,;:()]/}; !function(e){var r=/%%?[~:\w]+%?|!\S+!/,t={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},n=/"(?:[\\"]"|[^"])*"(?!")/,i=/(?:\b|-)\d+\b/;Prism.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/^for\b|\b(?:in|do)\b/i,string:n,parameter:t,variable:r,number:i,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|(?!")(?:(?!==)\S)+)?(?:==| (?:equ|neq|lss|leq|gtr|geq) )(?:"[^"]*"|[^\s"]\S*))/im,lookbehind:!0,inside:{keyword:/^if\b|\b(?:not|cmdextversion|defined|errorlevel|exist)\b/i,string:n,parameter:t,variable:r,number:i,operator:/\^|==|\b(?:equ|neq|lss|leq|gtr|geq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: \/[a-z](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:n,parameter:t,variable:[r,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:i,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:"(?:[\\"]"|[^"])*"(?!")|[^"^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^\w+\b/i,string:n,parameter:t,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:i,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(); Prism.languages.bbcode={tag:{pattern:/\[\/?[^\s=\]]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+))?(?:\s+[^\s=\]]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+))*\s*\]/,inside:{tag:{pattern:/^\[\/?[^\s=\]]+/,inside:{punctuation:/^\[\/?/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\]/,"attr-name":/[^\s=\]]+/}}},Prism.languages.shortcode=Prism.languages.bbcode; Prism.languages.birb=Prism.languages.extend("clike",{string:{pattern:/r?("|')(?:\\.|(?!\1)[^\\])*\1/,greedy:!0},"class-name":[/\b[A-Z](?:[\d_]*[a-zA-Z]\w*)?\b/,/\b[A-Z]\w*(?=\s+\w+\s*[;,=()])/],keyword:/\b(?:assert|break|case|class|const|default|else|enum|final|follows|for|grab|if|nest|next|new|noSeeb|return|static|switch|throw|var|void|while)\b/,operator:/\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?|:/,variable:/\b[a-z_]\w*\b/}),Prism.languages.insertBefore("birb","function",{metadata:{pattern:/<\w+>/,greedy:!0,alias:"symbol"}}); Prism.languages.bison=Prism.languages.extend("c",{}),Prism.languages.insertBefore("bison","comment",{bison:{pattern:/^(?:[^%]|%(?!%))*%%[\s\S]*?%%/,inside:{c:{pattern:/%\{[\s\S]*?%\}|\{(?:\{[^}]*\}|[^{}])*\}/,inside:{delimiter:{pattern:/^%?\{|%?\}$/,alias:"punctuation"},"bison-variable":{pattern:/[$@](?:<[^\s>]+>)?[\w$]+/,alias:"variable",inside:{punctuation:/<|>/}},rest:Prism.languages.c}},comment:Prism.languages.c.comment,string:Prism.languages.c.string,property:/\S+(?=:)/,keyword:/%\w+/,number:{pattern:/(^|[^@])\b(?:0x[\da-f]+|\d+)/i,lookbehind:!0},punctuation:/%[%?]|[|:;\[\]<>]/}}}); Prism.languages.bnf={string:{pattern:/"[^\r\n"]*"|'[^\r\n']*'/},definition:{pattern:/<[^<>\r\n\t]+>(?=\s*::=)/,alias:["rule","keyword"],inside:{punctuation:/^<|>$/}},rule:{pattern:/<[^<>\r\n\t]+>/,inside:{punctuation:/^<|>$/}},operator:/::=|[|()[\]{}*+?]|\.{3}/},Prism.languages.rbnf=Prism.languages.bnf; Prism.languages.brainfuck={pointer:{pattern:/<|>/,alias:"keyword"},increment:{pattern:/\+/,alias:"inserted"},decrement:{pattern:/-/,alias:"deleted"},branching:{pattern:/\[|\]/,alias:"important"},operator:/[.,]/,comment:/\S+/}; Prism.languages.brightscript={comment:/(?:\brem|').*/i,"directive-statement":{pattern:/(^[\t ]*)#(?:const|else(?:[\t ]+if)?|end[\t ]+if|error|if).*/im,lookbehind:!0,alias:"property",inside:{"error-message":{pattern:/(^#error).+/,lookbehind:!0},directive:{pattern:/^#(?:const|else(?:[\t ]+if)?|end[\t ]+if|error|if)/,alias:"keyword"},expression:{pattern:/[\s\S]+/,inside:null}}},property:{pattern:/([\r\n{,][\t ]*)(?:(?!\d)\w+|"(?:[^"\r\n]|"")*"(?!"))(?=[ \t]*:)/,lookbehind:!0,greedy:!0},string:{pattern:/"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},"class-name":{pattern:/(\bAs[\t ]+)\w+/i,lookbehind:!0},keyword:/\b(?:As|Dim|Each|Else|Elseif|End|Exit|For|Function|Goto|If|In|Print|Return|Step|Stop|Sub|Then|To|While)\b/i,boolean:/\b(?:true|false)\b/i,function:/\b(?!\d)\w+(?=[\t ]*\()/i,number:/(?:\b\d+(?:\.\d+)?(?:[ed][+-]\d+)?|&h[a-f\d]+)\b[%&!#]?/i,operator:/--|\+\+|>>=?|<<=?|<>|[-+*/\\<>]=?|[:^=?]|\b(?:and|mod|not|or)\b/i,punctuation:/[.,;()[\]{}]/,constant:/\b(?:LINE_NUM)\b/i},Prism.languages.brightscript["directive-statement"].inside.expression.inside=Prism.languages.brightscript; Prism.languages.bro={comment:{pattern:/(^|[^\\$])#.*/,lookbehind:!0,inside:{italic:/\b(?:TODO|FIXME|XXX)\b/}},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},boolean:/\b[TF]\b/,function:{pattern:/(?:function|hook|event) \w+(?:::\w+)?/,inside:{keyword:/^(?:function|hook|event)/}},variable:{pattern:/(?:global|local) \w+/i,inside:{keyword:/(?:global|local)/}},builtin:/(?:@(?:load(?:-(?:sigs|plugin))?|unload|prefixes|ifn?def|else|(?:end)?if|DIR|FILENAME))|(?:&?(?:redef|priority|log|optional|default|add_func|delete_func|expire_func|read_expire|write_expire|create_expire|synchronized|persistent|rotate_interval|rotate_size|encrypt|raw_output|mergeable|group|error_handler|type_column))/,constant:{pattern:/const \w+/i,inside:{keyword:/const/}},keyword:/\b(?:break|next|continue|alarm|using|of|add|delete|export|print|return|schedule|when|timeout|addr|any|bool|count|double|enum|file|int|interval|pattern|opaque|port|record|set|string|subnet|table|time|vector|for|if|else|in|module|function)\b/,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&|\|\|?|\?|\*|\/|~|\^|%/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,punctuation:/[{}[\];(),.:]/}; Prism.languages.bsl={comment:/\/\/.*/,string:[{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},{pattern:/'(?:[^'\r\n\\]|\\.)*'/}],keyword:[{pattern:/(^|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:пока|для|новый|прервать|попытка|исключение|вызватьисключение|иначе|конецпопытки|неопределено|функция|перем|возврат|конецфункции|если|иначеесли|процедура|конецпроцедуры|тогда|знач|экспорт|конецесли|из|каждого|истина|ложь|по|цикл|конеццикла|выполнить)(?![\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])/i,lookbehind:!0},{pattern:/\b(?:while|for|new|break|try|except|raise|else|endtry|undefined|function|var|return|endfunction|null|if|elseif|procedure|endprocedure|then|val|export|endif|in|each|true|false|to|do|enddo|execute)\b/i}],number:{pattern:/(^(?=\d)|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:\d+(?:\.\d*)?|\.\d+)(?:E[+-]?\d+)?/i,lookbehind:!0},operator:[/[<>+\-*/]=?|[%=]/,{pattern:/(^|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:и|или|не)(?![\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])/i,lookbehind:!0},{pattern:/\b(?:and|or|not)\b/i}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/,directive:[{pattern:/^(\s*)&.*/m,lookbehind:!0,alias:"important"},{pattern:/^\s*#.*/gm,alias:"important"}]},Prism.languages.oscript=Prism.languages.bsl; Prism.languages.cfscript=Prism.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,inside:{annotation:{pattern:/(?:^|[^.])@[\w\.]+/,alias:"punctuation"}}},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],keyword:/\b(?:abstract|break|catch|component|continue|default|do|else|extends|final|finally|for|function|if|in|include|package|private|property|public|remote|required|rethrow|return|static|switch|throw|try|var|while|xml)\b(?!\s*=)/,operator:[/\+\+|--|&&|\|\||::|=>|[!=]==|<=?|>=?|[-+*/%&|^!=<>]=?|\?(?:\.|:)?|[?:]/,/\b(?:and|contains|eq|equal|eqv|gt|gte|imp|is|lt|lte|mod|not|or|xor)\b/],scope:{pattern:/\b(?:application|arguments|cgi|client|cookie|local|session|super|this|variables)\b/,alias:"global"},type:{pattern:/\b(?:any|array|binary|boolean|date|guid|numeric|query|string|struct|uuid|void|xml)\b/,alias:"builtin"}}),Prism.languages.insertBefore("cfscript","keyword",{"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"}}),delete Prism.languages.cfscript["class-name"],Prism.languages.cfc=Prism.languages.cfscript; Prism.languages.chaiscript=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])'(?:[^'\\]|\\[\s\S])*'/,lookbehind:!0,greedy:!0},"class-name":[{pattern:/(\bclass\s+)\w+/,lookbehind:!0},{pattern:/(\b(?:attr|def)\s+)\w+(?=\s*::)/,lookbehind:!0}],keyword:/\b(?:attr|auto|break|case|catch|class|continue|def|default|else|finally|for|fun|global|if|return|switch|this|try|var|while)\b/,number:[Prism.languages.cpp.number,/\b(?:Infinity|NaN)\b/],operator:/>>=?|<<=?|\|\||&&|:[:=]?|--|\+\+|[=!<>+\-*/%|&^]=?|[?~]|`[^`\r\n]{1,4}`/}),Prism.languages.insertBefore("chaiscript","operator",{"parameter-type":{pattern:/([,(]\s*)\w+(?=\s+\w)/,lookbehind:!0,alias:"class-name"}}),Prism.languages.insertBefore("chaiscript","string",{"string-interpolation":{pattern:/(^|[^\\])"(?:[^"$\\]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*"/,lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}/,lookbehind:!0,inside:{"interpolation-expression":{pattern:/(^\$\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:Prism.languages.chaiscript},"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"}}},string:/[\s\S]+/}}}); Prism.languages.cil={comment:/\/\/.*/,string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},directive:{pattern:/(^|\W)\.[a-z]+(?=\s)/,lookbehind:!0,alias:"class-name"},variable:/\[[\w\.]+\]/,keyword:/\b(?:abstract|ansi|assembly|auto|autochar|beforefieldinit|bool|bstr|byvalstr|catch|char|cil|class|currency|date|decimal|default|enum|error|explicit|extends|extern|famandassem|family|famorassem|final(?:ly)?|float32|float64|hidebysig|iant|idispatch|implements|import|initonly|instance|u?int(?:8|16|32|64)?|interface|iunknown|literal|lpstr|lpstruct|lptstr|lpwstr|managed|method|native(?:Type)?|nested|newslot|object(?:ref)?|pinvokeimpl|private|privatescope|public|reqsecobj|rtspecialname|runtime|sealed|sequential|serializable|specialname|static|string|struct|syschar|tbstr|unicode|unmanagedexp|unsigned|value(?:type)?|variant|virtual|void)\b/,function:/\b(?:(?:constrained|unaligned|volatile|readonly|tail|no)\.)?(?:conv\.(?:[iu][1248]?|ovf\.[iu][1248]?(?:\.un)?|r\.un|r4|r8)|ldc\.(?:i4(?:\.[0-9]+|\.[mM]1|\.s)?|i8|r4|r8)|ldelem(?:\.[iu][1248]?|\.r[48]|\.ref|a)?|ldind\.(?:[iu][1248]?|r[48]|ref)|stelem\.?(?:i[1248]?|r[48]|ref)?|stind\.(?:i[1248]?|r[48]|ref)?|end(?:fault|filter|finally)|ldarg(?:\.[0-3s]|a(?:\.s)?)?|ldloc(?:\.[0-9]+|\.s)?|sub(?:\.ovf(?:\.un)?)?|mul(?:\.ovf(?:\.un)?)?|add(?:\.ovf(?:\.un)?)?|stloc(?:\.[0-3s])?|refany(?:type|val)|blt(?:\.un)?(?:\.s)?|ble(?:\.un)?(?:\.s)?|bgt(?:\.un)?(?:\.s)?|bge(?:\.un)?(?:\.s)?|unbox(?:\.any)?|init(?:blk|obj)|call(?:i|virt)?|brfalse(?:\.s)?|bne\.un(?:\.s)?|ldloca(?:\.s)?|brzero(?:\.s)?|brtrue(?:\.s)?|brnull(?:\.s)?|brinst(?:\.s)?|starg(?:\.s)?|leave(?:\.s)?|shr(?:\.un)?|rem(?:\.un)?|div(?:\.un)?|clt(?:\.un)?|alignment|ldvirtftn|castclass|beq(?:\.s)?|mkrefany|localloc|ckfinite|rethrow|ldtoken|ldsflda|cgt\.un|arglist|switch|stsfld|sizeof|newobj|newarr|ldsfld|ldnull|ldflda|isinst|throw|stobj|stfld|ldstr|ldobj|ldlen|ldftn|ldfld|cpobj|cpblk|break|br\.s|xor|shl|ret|pop|not|nop|neg|jmp|dup|cgt|ceq|box|and|or|br)\b/,boolean:/\b(?:true|false)\b/,number:/\b-?(?:0x[0-9a-f]+|[0-9]+)(?:\.[0-9a-f]+)?\b/i,punctuation:/[{}[\];(),:=]|IL_[0-9A-Za-z]+/}; Prism.languages.clojure={comment:/;.*/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},operator:/(?:::|[:|'])\b[a-z][\w*+!?-]*\b/i,keyword:{pattern:/([^\w+*'?-])(?:def|if|do|let|\.\.|quote|var|->>|->|fn|loop|recur|throw|try|monitor-enter|\.|new|set!|def-|defn|defn-|defmacro|defmulti|defmethod|defstruct|defonce|declare|definline|definterface|defprotocol|==|defrecord|>=|deftype|<=|defproject|ns|\*|\+|-|\/|<|=|>|accessor|agent|agent-errors|aget|alength|all-ns|alter|and|append-child|apply|array-map|aset|aset-boolean|aset-byte|aset-char|aset-double|aset-float|aset-int|aset-long|aset-short|assert|assoc|await|await-for|bean|binding|bit-and|bit-not|bit-or|bit-shift-left|bit-shift-right|bit-xor|boolean|branch\?|butlast|byte|cast|char|children|class|clear-agent-errors|comment|commute|comp|comparator|complement|concat|conj|cons|constantly|cond|if-not|construct-proxy|contains\?|count|create-ns|create-struct|cycle|dec|deref|difference|disj|dissoc|distinct|doall|doc|dorun|doseq|dosync|dotimes|doto|double|down|drop|drop-while|edit|end\?|ensure|eval|every\?|false\?|ffirst|file-seq|filter|find|find-doc|find-ns|find-var|first|float|flush|for|fnseq|frest|gensym|get-proxy-class|get|hash-map|hash-set|identical\?|identity|if-let|import|in-ns|inc|index|insert-child|insert-left|insert-right|inspect-table|inspect-tree|instance\?|int|interleave|intersection|into|into-array|iterate|join|key|keys|keyword|keyword\?|last|lazy-cat|lazy-cons|left|lefts|line-seq|list\*|list|load|load-file|locking|long|macroexpand|macroexpand-1|make-array|make-node|map|map-invert|map\?|mapcat|max|max-key|memfn|merge|merge-with|meta|min|min-key|name|namespace|neg\?|newline|next|nil\?|node|not|not-any\?|not-every\?|not=|ns-imports|ns-interns|ns-map|ns-name|ns-publics|ns-refers|ns-resolve|ns-unmap|nth|nthrest|or|parse|partial|path|peek|pop|pos\?|pr|pr-str|print|print-str|println|println-str|prn|prn-str|project|proxy|proxy-mappings|quot|rand|rand-int|range|re-find|re-groups|re-matcher|re-matches|re-pattern|re-seq|read|read-line|reduce|ref|ref-set|refer|rem|remove|remove-method|remove-ns|rename|rename-keys|repeat|replace|replicate|resolve|rest|resultset-seq|reverse|rfirst|right|rights|root|rrest|rseq|second|select|select-keys|send|send-off|seq|seq-zip|seq\?|set|short|slurp|some|sort|sort-by|sorted-map|sorted-map-by|sorted-set|special-symbol\?|split-at|split-with|str|string\?|struct|struct-map|subs|subvec|symbol|symbol\?|sync|take|take-nth|take-while|test|time|to-array|to-array-2d|tree-seq|true\?|union|up|update-proxy|val|vals|var-get|var-set|var\?|vector|vector-zip|vector\?|when|when-first|when-let|when-not|with-local-vars|with-meta|with-open|with-out-str|xml-seq|xml-zip|zero\?|zipmap|zipper)(?=[^\w+*'?-])/,lookbehind:!0},boolean:/\b(?:true|false|nil)\b/,number:/\b[\da-f]+\b/i,punctuation:/[{}\[\](),]/}; Prism.languages.cmake={comment:/#.*/,string:{pattern:/"(?:[^\\"]|\\.)*"/,greedy:!0,inside:{interpolation:{pattern:/\$\{(?:[^{}$]|\$\{[^{}$]*\})*\}/,inside:{punctuation:/\$\{|\}/,variable:/\w+/}}}},variable:/\b(?:CMAKE_\w+|\w+_(?:VERSION(?:_MAJOR|_MINOR|_PATCH|_TWEAK)?|(?:BINARY|SOURCE)_DIR|DESCRIPTION|HOMEPAGE_URL|ROOT)|(?:ANDROID|APPLE|BORLAND|BUILD_SHARED_LIBS|CACHE|CPACK_(?:ABSOLUTE_DESTINATION_FILES|COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY|ERROR_ON_ABSOLUTE_INSTALL_DESTINATION|INCLUDE_TOPLEVEL_DIRECTORY|INSTALL_DEFAULT_DIRECTORY_PERMISSIONS|INSTALL_SCRIPT|PACKAGING_INSTALL_PREFIX|SET_DESTDIR|WARN_ON_ABSOLUTE_INSTALL_DESTINATION)|CTEST_(?:BINARY_DIRECTORY|BUILD_COMMAND|BUILD_NAME|BZR_COMMAND|BZR_UPDATE_OPTIONS|CHANGE_ID|CHECKOUT_COMMAND|CONFIGURATION_TYPE|CONFIGURE_COMMAND|COVERAGE_COMMAND|COVERAGE_EXTRA_FLAGS|CURL_OPTIONS|CUSTOM_(?:COVERAGE_EXCLUDE|ERROR_EXCEPTION|ERROR_MATCH|ERROR_POST_CONTEXT|ERROR_PRE_CONTEXT|MAXIMUM_FAILED_TEST_OUTPUT_SIZE|MAXIMUM_NUMBER_OF_(?:ERRORS|WARNINGS)|MAXIMUM_PASSED_TEST_OUTPUT_SIZE|MEMCHECK_IGNORE|POST_MEMCHECK|POST_TEST|PRE_MEMCHECK|PRE_TEST|TESTS_IGNORE|WARNING_EXCEPTION|WARNING_MATCH)|CVS_CHECKOUT|CVS_COMMAND|CVS_UPDATE_OPTIONS|DROP_LOCATION|DROP_METHOD|DROP_SITE|DROP_SITE_CDASH|DROP_SITE_PASSWORD|DROP_SITE_USER|EXTRA_COVERAGE_GLOB|GIT_COMMAND|GIT_INIT_SUBMODULES|GIT_UPDATE_CUSTOM|GIT_UPDATE_OPTIONS|HG_COMMAND|HG_UPDATE_OPTIONS|LABELS_FOR_SUBPROJECTS|MEMORYCHECK_(?:COMMAND|COMMAND_OPTIONS|SANITIZER_OPTIONS|SUPPRESSIONS_FILE|TYPE)|NIGHTLY_START_TIME|P4_CLIENT|P4_COMMAND|P4_OPTIONS|P4_UPDATE_OPTIONS|RUN_CURRENT_SCRIPT|SCP_COMMAND|SITE|SOURCE_DIRECTORY|SUBMIT_URL|SVN_COMMAND|SVN_OPTIONS|SVN_UPDATE_OPTIONS|TEST_LOAD|TEST_TIMEOUT|TRIGGER_SITE|UPDATE_COMMAND|UPDATE_OPTIONS|UPDATE_VERSION_ONLY|USE_LAUNCHERS)|CYGWIN|ENV|EXECUTABLE_OUTPUT_PATH|GHS-MULTI|IOS|LIBRARY_OUTPUT_PATH|MINGW|MSVC(?:10|11|12|14|60|70|71|80|90|_IDE|_TOOLSET_VERSION|_VERSION)?|MSYS|PROJECT_(?:BINARY_DIR|DESCRIPTION|HOMEPAGE_URL|NAME|SOURCE_DIR|VERSION|VERSION_(?:MAJOR|MINOR|PATCH|TWEAK))|UNIX|WIN32|WINCE|WINDOWS_PHONE|WINDOWS_STORE|XCODE|XCODE_VERSION))\b/,property:/\b(?:cxx_\w+|(?:ARCHIVE_OUTPUT_(?:DIRECTORY|NAME)|COMPILE_DEFINITIONS|COMPILE_PDB_NAME|COMPILE_PDB_OUTPUT_DIRECTORY|EXCLUDE_FROM_DEFAULT_BUILD|IMPORTED_(?:IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_LANGUAGES|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|NO_SONAME|OBJECTS|SONAME)|INTERPROCEDURAL_OPTIMIZATION|LIBRARY_OUTPUT_DIRECTORY|LIBRARY_OUTPUT_NAME|LINK_FLAGS|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|MAP_IMPORTED_CONFIG|OSX_ARCHITECTURES|OUTPUT_NAME|PDB_NAME|PDB_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_NAME|STATIC_LIBRARY_FLAGS|VS_CSHARP|VS_DOTNET_REFERENCEPROP|VS_DOTNET_REFERENCE|VS_GLOBAL_SECTION_POST|VS_GLOBAL_SECTION_PRE|VS_GLOBAL|XCODE_ATTRIBUTE)_\w+|\w+_(?:CLANG_TIDY|COMPILER_LAUNCHER|CPPCHECK|CPPLINT|INCLUDE_WHAT_YOU_USE|OUTPUT_NAME|POSTFIX|VISIBILITY_PRESET)|ABSTRACT|ADDITIONAL_MAKE_CLEAN_FILES|ADVANCED|ALIASED_TARGET|ALLOW_DUPLICATE_CUSTOM_TARGETS|ANDROID_(?:ANT_ADDITIONAL_OPTIONS|API|API_MIN|ARCH|ASSETS_DIRECTORIES|GUI|JAR_DEPENDENCIES|NATIVE_LIB_DEPENDENCIES|NATIVE_LIB_DIRECTORIES|PROCESS_MAX|PROGUARD|PROGUARD_CONFIG_PATH|SECURE_PROPS_PATH|SKIP_ANT_STEP|STL_TYPE)|ARCHIVE_OUTPUT_DIRECTORY|ATTACHED_FILES|ATTACHED_FILES_ON_FAIL|AUTOGEN_(?:BUILD_DIR|ORIGIN_DEPENDS|PARALLEL|SOURCE_GROUP|TARGETS_FOLDER|TARGET_DEPENDS)|AUTOMOC|AUTOMOC_(?:COMPILER_PREDEFINES|DEPEND_FILTERS|EXECUTABLE|MACRO_NAMES|MOC_OPTIONS|SOURCE_GROUP|TARGETS_FOLDER)|AUTORCC|AUTORCC_EXECUTABLE|AUTORCC_OPTIONS|AUTORCC_SOURCE_GROUP|AUTOUIC|AUTOUIC_EXECUTABLE|AUTOUIC_OPTIONS|AUTOUIC_SEARCH_PATHS|BINARY_DIR|BUILDSYSTEM_TARGETS|BUILD_RPATH|BUILD_RPATH_USE_ORIGIN|BUILD_WITH_INSTALL_NAME_DIR|BUILD_WITH_INSTALL_RPATH|BUNDLE|BUNDLE_EXTENSION|CACHE_VARIABLES|CLEAN_NO_CUSTOM|COMMON_LANGUAGE_RUNTIME|COMPATIBLE_INTERFACE_(?:BOOL|NUMBER_MAX|NUMBER_MIN|STRING)|COMPILE_(?:DEFINITIONS|FEATURES|FLAGS|OPTIONS|PDB_NAME|PDB_OUTPUT_DIRECTORY)|COST|CPACK_DESKTOP_SHORTCUTS|CPACK_NEVER_OVERWRITE|CPACK_PERMANENT|CPACK_STARTUP_SHORTCUTS|CPACK_START_MENU_SHORTCUTS|CPACK_WIX_ACL|CROSSCOMPILING_EMULATOR|CUDA_EXTENSIONS|CUDA_PTX_COMPILATION|CUDA_RESOLVE_DEVICE_SYMBOLS|CUDA_SEPARABLE_COMPILATION|CUDA_STANDARD|CUDA_STANDARD_REQUIRED|CXX_EXTENSIONS|CXX_STANDARD|CXX_STANDARD_REQUIRED|C_EXTENSIONS|C_STANDARD|C_STANDARD_REQUIRED|DEBUG_CONFIGURATIONS|DEFINE_SYMBOL|DEFINITIONS|DEPENDS|DEPLOYMENT_ADDITIONAL_FILES|DEPLOYMENT_REMOTE_DIRECTORY|DISABLED|DISABLED_FEATURES|ECLIPSE_EXTRA_CPROJECT_CONTENTS|ECLIPSE_EXTRA_NATURES|ENABLED_FEATURES|ENABLED_LANGUAGES|ENABLE_EXPORTS|ENVIRONMENT|EXCLUDE_FROM_ALL|EXCLUDE_FROM_DEFAULT_BUILD|EXPORT_NAME|EXPORT_PROPERTIES|EXTERNAL_OBJECT|EchoString|FAIL_REGULAR_EXPRESSION|FIND_LIBRARY_USE_LIB32_PATHS|FIND_LIBRARY_USE_LIB64_PATHS|FIND_LIBRARY_USE_LIBX32_PATHS|FIND_LIBRARY_USE_OPENBSD_VERSIONING|FIXTURES_CLEANUP|FIXTURES_REQUIRED|FIXTURES_SETUP|FOLDER|FRAMEWORK|Fortran_FORMAT|Fortran_MODULE_DIRECTORY|GENERATED|GENERATOR_FILE_NAME|GENERATOR_IS_MULTI_CONFIG|GHS_INTEGRITY_APP|GHS_NO_SOURCE_GROUP_FILE|GLOBAL_DEPENDS_DEBUG_MODE|GLOBAL_DEPENDS_NO_CYCLES|GNUtoMS|HAS_CXX|HEADER_FILE_ONLY|HELPSTRING|IMPLICIT_DEPENDS_INCLUDE_TRANSFORM|IMPORTED|IMPORTED_(?:COMMON_LANGUAGE_RUNTIME|CONFIGURATIONS|GLOBAL|IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_(?:LANGUAGES|LIBRARIES|MULTIPLICITY)|LOCATION|NO_SONAME|OBJECTS|SONAME)|IMPORT_PREFIX|IMPORT_SUFFIX|INCLUDE_DIRECTORIES|INCLUDE_REGULAR_EXPRESSION|INSTALL_NAME_DIR|INSTALL_RPATH|INSTALL_RPATH_USE_LINK_PATH|INTERFACE_(?:AUTOUIC_OPTIONS|COMPILE_DEFINITIONS|COMPILE_FEATURES|COMPILE_OPTIONS|INCLUDE_DIRECTORIES|LINK_DEPENDS|LINK_DIRECTORIES|LINK_LIBRARIES|LINK_OPTIONS|POSITION_INDEPENDENT_CODE|SOURCES|SYSTEM_INCLUDE_DIRECTORIES)|INTERPROCEDURAL_OPTIMIZATION|IN_TRY_COMPILE|IOS_INSTALL_COMBINED|JOB_POOLS|JOB_POOL_COMPILE|JOB_POOL_LINK|KEEP_EXTENSION|LABELS|LANGUAGE|LIBRARY_OUTPUT_DIRECTORY|LINKER_LANGUAGE|LINK_(?:DEPENDS|DEPENDS_NO_SHARED|DIRECTORIES|FLAGS|INTERFACE_LIBRARIES|INTERFACE_MULTIPLICITY|LIBRARIES|OPTIONS|SEARCH_END_STATIC|SEARCH_START_STATIC|WHAT_YOU_USE)|LISTFILE_STACK|LOCATION|MACOSX_BUNDLE|MACOSX_BUNDLE_INFO_PLIST|MACOSX_FRAMEWORK_INFO_PLIST|MACOSX_PACKAGE_LOCATION|MACOSX_RPATH|MACROS|MANUALLY_ADDED_DEPENDENCIES|MEASUREMENT|MODIFIED|NAME|NO_SONAME|NO_SYSTEM_FROM_IMPORTED|OBJECT_DEPENDS|OBJECT_OUTPUTS|OSX_ARCHITECTURES|OUTPUT_NAME|PACKAGES_FOUND|PACKAGES_NOT_FOUND|PARENT_DIRECTORY|PASS_REGULAR_EXPRESSION|PDB_NAME|PDB_OUTPUT_DIRECTORY|POSITION_INDEPENDENT_CODE|POST_INSTALL_SCRIPT|PREDEFINED_TARGETS_FOLDER|PREFIX|PRE_INSTALL_SCRIPT|PRIVATE_HEADER|PROCESSORS|PROCESSOR_AFFINITY|PROJECT_LABEL|PUBLIC_HEADER|REPORT_UNDEFINED_PROPERTIES|REQUIRED_FILES|RESOURCE|RESOURCE_LOCK|RULE_LAUNCH_COMPILE|RULE_LAUNCH_CUSTOM|RULE_LAUNCH_LINK|RULE_MESSAGES|RUNTIME_OUTPUT_DIRECTORY|RUN_SERIAL|SKIP_AUTOGEN|SKIP_AUTOMOC|SKIP_AUTORCC|SKIP_AUTOUIC|SKIP_BUILD_RPATH|SKIP_RETURN_CODE|SOURCES|SOURCE_DIR|SOVERSION|STATIC_LIBRARY_FLAGS|STATIC_LIBRARY_OPTIONS|STRINGS|SUBDIRECTORIES|SUFFIX|SYMBOLIC|TARGET_ARCHIVES_MAY_BE_SHARED_LIBS|TARGET_MESSAGES|TARGET_SUPPORTS_SHARED_LIBS|TESTS|TEST_INCLUDE_FILE|TEST_INCLUDE_FILES|TIMEOUT|TIMEOUT_AFTER_MATCH|TYPE|USE_FOLDERS|VALUE|VARIABLES|VERSION|VISIBILITY_INLINES_HIDDEN|VS_(?:CONFIGURATION_TYPE|COPY_TO_OUT_DIR|DEBUGGER_(?:COMMAND|COMMAND_ARGUMENTS|ENVIRONMENT|WORKING_DIRECTORY)|DEPLOYMENT_CONTENT|DEPLOYMENT_LOCATION|DOTNET_REFERENCES|DOTNET_REFERENCES_COPY_LOCAL|GLOBAL_KEYWORD|GLOBAL_PROJECT_TYPES|GLOBAL_ROOTNAMESPACE|INCLUDE_IN_VSIX|IOT_STARTUP_TASK|KEYWORD|RESOURCE_GENERATOR|SCC_AUXPATH|SCC_LOCALPATH|SCC_PROJECTNAME|SCC_PROVIDER|SDK_REFERENCES|SHADER_(?:DISABLE_OPTIMIZATIONS|ENABLE_DEBUG|ENTRYPOINT|FLAGS|MODEL|OBJECT_FILE_NAME|OUTPUT_HEADER_FILE|TYPE|VARIABLE_NAME)|STARTUP_PROJECT|TOOL_OVERRIDE|USER_PROPS|WINRT_COMPONENT|WINRT_EXTENSIONS|WINRT_REFERENCES|XAML_TYPE)|WILL_FAIL|WIN32_EXECUTABLE|WINDOWS_EXPORT_ALL_SYMBOLS|WORKING_DIRECTORY|WRAP_EXCLUDE|XCODE_(?:EMIT_EFFECTIVE_PLATFORM_NAME|EXPLICIT_FILE_TYPE|FILE_ATTRIBUTES|LAST_KNOWN_FILE_TYPE|PRODUCT_TYPE|SCHEME_(?:ADDRESS_SANITIZER|ADDRESS_SANITIZER_USE_AFTER_RETURN|ARGUMENTS|DISABLE_MAIN_THREAD_CHECKER|DYNAMIC_LIBRARY_LOADS|DYNAMIC_LINKER_API_USAGE|ENVIRONMENT|EXECUTABLE|GUARD_MALLOC|MAIN_THREAD_CHECKER_STOP|MALLOC_GUARD_EDGES|MALLOC_SCRIBBLE|MALLOC_STACK|THREAD_SANITIZER(?:_STOP)?|UNDEFINED_BEHAVIOUR_SANITIZER(?:_STOP)?|ZOMBIE_OBJECTS))|XCTEST)\b/,keyword:/\b(?:add_compile_definitions|add_compile_options|add_custom_command|add_custom_target|add_definitions|add_dependencies|add_executable|add_library|add_link_options|add_subdirectory|add_test|aux_source_directory|break|build_command|build_name|cmake_host_system_information|cmake_minimum_required|cmake_parse_arguments|cmake_policy|configure_file|continue|create_test_sourcelist|ctest_build|ctest_configure|ctest_coverage|ctest_empty_binary_directory|ctest_memcheck|ctest_read_custom_files|ctest_run_script|ctest_sleep|ctest_start|ctest_submit|ctest_test|ctest_update|ctest_upload|define_property|else|elseif|enable_language|enable_testing|endforeach|endfunction|endif|endmacro|endwhile|exec_program|execute_process|export|export_library_dependencies|file|find_file|find_library|find_package|find_path|find_program|fltk_wrap_ui|foreach|function|get_cmake_property|get_directory_property|get_filename_component|get_property|get_source_file_property|get_target_property|get_test_property|if|include|include_directories|include_external_msproject|include_guard|include_regular_expression|install|install_files|install_programs|install_targets|link_directories|link_libraries|list|load_cache|load_command|macro|make_directory|mark_as_advanced|math|message|option|output_required_files|project|qt_wrap_cpp|qt_wrap_ui|remove|remove_definitions|return|separate_arguments|set|set_directory_properties|set_property|set_source_files_properties|set_target_properties|set_tests_properties|site_name|source_group|string|subdir_depends|subdirs|target_compile_definitions|target_compile_features|target_compile_options|target_include_directories|target_link_directories|target_link_libraries|target_link_options|target_sources|try_compile|try_run|unset|use_mangled_mesa|utility_source|variable_requires|variable_watch|while|write_file)(?=\s*\()\b/,boolean:/\b(?:ON|OFF|TRUE|FALSE)\b/,namespace:/\b(?:PROPERTIES|SHARED|PRIVATE|STATIC|PUBLIC|INTERFACE|TARGET_OBJECTS)\b/,operator:/\b(?:NOT|AND|OR|MATCHES|LESS|GREATER|EQUAL|STRLESS|STRGREATER|STREQUAL|VERSION_LESS|VERSION_EQUAL|VERSION_GREATER|DEFINED)\b/,inserted:{pattern:/\b\w+::\w+\b/,alias:"class-name"},number:/\b\d+(?:\.\d+)*\b/,function:/\b[a-z_]\w*(?=\s*\()\b/i,punctuation:/[()>}]|\$[<{]/}; Prism.languages.cobol={comment:{pattern:/\*>.*|(^[ \t]*)\*.*/m,lookbehind:!0,greedy:!0},string:{pattern:/[xzgn]?(?:"(?:[^\r\n"]|"")*"(?!")|'(?:[^\r\n']|'')*'(?!'))/i,greedy:!0},level:{pattern:/(^[ \t]*)\d+\b/m,lookbehind:!0,greedy:!0,alias:"number"},"class-name":{pattern:/(\bpic(?:ture)?\s+)(?:(?:[-\w$/,:*+<>]|\.(?!\s|$))(?:\(\d+\))?)+/i,lookbehind:!0,inside:{number:{pattern:/(\()\d+/,lookbehind:!0},punctuation:/[()]/}},keyword:{pattern:/(^|[^\w-])(?:ABORT|ACCEPT|ACCESS|ADD|ADDRESS|ADVANCING|AFTER|ALIGNED|ALL|ALPHABET|ALPHABETIC|ALPHABETIC-LOWER|ALPHABETIC-UPPER|ALPHANUMERIC|ALPHANUMERIC-EDITED|ALSO|ALTER|ALTERNATE|ANY|ARE|AREA|AREAS|AS|ASCENDING|ASCII|ASSIGN|ASSOCIATED-DATA|ASSOCIATED-DATA-LENGTH|AT|ATTRIBUTE|AUTHOR|AUTO|AUTO-SKIP|BACKGROUND-COLOR|BACKGROUND-COLOUR|BASIS|BEEP|BEFORE|BEGINNING|BELL|BINARY|BIT|BLANK|BLINK|BLOCK|BOUNDS|BOTTOM|BY|BYFUNCTION|BYTITLE|CALL|CANCEL|CAPABLE|CCSVERSION|CD|CF|CH|CHAINING|CHANGED|CHANNEL|CHARACTER|CHARACTERS|CLASS|CLASS-ID|CLOCK-UNITS|CLOSE|CLOSE-DISPOSITION|COBOL|CODE|CODE-SET|COLLATING|COL|COLUMN|COM-REG|COMMA|COMMITMENT|COMMON|COMMUNICATION|COMP|COMP-1|COMP-2|COMP-3|COMP-4|COMP-5|COMPUTATIONAL|COMPUTATIONAL-1|COMPUTATIONAL-2|COMPUTATIONAL-3|COMPUTATIONAL-4|COMPUTATIONAL-5|COMPUTE|CONFIGURATION|CONTAINS|CONTENT|CONTINUE|CONTROL|CONTROL-POINT|CONTROLS|CONVENTION|CONVERTING|COPY|CORR|CORRESPONDING|COUNT|CRUNCH|CURRENCY|CURSOR|DATA|DATA-BASE|DATE|DATE-COMPILED|DATE-WRITTEN|DAY|DAY-OF-WEEK|DBCS|DE|DEBUG-CONTENTS|DEBUG-ITEM|DEBUG-LINE|DEBUG-NAME|DEBUG-SUB-1|DEBUG-SUB-2|DEBUG-SUB-3|DEBUGGING|DECIMAL-POINT|DECLARATIVES|DEFAULT|DEFAULT-DISPLAY|DEFINITION|DELETE|DELIMITED|DELIMITER|DEPENDING|DESCENDING|DESTINATION|DETAIL|DFHRESP|DFHVALUE|DISABLE|DISK|DISPLAY|DISPLAY-1|DIVIDE|DIVISION|DONTCARE|DOUBLE|DOWN|DUPLICATES|DYNAMIC|EBCDIC|EGCS|EGI|ELSE|EMI|EMPTY-CHECK|ENABLE|END|END-ACCEPT|END-ADD|END-CALL|END-COMPUTE|END-DELETE|END-DIVIDE|END-EVALUATE|END-IF|END-MULTIPLY|END-OF-PAGE|END-PERFORM|END-READ|END-RECEIVE|END-RETURN|END-REWRITE|END-SEARCH|END-START|END-STRING|END-SUBTRACT|END-UNSTRING|END-WRITE|ENDING|ENTER|ENTRY|ENTRY-PROCEDURE|ENVIRONMENT|EOP|ERASE|ERROR|EOL|EOS|ESCAPE|ESI|EVALUATE|EVENT|EVERY|EXCEPTION|EXCLUSIVE|EXHIBIT|EXIT|EXPORT|EXTEND|EXTENDED|EXTERNAL|FD|FILE|FILE-CONTROL|FILLER|FINAL|FIRST|FOOTING|FOR|FOREGROUND-COLOR|FOREGROUND-COLOUR|FROM|FULL|FUNCTION|FUNCTIONNAME|FUNCTION-POINTER|GENERATE|GOBACK|GIVING|GLOBAL|GO|GRID|GROUP|HEADING|HIGHLIGHT|HIGH-VALUE|HIGH-VALUES|I-O|I-O-CONTROL|ID|IDENTIFICATION|IF|IMPLICIT|IMPORT|IN|INDEX|INDEXED|INDICATE|INITIAL|INITIALIZE|INITIATE|INPUT|INPUT-OUTPUT|INSPECT|INSTALLATION|INTEGER|INTO|INVALID|INVOKE|IS|JUST|JUSTIFIED|KANJI|KEPT|KEY|KEYBOARD|LABEL|LANGUAGE|LAST|LB|LD|LEADING|LEFT|LEFTLINE|LENGTH|LENGTH-CHECK|LIBACCESS|LIBPARAMETER|LIBRARY|LIMIT|LIMITS|LINAGE|LINAGE-COUNTER|LINE|LINES|LINE-COUNTER|LINKAGE|LIST|LOCAL|LOCAL-STORAGE|LOCK|LONG-DATE|LONG-TIME|LOWER|LOWLIGHT|LOW-VALUE|LOW-VALUES|MEMORY|MERGE|MESSAGE|MMDDYYYY|MODE|MODULES|MORE-LABELS|MOVE|MULTIPLE|MULTIPLY|NAMED|NATIONAL|NATIONAL-EDITED|NATIVE|NEGATIVE|NETWORK|NEXT|NO|NO-ECHO|NULL|NULLS|NUMBER|NUMERIC|NUMERIC-DATE|NUMERIC-EDITED|NUMERIC-TIME|OBJECT-COMPUTER|OCCURS|ODT|OF|OFF|OMITTED|ON|OPEN|OPTIONAL|ORDER|ORDERLY|ORGANIZATION|OTHER|OUTPUT|OVERFLOW|OVERLINE|OWN|PACKED-DECIMAL|PADDING|PAGE|PAGE-COUNTER|PASSWORD|PERFORM|PF|PH|PIC|PICTURE|PLUS|POINTER|POSITION|POSITIVE|PORT|PRINTER|PRINTING|PRIVATE|PROCEDURE|PROCEDURE-POINTER|PROCEDURES|PROCEED|PROCESS|PROGRAM|PROGRAM-ID|PROGRAM-LIBRARY|PROMPT|PURGE|QUEUE|QUOTE|QUOTES|RANDOM|READER|REMOTE|RD|REAL|READ|RECEIVE|RECEIVED|RECORD|RECORDING|RECORDS|RECURSIVE|REDEFINES|REEL|REF|REFERENCE|REFERENCES|RELATIVE|RELEASE|REMAINDER|REMARKS|REMOVAL|REMOVE|RENAMES|REPLACE|REPLACING|REPORT|REPORTING|REPORTS|REQUIRED|RERUN|RESERVE|REVERSE-VIDEO|RESET|RETURN|RETURN-CODE|RETURNING|REVERSED|REWIND|REWRITE|RF|RH|RIGHT|ROUNDED|RUN|SAME|SAVE|SCREEN|SD|SEARCH|SECTION|SECURE|SECURITY|SEGMENT|SEGMENT-LIMIT|SELECT|SEND|SENTENCE|SEPARATE|SEQUENCE|SEQUENTIAL|SET|SHARED|SHAREDBYALL|SHAREDBYRUNUNIT|SHARING|SHIFT-IN|SHIFT-OUT|SHORT-DATE|SIGN|SIZE|SORT|SORT-CONTROL|SORT-CORE-SIZE|SORT-FILE-SIZE|SORT-MERGE|SORT-MESSAGE|SORT-MODE-SIZE|SORT-RETURN|SOURCE|SOURCE-COMPUTER|SPACE|SPACES|SPECIAL-NAMES|STANDARD|STANDARD-1|STANDARD-2|START|STATUS|STOP|STRING|SUB-QUEUE-1|SUB-QUEUE-2|SUB-QUEUE-3|SUBTRACT|SUM|SUPPRESS|SYMBOL|SYMBOLIC|SYNC|SYNCHRONIZED|TABLE|TALLY|TALLYING|TASK|TAPE|TERMINAL|TERMINATE|TEST|TEXT|THEN|THREAD|THREAD-LOCAL|THROUGH|THRU|TIME|TIMER|TIMES|TITLE|TO|TODAYS-DATE|TODAYS-NAME|TOP|TRAILING|TRUNCATED|TYPE|TYPEDEF|UNDERLINE|UNIT|UNSTRING|UNTIL|UP|UPON|USAGE|USE|USING|VALUE|VALUES|VARYING|VIRTUAL|WAIT|WHEN|WHEN-COMPILED|WITH|WORDS|WORKING-STORAGE|WRITE|YEAR|YYYYMMDD|YYYYDDD|ZERO-FILL|ZEROS|ZEROES)(?![\w-])/i,lookbehind:!0},boolean:{pattern:/(^|[^\w-])(?:false|true)(?![\w-])/i,lookbehind:!0},number:{pattern:/(^|[^\w-])(?:[+-]?(?:(?:\d+(?:[.,]\d+)?|[.,]\d+)(?:e[+-]?\d+)?|zero))(?![\w-])/i,lookbehind:!0},operator:[/<>|[<>]=?|[=+*/&]/,{pattern:/(^|[^\w-])(?:-|and|equal|greater|less|not|or|than)(?![\w-])/i,lookbehind:!0}],punctuation:/[.:,()]/}; !function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(Prism); Prism.languages.concurnas={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],langext:{pattern:/\b\w+\s*\|\|[\s\S]+?\|\|/,greedy:!0,alias:"string"},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/,lookbehind:!0},keyword:/\b(?:abstract|actor|also|annotation|assert|async|await|bool|boolean|break|byte|case|catch|changed|char|class|closed|constant|continue|def|default|del|double|elif|else|enum|every|extends|false|finally|float|for|from|global|gpudef|gpukernel|if|import|in|init|inject|int|lambda|local|long|loop|match|new|nodefault|null|of|onchange|open|out|override|package|parfor|parforsync|post|pre|private|protected|provide|provider|public|return|shared|short|single|size_t|sizeof|super|sync|this|throw|trait|trans|transient|true|try|typedef|unchecked|using|val|var|void|while|with)\b/,boolean:/\b(?:false|true)\b/,number:/\b0b[01][01_]*L?\b|\b0x(?:[\da-f_]*\.)?[\da-f_p+-]+\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfls]?/i,punctuation:/[{}[\];(),.:]/,operator:/<==|>==|=>|->|<-|<>|\^|&==|&<>|!|\?:?|\.\?|\+\+|--|[-+*/=<>]=?|\b(?:and|as|band|bor|bxor|comp|is|isnot|mod|or)\b=?/,annotation:{pattern:/@(?:\w+:)?(?:\w+|\[[^\]]+\])?/,alias:"builtin"}},Prism.languages.insertBefore("concurnas","langext",{string:{pattern:/[rs]?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:Prism.languages.concurnas},string:/[\s\S]+/}}}),Prism.languages.conc=Prism.languages.concurnas; Prism.languages.csp={directive:{pattern:/(^|[^-\da-z])(?:base-uri|block-all-mixed-content|(?:child|connect|default|font|frame|img|manifest|media|object|prefetch|script|style|worker)-src|disown-opener|form-action|frame-(?:ancestors|options)|input-protection(?:-(?:clip|selectors))?|navigate-to|plugin-types|policy-uri|referrer|reflected-xss|report-(?:to|uri)|require-sri-for|sandbox|(?:script|style)-src-(?:attr|elem)|upgrade-insecure-requests)(?=[^-\da-z]|$)/i,lookbehind:!0,alias:"keyword"},safe:{pattern:/'(?:deny|none|report-sample|self|strict-dynamic|top-only|(?:nonce|sha(?:256|384|512))-[-+/\w=]+)'/i,alias:"selector"},unsafe:{pattern:/(?:'unsafe-(?:allow-redirects|dynamic|eval|hash-attributes|hashed-attributes|hashes|inline)'|\*)/i,alias:"function"}}; !function(e){for(var t="\\(\\*(?:[^(*]|\\((?!\\*)|\\*(?!\\))|)*\\*\\)",i=0;i<2;i++)t=t.replace(//g,function(){return t});t=t.replace(//g,"[]"),e.languages.coq={comment:RegExp(t),string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},attribute:[{pattern:RegExp('#\\[(?:[^\\]("]|"(?:[^"]|"")*"(?!")|\\((?!\\*)|)*\\]'.replace(//g,function(){return t})),greedy:!0,alias:"attr-name",inside:{comment:RegExp(t),string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},operator:/=/,punctuation:/^#\[|\]$|[,()]/}},{pattern:/\b(?:Cumulative|Global|Local|Monomorphic|NonCumulative|Polymorphic|Private|Program)\b/,alias:"attr-name"}],keyword:/\b(?:_|Abort|About|Add|Admit|Admitted|All|apply|Arguments|as|As|Assumptions|at|Axiom|Axioms|Back|BackTo|Backtrace|Bind|BinOp|BinOpSpec|BinRel|Blacklist|by|Canonical|Case|Cd|Check|Class|Classes|Close|Coercion|Coercions|cofix|CoFixpoint|CoInductive|Collection|Combined|Compute|Conjecture|Conjectures|Constant|Constants|Constraint|Constructors|Context|Corollary|Create|CstOp|Custom|Cut|Debug|Declare|Defined|Definition|Delimit|Dependencies|Dependent|Derive|Diffs|Drop|Elimination|else|end|End|Entry|Equality|Eval|Example|Existential|Existentials|Existing|exists|exists2|Export|Extern|Extraction|Fact|Fail|Field|File|Firstorder|fix|Fixpoint|Flags|Focus|for|forall|From|fun|Funclass|Function|Functional|GC|Generalizable|Goal|Grab|Grammar|Graph|Guarded|Haskell|Heap|Hide|Hint|HintDb|Hints|Hypotheses|Hypothesis|Identity|if|IF|Immediate|Implicit|Implicits|Import|in|Include|Induction|Inductive|Infix|Info|Initial|InjTyp|Inline|Inspect|Instance|Instances|Intro|Intros|Inversion|Inversion_clear|JSON|Language|Left|Lemma|let|Let|Lia|Libraries|Library|Load|LoadPath|Locate|Ltac|Ltac2|match|Match|measure|Method|Minimality|ML|Module|Modules|Morphism|move|Next|NoInline|Notation|Number|Obligation|Obligations|OCaml|Opaque|Open|Optimize|Parameter|Parameters|Parametric|Path|Paths|Prenex|Preterm|Primitive|Print|Profile|Projections|Proof|Prop|PropBinOp|Property|PropOp|Proposition|PropUOp|Pwd|Qed|Quit|Rec|Record|Recursive|Redirect|Reduction|Register|Relation|Remark|Remove|removed|Require|Reserved|Reset|Resolve|Restart|return|Rewrite|Right|Ring|Rings|Saturate|Save|Scheme|Scope|Scopes|Search|SearchHead|SearchPattern|SearchRewrite|Section|Separate|Set|Setoid|Show|Signatures|Solve|Solver|Sort|Sortclass|Sorted|Spec|SProp|Step|Strategies|Strategy|String|struct|Structure|SubClass|Subgraph|SuchThat|Tactic|Term|TestCompile|then|Theorem|Time|Timeout|To|Transparent|Type|Typeclasses|Types|Typing|Undelimit|Undo|Unfocus|Unfocused|Unfold|Universe|Universes|UnOp|UnOpSpec|Unshelve|using|Variable|Variables|Variant|Verbose|View|Visibility|wf|where|with|Zify)\b/,number:/\b(?:0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]+)?(?:p[+-]?\d[\d_]*)?|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?\d[\d_]*)?)\b/i,punct:{pattern:/@\{|\{\||\[=|:>/,alias:"punctuation"},operator:/\/\\|\\\/|\.{2,3}|:{1,2}=|\*\*|[-=]>|<(?:->?|[+:=>]|<:)|>(?:=|->)|\|[-|]?|[-!%&*+/<=>?@^~']/,punctuation:/\.\(|`\(|@\{|`\{|\{\||\[=|:>|[:.,;(){}\[\]]/}}(Prism); !function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#.*/,{pattern:/^=begin\s[\s\S]*?^=end/m,greedy:!0}],"class-name":{pattern:/(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.languages.ruby}};delete e.languages.ruby.function,e.languages.insertBefore("ruby","keyword",{regex:[{pattern:RegExp("%r(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","\\((?:[^()\\\\]|\\\\[^])*\\)","\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[^])*\\}","\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\]","<(?:[^<>\\\\]|\\\\[^])*>"].join("|")+")[egimnosux]{0,6}"),greedy:!0,inside:{interpolation:n}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:n}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/,lookbehind:!0},"method-definition":{pattern:/(\bdef\s+)[\w.]+/,lookbehind:!0,inside:{function:/\w+$/,rest:e.languages.ruby}}}),e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z]\w*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:RegExp("%[qQiIwWxs]?(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","\\((?:[^()\\\\]|\\\\[^])*\\)","\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[^])*\\}","\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\]","<(?:[^<>\\\\]|\\\\[^])*>"].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:n}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|[a-z_]\w*$/i,alias:"symbol",inside:{punctuation:/^<<[-~]?/}},interpolation:n}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|[a-z_]\w*$/i,alias:"symbol",inside:{punctuation:/^<<[-~]?'|'$/}}}}],e.languages.rb=e.languages.ruby}(Prism); !function(e){e.languages.crystal=e.languages.extend("ruby",{keyword:[/\b(?:abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|rescue|return|require|select|self|sizeof|struct|super|then|type|typeof|uninitialized|union|unless|until|when|while|with|yield|__DIR__|__END_LINE__|__FILE__|__LINE__)\b/,{pattern:/(\.\s*)(?:is_a|responds_to)\?/,lookbehind:!0}],number:/\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[\da-fA-F_]*[\da-fA-F]|(?:\d(?:[\d_]*\d)?)(?:\.[\d_]*\d)?(?:[eE][+-]?[\d_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/}),e.languages.insertBefore("crystal","string",{attribute:{pattern:/@\[.+?\]/,alias:"attr-name",inside:{delimiter:{pattern:/^@\[|\]$/,alias:"tag"},rest:e.languages.crystal}},expansion:[{pattern:/\{\{.+?\}\}/,inside:{delimiter:{pattern:/^\{\{|\}\}$/,alias:"tag"},rest:e.languages.crystal}},{pattern:/\{%.+?%\}/,inside:{delimiter:{pattern:/^\{%|%\}$/,alias:"tag"},rest:e.languages.crystal}}]})}(Prism); !function(e){var a,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:a={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=a,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},i={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:i,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:i})}(Prism); Prism.languages.csv={value:/[^\r\n,"]+|"(?:[^"]|"")*"(?!")/,punctuation:/,/}; Prism.languages.cypher={comment:/\/\/.*/,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/,greedy:!0},"class-name":{pattern:/(:\s*)(?:\w+|`(?:[^`\\\r\n])*`)(?=\s*[{):])/,lookbehind:!0,greedy:!0},relationship:{pattern:/(-\[\s*(?:\w+\s*|`(?:[^`\\\r\n])*`\s*)?:\s*|\|\s*:\s*)(?:\w+|`(?:[^`\\\r\n])*`)/,lookbehind:!0,greedy:!0,alias:"property"},identifier:{pattern:/`(?:[^`\\\r\n])*`/,greedy:!0,alias:"symbol"},variable:/\$\w+/,keyword:/\b(?:ADD|ALL|AND|AS|ASC|ASCENDING|ASSERT|BY|CALL|CASE|COMMIT|CONSTRAINT|CONTAINS|CREATE|CSV|DELETE|DESC|DESCENDING|DETACH|DISTINCT|DO|DROP|ELSE|END|ENDS|EXISTS|FOR|FOREACH|IN|INDEX|IS|JOIN|KEY|LIMIT|LOAD|MANDATORY|MATCH|MERGE|NODE|NOT|OF|ON|OPTIONAL|OR|ORDER(?=\s+BY)|PERIODIC|REMOVE|REQUIRE|RETURN|SCALAR|SCAN|SET|SKIP|START|STARTS|THEN|UNION|UNIQUE|UNWIND|USING|WHEN|WHERE|WITH|XOR|YIELD)\b/i,function:/\b\w+\b(?=\s*\()/,boolean:/\b(?:true|false|null)\b/i,number:/\b(?:0x[\da-fA-F]+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b/,operator:/:|<--?|--?>?|<>|=~?|[<>]=?|[+*/%^|]|\.\.\.?/,punctuation:/[()[\]{},;.]/}; Prism.languages.d=Prism.languages.extend("clike",{comment:[{pattern:/^\s*#!.+/,greedy:!0},{pattern:RegExp("(^|[^\\\\])(?:"+["/\\+(?:/\\+(?:[^+]|\\+(?!/))*\\+/|(?!/\\+)[^])*?\\+/","//.*","/\\*[^]*?\\*/"].join("|")+")"),lookbehind:!0,greedy:!0}],string:[{pattern:RegExp(['\\b[rx]"(?:\\\\[^]|[^\\\\"])*"[cwd]?','\\bq"(?:\\[[^]*?\\]|\\([^]*?\\)|<[^]*?>|\\{[^]*?\\})"','\\bq"((?!\\d)\\w+)$[^]*?^\\1"','\\bq"(.)[^]*?\\2"',"'(?:\\\\(?:\\W|\\w+)|[^\\\\])'",'(["`])(?:\\\\[^]|(?!\\3)[^\\\\])*\\3[cwd]?'].join("|"),"m"),greedy:!0},{pattern:/\bq\{(?:\{[^{}]*\}|[^{}])*\}/,greedy:!0,alias:"token-string"}],keyword:/\$|\b(?:abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|else|enum|export|extern|false|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|immutable|import|inout|int|interface|invariant|ireal|lazy|long|macro|mixin|module|new|nothrow|null|out|override|package|pragma|private|protected|public|pure|real|ref|return|scope|shared|short|static|struct|super|switch|synchronized|template|this|throw|true|try|typedef|typeid|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with|__(?:(?:FILE|MODULE|LINE|FUNCTION|PRETTY_FUNCTION|DATE|EOF|TIME|TIMESTAMP|VENDOR|VERSION)__|gshared|traits|vector|parameters)|string|wstring|dstring|size_t|ptrdiff_t)\b/,number:[/\b0x\.?[a-f\d_]+(?:(?!\.\.)\.[a-f\d_]*)?(?:p[+-]?[a-f\d_]+)?[ulfi]{0,4}/i,{pattern:/((?:\.\.)?)(?:\b0b\.?|\b|\.)\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:e[+-]?\d[\d_]*)?[ulfi]{0,4}/i,lookbehind:!0}],operator:/\|[|=]?|&[&=]?|\+[+=]?|-[-=]?|\.?\.\.|=[>=]?|!(?:i[ns]\b|<>?=?|>=?|=)?|\bi[ns]\b|(?:<[<>]?|>>?>?|\^\^|[*\/%^~])=?/}),Prism.languages.insertBefore("d","keyword",{property:/\B@\w*/}),Prism.languages.insertBefore("d","function",{register:{pattern:/\b(?:[ABCD][LHX]|E[ABCD]X|E?(?:BP|SP|DI|SI)|[ECSDGF]S|CR[0234]|DR[012367]|TR[3-7]|X?MM[0-7]|R[ABCD]X|[BS]PL|R[BS]P|[DS]IL|R[DS]I|R(?:[89]|1[0-5])[BWD]?|XMM(?:[89]|1[0-5])|YMM(?:1[0-5]|\d))\b|\bST(?:\([0-7]\)|\b)/,alias:"variable"}}); !function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],t="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{string:[{pattern:/r?("""|''')[\s\S]*?\1/,greedy:!0},{pattern:/r?(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0}],"class-name":[s,{pattern:RegExp(t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","function",{metadata:{pattern:/@\w+/,alias:"symbol"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); Prism.languages.dataweave={url:/\b[A-Za-z]+:\/\/[\w/:.?=&-]+|\burn:[\w:.?=&-]+/,property:{pattern:/(?:\b\w+#)?(?:"(?:\\.|[^\\"\r\n])*"|\b\w+)(?=\s*[:@])/,greedy:!0},string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},"mime-type":/\b(?:text|audio|video|application|multipart|image)\/[\w+-]+/,date:{pattern:/\|[\w:+-]+\|/,greedy:!0},comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],regex:{pattern:/\/(?:[^\\\/\r\n]|\\[^\r\n])+\//,greedy:!0},function:/\b[A-Z_]\w*(?=\s*\()/i,number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\];(),.:@]/,operator:/<<|>>|->|[<>~=]=?|!=|--?-?|\+\+?|!|\?/,boolean:/\b(?:true|false)\b/,keyword:/\b(?:match|input|output|ns|type|update|null|if|else|using|unless|at|is|as|case|do|fun|var|not|and|or)\b/}; Prism.languages.dax={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/).*)/,lookbehind:!0},"data-field":{pattern:/'(?:[^']|'')*'(?!')(?:\[[ \w\xA0-\uFFFF]+\])?|\w+\[[ \w\xA0-\uFFFF]+\]/,alias:"symbol"},measure:{pattern:/\[[ \w\xA0-\uFFFF]+\]/,alias:"constant"},string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},function:/\b(?:ABS|ACOS|ACOSH|ACOT|ACOTH|ADDCOLUMNS|ADDMISSINGITEMS|ALL|ALLCROSSFILTERED|ALLEXCEPT|ALLNOBLANKROW|ALLSELECTED|AND|APPROXIMATEDISTINCTCOUNT|ASIN|ASINH|ATAN|ATANH|AVERAGE|AVERAGEA|AVERAGEX|BETA\.DIST|BETA\.INV|BLANK|CALCULATE|CALCULATETABLE|CALENDAR|CALENDARAUTO|CEILING|CHISQ\.DIST|CHISQ\.DIST\.RT|CHISQ\.INV|CHISQ\.INV\.RT|CLOSINGBALANCEMONTH|CLOSINGBALANCEQUARTER|CLOSINGBALANCEYEAR|COALESCE|COMBIN|COMBINA|COMBINEVALUES|CONCATENATE|CONCATENATEX|CONFIDENCE\.NORM|CONFIDENCE\.T|CONTAINS|CONTAINSROW|CONTAINSSTRING|CONTAINSSTRINGEXACT|CONVERT|COS|COSH|COT|COTH|COUNT|COUNTA|COUNTAX|COUNTBLANK|COUNTROWS|COUNTX|CROSSFILTER|CROSSJOIN|CURRENCY|CURRENTGROUP|CUSTOMDATA|DATATABLE|DATE|DATEADD|DATEDIFF|DATESBETWEEN|DATESINPERIOD|DATESMTD|DATESQTD|DATESYTD|DATEVALUE|DAY|DEGREES|DETAILROWS|DISTINCT|DISTINCTCOUNT|DISTINCTCOUNTNOBLANK|DIVIDE|EARLIER|EARLIEST|EDATE|ENDOFMONTH|ENDOFQUARTER|ENDOFYEAR|EOMONTH|ERROR|EVEN|EXACT|EXCEPT|EXP|EXPON\.DIST|FACT|FALSE|FILTER|FILTERS|FIND|FIRSTDATE|FIRSTNONBLANK|FIRSTNONBLANKVALUE|FIXED|FLOOR|FORMAT|GCD|GENERATE|GENERATEALL|GENERATESERIES|GEOMEAN|GEOMEANX|GROUPBY|HASONEFILTER|HASONEVALUE|HOUR|IF|IF\.EAGER|IFERROR|IGNORE|INT|INTERSECT|ISBLANK|ISCROSSFILTERED|ISEMPTY|ISERROR|ISEVEN|ISFILTERED|ISINSCOPE|ISLOGICAL|ISNONTEXT|ISNUMBER|ISO\.CEILING|ISODD|ISONORAFTER|ISSELECTEDMEASURE|ISSUBTOTAL|ISTEXT|KEEPFILTERS|KEYWORDMATCH|LASTDATE|LASTNONBLANK|LASTNONBLANKVALUE|LCM|LEFT|LEN|LN|LOG|LOG10|LOOKUPVALUE|LOWER|MAX|MAXA|MAXX|MEDIAN|MEDIANX|MID|MIN|MINA|MINUTE|MINX|MOD|MONTH|MROUND|NATURALINNERJOIN|NATURALLEFTOUTERJOIN|NEXTDAY|NEXTMONTH|NEXTQUARTER|NEXTYEAR|NONVISUAL|NORM\.DIST|NORM\.INV|NORM\.S\.DIST|NORM\.S\.INV|NOT|NOW|ODD|OPENINGBALANCEMONTH|OPENINGBALANCEQUARTER|OPENINGBALANCEYEAR|OR|PARALLELPERIOD|PATH|PATHCONTAINS|PATHITEM|PATHITEMREVERSE|PATHLENGTH|PERCENTILE\.EXC|PERCENTILE\.INC|PERCENTILEX\.EXC|PERCENTILEX\.INC|PERMUT|PI|POISSON\.DIST|POWER|PREVIOUSDAY|PREVIOUSMONTH|PREVIOUSQUARTER|PREVIOUSYEAR|PRODUCT|PRODUCTX|QUARTER|QUOTIENT|RADIANS|RAND|RANDBETWEEN|RANK\.EQ|RANKX|RELATED|RELATEDTABLE|REMOVEFILTERS|REPLACE|REPT|RIGHT|ROLLUP|ROLLUPADDISSUBTOTAL|ROLLUPGROUP|ROLLUPISSUBTOTAL|ROUND|ROUNDDOWN|ROUNDUP|ROW|SAMEPERIODLASTYEAR|SAMPLE|SEARCH|SECOND|SELECTCOLUMNS|SELECTEDMEASURE|SELECTEDMEASUREFORMATSTRING|SELECTEDMEASURENAME|SELECTEDVALUE|SIGN|SIN|SINH|SQRT|SQRTPI|STARTOFMONTH|STARTOFQUARTER|STARTOFYEAR|STDEV\.P|STDEV\.S|STDEVX\.P|STDEVX\.S|SUBSTITUTE|SUBSTITUTEWITHINDEX|SUM|SUMMARIZE|SUMMARIZECOLUMNS|SUMX|SWITCH|T\.DIST|T\.DIST\.2T|T\.DIST\.RT|T\.INV|T\.INV\.2T|TAN|TANH|TIME|TIMEVALUE|TODAY|TOPN|TOPNPERLEVEL|TOPNSKIP|TOTALMTD|TOTALQTD|TOTALYTD|TREATAS|TRIM|TRUE|TRUNC|UNICHAR|UNICODE|UNION|UPPER|USERELATIONSHIP|USERNAME|USEROBJECTID|USERPRINCIPALNAME|UTCNOW|UTCTODAY|VALUE|VALUES|VAR\.P|VAR\.S|VARX\.P|VARX\.S|WEEKDAY|WEEKNUM|XIRR|XNPV|YEAR|YEARFRAC)(?=\s*\()/i,keyword:/\b(?:DEFINE|MEASURE|EVALUATE|ORDER\s+BY|RETURN|VAR|START\s+AT|ASC|DESC)\b/i,boolean:{pattern:/\b(?:TRUE|FALSE|NULL)\b/i,alias:"constant"},number:/\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/:=|[-+*\/=^]|&&?|\|\||<(?:=>?|<|>)?|>[>=]?|\b(?:IN|NOT)\b/i,punctuation:/[;\[\](){}`,.]/}; Prism.languages.dhall={comment:/--.*|\{-(?:[^-{]|-(?!\})|\{(?!-)|\{-(?:[^-{]|-(?!\})|\{(?!-))*-\})*-\}/,string:{pattern:/"(?:[^"\\]|\\.)*"|''(?:[^']|'(?!')|'''|''\$\{)*''(?!'|\$)/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^{}]*\}/,inside:{expression:{pattern:/(^\$\{)[\s\S]+(?=\}$)/,lookbehind:!0,alias:"language-dhall",inside:null},punctuation:/\$\{|\}/}}}},label:{pattern:/`[^`]*`/,greedy:!0},url:{pattern:/\bhttps?:\/\/[\w.:%!$&'*+;=@~-]+(?:\/[\w.:%!$&'*+;=@~-]*)*(?:\?[/?\w.:%!$&'*+;=@~-]*)?/,greedy:!0},env:{pattern:/\benv:(?:(?!\d)\w+|"(?:[^"\\=]|\\.)*")/,greedy:!0,inside:{function:/^env/,operator:/^:/,variable:/[\s\S]+/}},hash:{pattern:/\bsha256:[\da-fA-F]{64}\b/,inside:{function:/sha256/,operator:/:/,number:/[\da-fA-F]{64}/}},keyword:/\b(?:as|assert|else|forall|if|in|let|merge|missing|then|toMap|using|with)\b|\u2200/,builtin:/\b(?:Some|None)\b/,boolean:/\b(?:False|True)\b/,number:/\bNaN\b|-?\bInfinity\b|[+-]?\b(?:0x[\da-fA-F]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/,operator:/\/\\|\/\/\\\\|&&|\|\||===|[!=]=|\/\/|->|\+\+|::|[+*#@=:?<>|\\\u2227\u2a53\u2261\u2afd\u03bb\u2192]/,punctuation:/\.\.|[{}\[\](),./]/,"class-name":/\b[A-Z]\w*\b/},Prism.languages.dhall.string.inside.interpolation.inside.expression.inside=Prism.languages.dhall; !function(i){i.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var r={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(r).forEach(function(e){var n=r[e],a=[];/^\w+$/.test(e)||a.push(/\w+/.exec(e)[0]),"diff"===e&&a.push("bold"),i.languages.diff[e]={pattern:RegExp("^(?:["+n+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(e)[0]}}}}),Object.defineProperty(i.languages.diff,"PREFIXES",{value:r})}(Prism); !function(h){function v(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(h.languages["markup-templating"]={},{buildPlaceholders:{value:function(a,r,e,o){if(a.language===r){var c=a.tokenStack=[];a.code=a.code.replace(e,function(e){if("function"==typeof o&&!o(e))return e;for(var n,t=c.length;-1!==a.code.indexOf(n=v(r,t));)++t;return c[t]=e,n}),a.grammar=h.languages.markup}}},tokenizePlaceholders:{value:function(p,k){if(p.language===k&&p.tokenStack){p.grammar=h.languages[k];var m=0,d=Object.keys(p.tokenStack);!function e(n){for(var t=0;t=d.length);t++){var a=n[t];if("string"==typeof a||a.content&&"string"==typeof a.content){var r=d[m],o=p.tokenStack[r],c="string"==typeof a?a:a.content,i=v(k,r),u=c.indexOf(i);if(-1]?|>[=>]?|[&|^~]/,number:/\b\d+(?:\.\d+)?\b/,boolean:/[Tt]rue|[Ff]alse|[Nn]one/,variable:/\b\w+?\b/,punctuation:/[{}[\](),.:;]/};var n=/\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}|\{#[\s\S]*?#\}/g,o=e.languages["markup-templating"];e.hooks.add("before-tokenize",function(e){o.buildPlaceholders(e,"django",n)}),e.hooks.add("after-tokenize",function(e){o.tokenizePlaceholders(e,"django")}),e.languages.jinja2=e.languages.django,e.hooks.add("before-tokenize",function(e){o.buildPlaceholders(e,"jinja2",n)}),e.hooks.add("after-tokenize",function(e){o.tokenizePlaceholders(e,"jinja2")})}(Prism); Prism.languages["dns-zone-file"]={comment:/;.*/,string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},variable:[{pattern:/(^\$ORIGIN[ \t]+)\S+/m,lookbehind:!0},{pattern:/(^|\s)@(?=\s|$)/,lookbehind:!0}],keyword:/^\$(?:ORIGIN|INCLUDE|TTL)(?=\s|$)/m,class:{pattern:/(^|\s)(?:IN|CH|CS|HS)(?=\s|$)/,lookbehind:!0,alias:"keyword"},type:{pattern:/(^|\s)(?:A|A6|AAAA|AFSDB|APL|ATMA|CAA|CDNSKEY|CDS|CERT|CNAME|DHCID|DLV|DNAME|DNSKEY|DS|EID|GID|GPOS|HINFO|HIP|IPSECKEY|ISDN|KEY|KX|LOC|MAILA|MAILB|MB|MD|MF|MG|MINFO|MR|MX|NAPTR|NB|NBSTAT|NIMLOC|NINFO|NS|NSAP|NSAP-PTR|NSEC|NSEC3|NSEC3PARAM|NULL|NXT|OPENPGPKEY|PTR|PX|RKEY|RP|RRSIG|RT|SIG|SINK|SMIMEA|SOA|SPF|SRV|SSHFP|TA|TKEY|TLSA|TSIG|TXT|UID|UINFO|UNSPEC|URI|WKS|X25)(?=\s|$)/,lookbehind:!0,alias:"keyword"},punctuation:/[()]/},Prism.languages["dns-zone"]=Prism.languages["dns-zone-file"]; !function(e){var r="(?:[ \t]+(?![ \t])(?:)?|)".replace(//g,function(){return"\\\\[\r\n](?:\\s|\\\\[\r\n]|#.*(?!.))*(?![\\s#]|\\\\[\r\n])"}),n="\"(?:[^\"\\\\\r\n]|\\\\(?:\r\n|[^]))*\"|'(?:[^'\\\\\r\n]|\\\\(?:\r\n|[^]))*'",t="--[\\w-]+=(?:|(?![\"'])(?:[^\\s\\\\]|\\\\.)+)".replace(//g,function(){return n}),o={pattern:RegExp(n),greedy:!0},i={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function a(e,n){return e=e.replace(//g,function(){return t}).replace(//g,function(){return r}),RegExp(e,n)}e.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:a("(^(?:ONBUILD)?\\w+)(?:)*","i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[o,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:a("(^(?:ONBUILD)?HEALTHCHECK(?:)*)(?:CMD|NONE)\\b","i"),lookbehind:!0,greedy:!0},{pattern:a("(^(?:ONBUILD)?FROM(?:)*(?!--)[^ \t\\\\]+)AS","i"),lookbehind:!0,greedy:!0},{pattern:a("(^ONBUILD)\\w+","i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:i,string:o,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:i},e.languages.dockerfile=e.languages.docker}(Prism); !function(e){var n="(?:"+["[a-zA-Z_\\x80-\\uFFFF][\\w\\x80-\\uFFFF]*","-?(?:\\.\\d+|\\d+(?:\\.\\d*)?)",'"[^"\\\\]*(?:\\\\[^][^"\\\\]*)*"',"<(?:[^<>]|(?!\x3c!--)<(?:[^<>\"']|\"[^\"]*\"|'[^']*')+>|\x3c!--(?:[^-]|-(?!->))*--\x3e)*>"].join("|")+")",a={markup:{pattern:/(^<)[\s\S]+(?=>$)/,lookbehind:!0,alias:["language-markup","language-html","language-xml"],inside:e.languages.markup}};function r(e,a){return RegExp(e.replace(//g,function(){return n}),a)}e.languages.dot={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\/|^#.*/m,greedy:!0},"graph-name":{pattern:r("(\\b(?:digraph|graph|subgraph)[ \t\r\n]+)","i"),lookbehind:!0,greedy:!0,alias:"class-name",inside:a},"attr-value":{pattern:r("(=[ \t\r\n]*)"),lookbehind:!0,greedy:!0,inside:a},"attr-name":{pattern:r("([\\[;, \t\r\n])(?=[ \t\r\n]*=)"),lookbehind:!0,greedy:!0,inside:a},keyword:/\b(?:digraph|edge|graph|node|strict|subgraph)\b/i,"compass-point":{pattern:/(:[ \t\r\n]*)(?:[ns][ew]?|[ewc_])(?![\w\x80-\uFFFF])/,lookbehind:!0,alias:"builtin"},node:{pattern:r("(^|[^-.\\w\\x80-\\uFFFF\\\\])"),lookbehind:!0,greedy:!0,inside:a},operator:/[=:]|-[->]/,punctuation:/[\[\]{};,]/},e.languages.gv=e.languages.dot}(Prism); Prism.languages.ebnf={comment:/\(\*[\s\S]*?\*\)/,string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,greedy:!0},special:{pattern:/\?[^?\r\n]*\?/,greedy:!0,alias:"class-name"},definition:{pattern:/^([\t ]*)[a-z]\w*(?:[ \t]+[a-z]\w*)*(?=\s*=)/im,lookbehind:!0,alias:["rule","keyword"]},rule:/\b[a-z]\w*(?:[ \t]+[a-z]\w*)*\b/i,punctuation:/\([:/]|[:/]\)|[.,;()[\]{}]/,operator:/[-=|*/!]/}; Prism.languages.editorconfig={comment:/[;#].*/,section:{pattern:/(^[ \t]*)\[.+\]/m,lookbehind:!0,alias:"keyword",inside:{regex:/\\\\[\[\]{},!?.*]/,operator:/[!?]|\.\.|\*{1,2}/,punctuation:/[\[\]{},]/}},property:{pattern:/(^[ \t]*)[^\s=]+(?=[ \t]*=)/m,lookbehind:!0},value:{pattern:/=.*/,alias:"string",inside:{punctuation:/^=/}}}; Prism.languages.eiffel={comment:/--.*/,string:[{pattern:/"([^[]*)\[[\s\S]*?\]\1"/,greedy:!0},{pattern:/"([^{]*)\{[\s\S]*?\}\1"/,greedy:!0},{pattern:/"(?:%(?:(?!\n)\s)*\n\s*%|%\S|[^%"\r\n])*"/,greedy:!0}],char:/'(?:%.|[^%'\r\n])+'/,keyword:/\b(?:across|agent|alias|all|and|attached|as|assign|attribute|check|class|convert|create|Current|debug|deferred|detachable|do|else|elseif|end|ensure|expanded|export|external|feature|from|frozen|if|implies|inherit|inspect|invariant|like|local|loop|not|note|obsolete|old|once|or|Precursor|redefine|rename|require|rescue|Result|retry|select|separate|some|then|undefine|until|variant|Void|when|xor)\b/i,boolean:/\b(?:True|False)\b/i,"class-name":{pattern:/\b[A-Z][\dA-Z_]*\b/,alias:"builtin"},number:[/\b0[xcb][\da-f](?:_*[\da-f])*\b/i,/(?:\b\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?e[+-]?)?\d(?:_*\d)*\b|\b\d(?:_*\d)*\b\.?/i],punctuation:/:=|<<|>>|\(\||\|\)|->|\.(?=\w)|[{}[\];(),:?]/,operator:/\\\\|\|\.\.\||\.\.|\/[~\/=]?|[><]=?|[-+*^=~]/}; !function(e){e.languages.ejs={delimiter:{pattern:/^<%[-_=]?|[-_]?%>$/,alias:"punctuation"},comment:/^#[\s\S]*/,"language-javascript":{pattern:/[\s\S]+/,inside:e.languages.javascript}},e.hooks.add("before-tokenize",function(a){e.languages["markup-templating"].buildPlaceholders(a,"ejs",/<%(?!%)[\s\S]+?%>/g)}),e.hooks.add("after-tokenize",function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"ejs")}),e.languages.eta=e.languages.ejs}(Prism); Prism.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/m,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\b\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|delegate|exception|impl|macro|module|n|np|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|quote|raise|require|rescue|try|unless|unquote|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}); Prism.languages.elm={comment:/--.*|\{-[\s\S]*?-\}/,char:{pattern:/'(?:[^\\'\r\n]|\\(?:[abfnrtv\\']|\d+|x[0-9a-fA-F]+))'/,greedy:!0},string:[{pattern:/"""[\s\S]*?"""/,greedy:!0},{pattern:/"(?:[^\\"\r\n]|\\.)*"/,greedy:!0}],"import-statement":{pattern:/(^[\t ]*)import\s+[A-Z]\w*(?:\.[A-Z]\w*)*(?:\s+as\s+(?:[A-Z]\w*)(?:\.[A-Z]\w*)*)?(?:\s+exposing\s+)?/m,lookbehind:!0,inside:{keyword:/\b(?:import|as|exposing)\b/}},keyword:/\b(?:alias|as|case|else|exposing|if|in|infixl|infixr|let|module|of|then|type)\b/,builtin:/\b(?:abs|acos|always|asin|atan|atan2|ceiling|clamp|compare|cos|curry|degrees|e|flip|floor|fromPolar|identity|isInfinite|isNaN|logBase|max|min|negate|never|not|pi|radians|rem|round|sin|sqrt|tan|toFloat|toPolar|toString|truncate|turns|uncurry|xor)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0x[0-9a-f]+)\b/i,operator:/\s\.\s|[+\-/*=.$<>:&|^?%#@~!]{2,}|[+\-/*=$<>:&|^?%#@~!]/,hvariable:/\b(?:[A-Z]\w*\.)*[a-z]\w*\b/,constant:/\b(?:[A-Z]\w*\.)*[A-Z]\w*\b/,punctuation:/[{}[\]|(),.:]/}; Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; !function(e){e.languages.etlua={delimiter:{pattern:/^<%[-=]?|-?%>$/,alias:"punctuation"},"language-lua":{pattern:/[\s\S]+/,inside:e.languages.lua}},e.hooks.add("before-tokenize",function(a){e.languages["markup-templating"].buildPlaceholders(a,"etlua",/<%[\s\S]+?%>/g)}),e.hooks.add("after-tokenize",function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"etlua")})}(Prism); !function(n){n.languages.erb=n.languages.extend("ruby",{}),n.languages.insertBefore("erb","comment",{delimiter:{pattern:/^<%=?|%>$/,alias:"punctuation"}}),n.hooks.add("before-tokenize",function(e){n.languages["markup-templating"].buildPlaceholders(e,"erb",/<%=?(?:[^\r\n]|[\r\n](?!=begin)|[\r\n]=begin\s(?:[^\r\n]|[\r\n](?!=end))*[\r\n]=end)+?%>/gm)}),n.hooks.add("after-tokenize",function(e){n.languages["markup-templating"].tokenizePlaceholders(e,"erb")})}(Prism); Prism.languages.erlang={comment:/%.+/,string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},"quoted-function":{pattern:/'(?:\\.|[^\\'\r\n])+'(?=\()/,alias:"function"},"quoted-atom":{pattern:/'(?:\\.|[^\\'\r\n])+'/,alias:"atom"},boolean:/\b(?:true|false)\b/,keyword:/\b(?:fun|when|case|of|end|if|receive|after|try|catch)\b/,number:[/\$\\?./,/\b\d+#[a-z0-9]+/i,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i],function:/\b[a-z][\w@]*(?=\()/,variable:{pattern:/(^|[^@])(?:\b|\?)[A-Z_][\w@]*/,lookbehind:!0},operator:[/[=\/<>:]=|=[:\/]=|\+\+?|--?|[=*\/!]|\b(?:bnot|div|rem|band|bor|bxor|bsl|bsr|not|and|or|xor|orelse|andalso)\b/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],atom:/\b[a-z][\w@]*/,punctuation:/[()[\]{}:;,.#|]|<<|>>/}; Prism.languages["excel-formula"]={comment:{pattern:/(\bN\(\s*)"(?:[^"]|"")*"(?=\s*\))/i,lookbehind:!0,greedy:!0},string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},reference:{pattern:/(?:'[^']*'|(?:[^\s()[\]{}<>*?"';,$&]*\[[^^\s()[\]{}<>*?"']+\])?\w+)!/,greedy:!0,alias:"string",inside:{operator:/!$/,punctuation:/'/,sheet:{pattern:/[^[\]]+$/,alias:"function"},file:{pattern:/\[[^[\]]+\]$/,inside:{punctuation:/[[\]]/}},path:/[\s\S]+/}},"function-name":{pattern:/\b[A-Z]\w*(?=\()/i,alias:"keyword"},range:{pattern:/\$?\b(?:[A-Z]+\$?\d+:\$?[A-Z]+\$?\d+|[A-Z]+:\$?[A-Z]+|\d+:\$?\d+)\b/i,alias:"property",inside:{operator:/:/,cell:/\$?[A-Z]+\$?\d+/i,column:/\$?[A-Z]+/i,row:/\$?\d+/}},cell:{pattern:/\b[A-Z]+\d+\b|\$[A-Za-z]+\$?\d+\b|\b[A-Za-z]+\$\d+\b/,alias:"property"},number:/(?:\b\d+(?:\.\d+)?|\B\.\d+)(?:e[+-]?\d+)?\b/i,boolean:/\b(?:TRUE|FALSE)\b/i,operator:/[-+*/^%=&,]|<[=>]?|>=?/,punctuation:/[[\]();{}|]/},Prism.languages.xlsx=Prism.languages.xls=Prism.languages["excel-formula"]; Prism.languages.fsharp=Prism.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\(\*(?!\))[\s\S]*?\*\)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(?:"""[\s\S]*?"""|@"(?:""|[^"])*"|"(?:\\[\s\S]|[^\\"])*")B?|'(?:[^\\']|\\(?:.|\d{3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}|U[a-fA-F\d]{8}))'B?/,greedy:!0},"class-name":{pattern:/(\b(?:exception|inherit|interface|new|of|type)\s+|\w\s*:\s*|\s:\??>\s*)[.\w]+\b(?:\s*(?:->|\*)\s*[.\w]+\b)*(?!\s*[:.])/,lookbehind:!0,inside:{operator:/->|\*/,punctuation:/\./}},keyword:/\b(?:let|return|use|yield)(?:!\B|\b)|\b(?:abstract|and|as|assert|base|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|global|if|in|inherit|inline|interface|internal|lazy|match|member|module|mutable|namespace|new|not|null|of|open|or|override|private|public|rec|select|static|struct|then|to|true|try|type|upcast|val|void|when|while|with|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|include|method|mixin|object|parallel|process|protected|pure|sealed|tailcall|trait|virtual|volatile)\b/,number:[/\b0x[\da-fA-F]+(?:un|lf|LF)?\b/,/\b0b[01]+(?:y|uy)?\b/,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[fm]|e[+-]?\d+)?\b/i,/\b\d+(?:[IlLsy]|u[lsy]?|UL)?\b/],operator:/([<>~&^])\1\1|([*.:<>&])\2|<-|->|[!=:]=|?|\??(?:<=|>=|<>|[-+*/%=<>])\??|[!?^&]|~[+~-]|:>|:\?>?/}),Prism.languages.insertBefore("fsharp","keyword",{preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(^#)\b(?:else|endif|if|light|line|nowarn)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.insertBefore("fsharp","punctuation",{"computation-expression":{pattern:/\b[_a-z]\w*(?=\s*\{)/i,alias:"keyword"}}),Prism.languages.insertBefore("fsharp","string",{annotation:{pattern:/\[<.+?>\]/,inside:{punctuation:/^\[<|>\]$/,"class-name":{pattern:/^\w+$|(^|;\s*)[A-Z]\w*(?=\()/,lookbehind:!0},"annotation-content":{pattern:/[\s\S]+/,inside:Prism.languages.fsharp}}}}); !function(e){var t={function:/\b(?:TODOS?|FIX(?:MES?)?|NOTES?|BUGS?|XX+|HACKS?|WARN(?:ING)?|\?{2,}|!{2,})\b/},s={number:/\\[^\s']|%\w/},i={comment:[{pattern:/(^|\s)(?:! .*|!$)/,lookbehind:!0,inside:t},{pattern:/(^|\s)\/\*\s[\s\S]*?\*\/(?=\s|$)/,lookbehind:!0,greedy:!0,inside:t},{pattern:/(^|\s)!\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,lookbehind:!0,greedy:!0,inside:t}],number:[{pattern:/(^|\s)[+-]?\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?0(?:b[01]+|o[0-7]+|d\d+|x[\dA-F]+)(?=\s|$)/i,lookbehind:!0},{pattern:/(^|\s)[+-]?\d+\/\d+\.?(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)\+?\d+\+\d+\/\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)-\d+-\d+\/\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?(?:\d*\.\d+|\d+\.\d*|\d+)(?:e[+-]?\d+)?(?=\s|$)/i,lookbehind:!0},{pattern:/(^|\s)NAN:\s+[\da-fA-F]+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?0(?:b1\.[01]*|o1\.[0-7]*|d1\.\d*|x1\.[\dA-F]*)p\d+(?=\s|$)/i,lookbehind:!0}],regexp:{pattern:/(^|\s)R\/\s(?:\\\S|[^\\/])*\/(?:[idmsr]*|[idmsr]+-[idmsr]+)(?=\s|$)/,lookbehind:!0,alias:"number",inside:{variable:/\\\S/,keyword:/[+?*\[\]^$(){}.|]/,operator:{pattern:/(\/)[idmsr]+(?:-[idmsr]+)?/,lookbehind:!0}}},boolean:{pattern:/(^|\s)[tf](?=\s|$)/,lookbehind:!0},"custom-string":{pattern:/(^|\s)[A-Z0-9\-]+"\s(?:\\\S|[^"\\])*"/,lookbehind:!0,greedy:!0,alias:"string",inside:{number:/\\\S|%\w|\//}},"multiline-string":[{pattern:/(^|\s)STRING:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*;(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:{number:s.number,"semicolon-or-setlocal":{pattern:/([\r\n][ \t]*);(?=\s|$)/,lookbehind:!0,alias:"function"}}},{pattern:/(^|\s)HEREDOC:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*\S+(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:s},{pattern:/(^|\s)\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:s}],"special-using":{pattern:/(^|\s)USING:(?:\s\S+)*(?=\s+;(?:\s|$))/,lookbehind:!0,alias:"function",inside:{string:{pattern:/(\s)[^:\s]+/,lookbehind:!0}}},"stack-effect-delimiter":[{pattern:/(^|\s)(?:call|execute|eval)?\((?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)--(?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)\)(?=\s|$)/,lookbehind:!0,alias:"operator"}],combinators:{pattern:null,lookbehind:!0,alias:"keyword"},"kernel-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"sequences-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"math-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"constructor-word":{pattern:/(^|\s)<(?!=+>|-+>)\S+>(?=\s|$)/,lookbehind:!0,alias:"keyword"},"other-builtin-syntax":{pattern:null,lookbehind:!0,alias:"operator"},"conventionally-named-word":{pattern:/(^|\s)(?!")(?:(?:set|change|with|new)-\S+|\$\S+|>[^>\s]+|[^:>\s]+>|[^>\s]+>[^>\s]+|\+[^+\s]+\+|[^?\s]+\?|\?[^?\s]+|[^>\s]+>>|>>[^>\s]+|[^<\s]+<<|\([^()\s]+\)|[^!\s]+!|[^*\s]\S*\*|[^.\s]\S*\.)(?=\s|$)/,lookbehind:!0,alias:"keyword"},"colon-syntax":{pattern:/(^|\s)(?:[A-Z0-9\-]+#?)?:{1,2}\s+(?:;\S+|(?!;)\S+)(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"function"},"semicolon-or-setlocal":{pattern:/(\s)(?:;|:>)(?=\s|$)/,lookbehind:!0,alias:"function"},"curly-brace-literal-delimiter":[{pattern:/(^|\s)[a-z]*\{(?=\s)/i,lookbehind:!0,alias:"operator"},{pattern:/(\s)\}(?=\s|$)/,lookbehind:!0,alias:"operator"}],"quotation-delimiter":[{pattern:/(^|\s)\[(?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)\](?=\s|$)/,lookbehind:!0,alias:"operator"}],"normal-word":{pattern:/(^|\s)[^"\s]\S*(?=\s|$)/,lookbehind:!0},string:{pattern:/"(?:\\\S|[^"\\])*"/,greedy:!0,inside:s}},n=function(e){return(e+"").replace(/([.?*+\^$\[\]\\(){}|\-])/g,"\\$1")},r=function(e){return new RegExp("(^|\\s)(?:"+e.map(n).join("|")+")(?=\\s|$)")},a={"kernel-builtin":["or","2nipd","4drop","tuck","wrapper","nip","wrapper?","callstack>array","die","dupd","callstack","callstack?","3dup","hashcode","pick","4nip","build",">boolean","nipd","clone","5nip","eq?","?","=","swapd","2over","clear","2dup","get-retainstack","not","tuple?","dup","3nipd","call","-rotd","object","drop","assert=","assert?","-rot","execute","boa","get-callstack","curried?","3drop","pickd","overd","over","roll","3nip","swap","and","2nip","rotd","throw","(clone)","hashcode*","spin","reach","4dup","equal?","get-datastack","assert","2drop","","boolean?","identity-hashcode","identity-tuple?","null","composed?","new","5drop","rot","-roll","xor","identity-tuple","boolean"],"other-builtin-syntax":["=======","recursive","flushable",">>","<<<<<<","M\\","B","PRIVATE>","\\","======","final","inline","delimiter","deprecated",">>>>>","<<<<<<<","parse-complex","malformed-complex","read-only",">>>>>>>","call-next-method","<<","foldable","$","$[","${"],"sequences-builtin":["member-eq?","mismatch","append","assert-sequence=","longer","repetition","clone-like","3sequence","assert-sequence?","last-index-from","reversed","index-from","cut*","pad-tail","join-as","remove-eq!","concat-as","but-last","snip","nths","nth","sequence","longest","slice?","","remove-nth","tail-slice","empty?","tail*","member?","virtual-sequence?","set-length","drop-prefix","iota","unclip","bounds-error?","unclip-last-slice","non-negative-integer-expected","non-negative-integer-expected?","midpoint@","longer?","?set-nth","?first","rest-slice","prepend-as","prepend","fourth","sift","subseq-start","new-sequence","?last","like","first4","1sequence","reverse","slice","virtual@","repetition?","set-last","index","4sequence","max-length","set-second","immutable-sequence","first2","first3","supremum","unclip-slice","suffix!","insert-nth","tail","3append","short","suffix","concat","flip","immutable?","reverse!","2sequence","sum","delete-all","indices","snip-slice","","check-slice","sequence?","head","append-as","halves","sequence=","collapse-slice","?second","slice-error?","product","bounds-check?","bounds-check","immutable","virtual-exemplar","harvest","remove","pad-head","last","set-fourth","cartesian-product","remove-eq","shorten","shorter","reversed?","shorter?","shortest","head-slice","pop*","tail-slice*","but-last-slice","iota?","append!","cut-slice","new-resizable","head-slice*","sequence-hashcode","pop","set-nth","?nth","second","join","immutable-sequence?","","3append-as","virtual-sequence","subseq?","remove-nth!","length","last-index","lengthen","assert-sequence","copy","move","third","first","tail?","set-first","prefix","bounds-error","","exchange","surround","cut","min-length","set-third","push-all","head?","subseq-start-from","delete-slice","rest","sum-lengths","head*","infimum","remove!","glue","slice-error","subseq","push","replace-slice","subseq-as","unclip-last"],"math-builtin":["number=","next-power-of-2","?1+","fp-special?","imaginary-part","float>bits","number?","fp-infinity?","bignum?","fp-snan?","denominator","gcd","*","+","fp-bitwise=","-","u>=","/",">=","bitand","power-of-2?","log2-expects-positive","neg?","<","log2",">","integer?","number","bits>double","2/","zero?","bits>float","float?","shift","ratio?","rect>","even?","ratio","fp-sign","bitnot",">fixnum","complex?","/i","integer>fixnum","/f","sgn",">bignum","next-float","u<","u>","mod","recip","rational",">float","2^","integer","fixnum?","neg","fixnum","sq","bignum",">rect","bit?","fp-qnan?","simple-gcd","complex","","real",">fraction","double>bits","bitor","rem","fp-nan-payload","real-part","log2-expects-positive?","prev-float","align","unordered?","float","fp-nan?","abs","bitxor","integer>fixnum-strict","u<=","odd?","<=","/mod",">integer","real?","rational?","numerator"]};Object.keys(a).forEach(function(e){i[e].pattern=r(a[e])});i.combinators.pattern=r(["2bi","while","2tri","bi*","4dip","both?","same?","tri@","curry","prepose","3bi","?if","tri*","2keep","3keep","curried","2keepd","when","2bi*","2tri*","4keep","bi@","keepdd","do","unless*","tri-curry","if*","loop","bi-curry*","when*","2bi@","2tri@","with","2with","either?","bi","until","3dip","3curry","tri-curry*","tri-curry@","bi-curry","keepd","compose","2dip","if","3tri","unless","tuple","keep","2curry","tri","most","while*","dip","composed","bi-curry@","find-last-from","trim-head-slice","map-as","each-from","none?","trim-tail","partition","if-empty","accumulate*","reject!","find-from","accumulate-as","collector-for-as","reject","map","map-sum","accumulate!","2each-from","follow","supremum-by","map!","unless-empty","collector","padding","reduce-index","replicate-as","infimum-by","trim-tail-slice","count","find-index","filter","accumulate*!","reject-as","map-integers","map-find","reduce","selector","interleave","2map","filter-as","binary-reduce","map-index-as","find","produce","filter!","replicate","cartesian-map","cartesian-each","find-index-from","map-find-last","3map-as","3map","find-last","selector-as","2map-as","2map-reduce","accumulate","each","each-index","accumulate*-as","when-empty","all?","collector-as","push-either","new-like","collector-for","2selector","push-if","2all?","map-reduce","3each","any?","trim-slice","2reduce","change-nth","produce-as","2each","trim","trim-head","cartesian-find","map-index","if-zero","each-integer","unless-zero","(find-integer)","when-zero","find-last-integer","(all-integers?)","times","(each-integer)","find-integer","all-integers?","unless-negative","if-positive","when-positive","when-negative","unless-positive","if-negative","case","2cleave","cond>quot","case>quot","3cleave","wrong-values","to-fixed-point","alist>quot","cond","cleave","call-effect","recursive-hashcode","spread","deep-spread>quot","2||","0||","n||","0&&","2&&","3||","1||","1&&","n&&","3&&","smart-unless*","keep-inputs","reduce-outputs","smart-when*","cleave>array","smart-with","smart-apply","smart-if","inputs/outputs","output>sequence-n","map-outputs","map-reduce-outputs","dropping","output>array","smart-map-reduce","smart-2map-reduce","output>array-n","nullary","inputsequence"]),e.languages.factor=i}(Prism); Prism.languages.false={comment:{pattern:/\{[^}]*\}/},string:{pattern:/"[^"]*"/,greedy:!0},"character-code":{pattern:/'(?:[^\r]|\r\n?)/,alias:"number"},"assembler-code":{pattern:/\d+`/,alias:"important"},number:/\d+/,operator:/[-!#$%&'*+,./:;=>?@\\^_`|~ßø]/,punctuation:/\[|\]/,variable:/[a-z]/,"non-standard":{pattern:/[()!=]=?|[-+*/%]|\b(?:in|is)\b/}),delete Prism.languages["firestore-security-rules"]["class-name"],Prism.languages.insertBefore("firestore-security-rules","keyword",{path:{pattern:/(^|[\s(),])(?:\/(?:[\w\xA0-\uFFFF]+|\{[\w\xA0-\uFFFF]+(?:=\*\*)?\}|\$\([\w\xA0-\uFFFF.]+\)))+/,lookbehind:!0,greedy:!0,inside:{variable:{pattern:/\{[\w\xA0-\uFFFF]+(?:=\*\*)?\}|\$\([\w\xA0-\uFFFF.]+\)/,inside:{operator:/=/,keyword:/\*\*/,punctuation:/[.$(){}]/}},punctuation:/\//}},method:{pattern:/(\ballow\s+)[a-z]+(?:\s*,\s*[a-z]+)*(?=\s*[:;])/,lookbehind:!0,alias:"builtin",inside:{punctuation:/,/}}}); !function(a){a.languages.flow=a.languages.extend("javascript",{}),a.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Nn]umber|[Ss]tring|[Bb]oolean|Function|any|mixed|null|void)\b/,alias:"tag"}]}),a.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete a.languages.flow.parameter,a.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(a.languages.flow.keyword)||(a.languages.flow.keyword=[a.languages.flow.keyword]),a.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:type|opaque|declare|Class)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:await|Diff|Exact|Keys|ObjMap|PropertyType|Shape|Record|Supertype|Subtype|Enum)\b(?!\$)/,lookbehind:!0})}(Prism); Prism.languages.fortran={"quoted-number":{pattern:/[BOZ](['"])[A-F0-9]+\1/i,alias:"number"},string:{pattern:/(?:\b\w+_)?(['"])(?:\1\1|&(?:\r\n?|\n)(?:[ \t]*!.*(?:\r\n?|\n)|(?![ \t]*!))|(?!\1).)*(?:\1|&)/,inside:{comment:{pattern:/(&(?:\r\n?|\n)\s*)!.*/,lookbehind:!0}}},comment:{pattern:/!.*/,greedy:!0},boolean:/\.(?:TRUE|FALSE)\.(?:_\w+)?/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[ED][+-]?\d+)?(?:_\w+)?/i,keyword:[/\b(?:INTEGER|REAL|DOUBLE ?PRECISION|COMPLEX|CHARACTER|LOGICAL)\b/i,/\b(?:END ?)?(?:BLOCK ?DATA|DO|FILE|FORALL|FUNCTION|IF|INTERFACE|MODULE(?! PROCEDURE)|PROGRAM|SELECT|SUBROUTINE|TYPE|WHERE)\b/i,/\b(?:ALLOCATABLE|ALLOCATE|BACKSPACE|CALL|CASE|CLOSE|COMMON|CONTAINS|CONTINUE|CYCLE|DATA|DEALLOCATE|DIMENSION|DO|END|EQUIVALENCE|EXIT|EXTERNAL|FORMAT|GO ?TO|IMPLICIT(?: NONE)?|INQUIRE|INTENT|INTRINSIC|MODULE PROCEDURE|NAMELIST|NULLIFY|OPEN|OPTIONAL|PARAMETER|POINTER|PRINT|PRIVATE|PUBLIC|READ|RETURN|REWIND|SAVE|SELECT|STOP|TARGET|WHILE|WRITE)\b/i,/\b(?:ASSIGNMENT|DEFAULT|ELEMENTAL|ELSE|ELSEWHERE|ELSEIF|ENTRY|IN|INCLUDE|INOUT|KIND|NULL|ONLY|OPERATOR|OUT|PURE|RECURSIVE|RESULT|SEQUENCE|STAT|THEN|USE)\b/i],operator:[/\*\*|\/\/|=>|[=\/]=|[<>]=?|::|[+\-*=%]|\.[A-Z]+\./i,{pattern:/(^|(?!\().)\/(?!\))/,lookbehind:!0}],punctuation:/\(\/|\/\)|[(),;:&]/}; !function(n){for(var i="[^<()\"']|\\((?:)*\\)|<(?!#--)|<#--(?:[^-]|-(?!->))*--\x3e|\"(?:[^\\\\\"]|\\\\.)*\"|'(?:[^\\\\']|\\\\.)*'",e=0;e<2;e++)i=i.replace(//g,function(){return i});i=i.replace(//g,"[^\\s\\S]");var t={comment:/<#--[\s\S]*?-->/,string:[{pattern:/\br("|')(?:(?!\1)[^\\]|\\.)*\1/,greedy:!0},{pattern:RegExp("(\"|')(?:(?!\\1|\\$\\{)[^\\\\]|\\\\.|\\$\\{(?:(?!\\})(?:))*\\})*\\1".replace(//g,function(){return i})),greedy:!0,inside:{interpolation:{pattern:RegExp("((?:^|[^\\\\])(?:\\\\\\\\)*)\\$\\{(?:(?!\\})(?:))*\\}".replace(//g,function(){return i})),lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:null}}}}],keyword:/\b(?:as)\b/,boolean:/\b(?:true|false)\b/,"builtin-function":{pattern:/((?:^|[^?])\?\s*)\w+/,lookbehind:!0,alias:"function"},function:/\b\w+(?=\s*\()/,number:/\b\d+(?:\.\d+)?\b/,operator:/\.\.[<*!]?|->|--|\+\+|&&|\|\||\?{1,2}|[-+*/%!=<>]=?|\b(?:gt|gte|lt|lte)\b/,punctuation:/[,;.:()[\]{}]/};t.string[1].inside.interpolation.inside.rest=t,n.languages.ftl={"ftl-comment":{pattern:/^<#--[\s\S]*/,alias:"comment"},"ftl-directive":{pattern:/^<[\s\S]+>$/,inside:{directive:{pattern:/(^<\/?)[#@][a-z]\w*/i,lookbehind:!0,alias:"keyword"},punctuation:/^<\/?|\/?>$/,content:{pattern:/\s*\S[\s\S]*/,alias:"ftl",inside:t}}},"ftl-interpolation":{pattern:/^\$\{[\s\S]*\}$/,inside:{punctuation:/^\$\{|\}$/,content:{pattern:/\s*\S[\s\S]*/,alias:"ftl",inside:t}}}},n.hooks.add("before-tokenize",function(e){var t=RegExp("<#--[^]*?--\x3e|)*?>|\\$\\{(?:)*?\\}".replace(//g,function(){return i}),"gi");n.languages["markup-templating"].buildPlaceholders(e,"ftl",t)}),n.hooks.add("after-tokenize",function(e){n.languages["markup-templating"].tokenizePlaceholders(e,"ftl")})}(Prism); Prism.languages.gamemakerlanguage=Prism.languages.gml=Prism.languages.extend("clike",{keyword:/\b(?:if|else|switch|case|default|break|for|repeat|while|do|until|continue|exit|return|globalvar|var|enum)\b/,number:/(?:\b0x[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ulf]{0,4}/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not|with|at|xor)\b/,constant:/\b(?:self|other|all|noone|global|local|undefined|pointer_(?:invalid|null)|action_(?:stop|restart|continue|reverse)|pi|GM_build_date|GM_version|timezone_(?:local|utc)|gamespeed_(?:fps|microseconds)|ev_(?:create|destroy|step|alarm|keyboard|mouse|collision|other|draw|draw_(?:begin|end|pre|post)|keypress|keyrelease|trigger|(?:left|right|middle|no)_button|(?:left|right|middle)_press|(?:left|right|middle)_release|mouse_(?:enter|leave|wheel_up|wheel_down)|global_(?:left|right|middle)_button|global_(?:left|right|middle)_press|global_(?:left|right|middle)_release|joystick(?:1|2)_(?:left|right|up|down|button1|button2|button3|button4|button5|button6|button7|button8)|outside|boundary|game_start|game_end|room_start|room_end|no_more_lives|animation_end|end_of_path|no_more_health|user\d|step_(?:normal|begin|end)|gui|gui_begin|gui_end)|vk_(?:nokey|anykey|enter|return|shift|control|alt|escape|space|backspace|tab|pause|printscreen|left|right|up|down|home|end|delete|insert|pageup|pagedown|f\d|numpad\d|divide|multiply|subtract|add|decimal|lshift|lcontrol|lalt|rshift|rcontrol|ralt)|mb_(?:any|none|left|right|middle)|c_(?:aqua|black|blue|dkgray|fuchsia|gray|green|lime|ltgray|maroon|navy|olive|purple|red|silver|teal|white|yellow|orange)|fa_(?:left|center|right|top|middle|bottom|readonly|hidden|sysfile|volumeid|directory|archive)|pr_(?:pointlist|linelist|linestrip|trianglelist|trianglestrip|trianglefan)|bm_(?:complex|normal|add|max|subtract|zero|one|src_colour|inv_src_colour|src_color|inv_src_color|src_alpha|inv_src_alpha|dest_alpha|inv_dest_alpha|dest_colour|inv_dest_colour|dest_color|inv_dest_color|src_alpha_sat)|audio_(?:falloff_(?:none|inverse_distance|inverse_distance_clamped|linear_distance|linear_distance_clamped|exponent_distance|exponent_distance_clamped)|old_system|new_system|mono|stereo|3d)|cr_(?:default|none|arrow|cross|beam|size_nesw|size_ns|size_nwse|size_we|uparrow|hourglass|drag|appstart|handpoint|size_all)|asset_(?:object|unknown|sprite|sound|room|path|script|font|timeline|tiles|shader)|ds_type_(?:map|list|stack|queue|grid|priority)|ef_(?:explosion|ring|ellipse|firework|smoke|smokeup|star|spark|flare|cloud|rain|snow)|pt_shape_(?:pixel|disk|square|line|star|circle|ring|sphere|flare|spark|explosion|cloud|smoke|snow)|ps_(?:distr|shape)_(?:linear|gaussian|invgaussian|rectangle|ellipse|diamond|line)|ty_(?:real|string)|dll_(?:cdel|cdecl|stdcall)|matrix_(?:view|projection|world)|os_(?:win32|windows|macosx|ios|android|linux|unknown|winphone|win8native|psvita|ps4|xboxone|ps3|uwp)|browser_(?:not_a_browser|unknown|ie|firefox|chrome|safari|safari_mobile|opera|tizen|windows_store|ie_mobile)|device_ios_(?:unknown|iphone|iphone_retina|ipad|ipad_retina|iphone5|iphone6|iphone6plus)|device_(?:emulator|tablet)|display_(?:landscape|landscape_flipped|portrait|portrait_flipped)|of_challenge_(?:win|lose|tie)|leaderboard_type_(?:number|time_mins_secs)|cmpfunc_(?:never|less|equal|lessequal|greater|notequal|greaterequal|always)|cull_(?:noculling|clockwise|counterclockwise)|lighttype_(?:dir|point)|iap_(?:ev_storeload|ev_product|ev_purchase|ev_consume|ev_restore|storeload_ok|storeload_failed|status_uninitialised|status_unavailable|status_loading|status_available|status_processing|status_restoring|failed|unavailable|available|purchased|canceled|refunded)|fb_login_(?:default|fallback_to_webview|no_fallback_to_webview|forcing_webview|use_system_account|forcing_safari)|phy_joint_(?:anchor_1_x|anchor_1_y|anchor_2_x|anchor_2_y|reaction_force_x|reaction_force_y|reaction_torque|motor_speed|angle|motor_torque|max_motor_torque|translation|speed|motor_force|max_motor_force|length_1|length_2|damping_ratio|frequency|lower_angle_limit|upper_angle_limit|angle_limits|max_length|max_torque|max_force)|phy_debug_render_(?:aabb|collision_pairs|coms|core_shapes|joints|obb|shapes)|phy_particle_flag_(?:water|zombie|wall|spring|elastic|viscous|powder|tensile|colourmixing|colormixing)|phy_particle_group_flag_(?:solid|rigid)|phy_particle_data_flag_(?:typeflags|position|velocity|colour|color|category)|achievement_(?:our_info|friends_info|leaderboard_info|info|filter_(?:all_players|friends_only|favorites_only)|type_challenge|type_score_challenge|pic_loaded|show_(?:ui|profile|leaderboard|achievement|bank|friend_picker|purchase_prompt))|network_(?:socket_(?:tcp|udp|bluetooth)|type_(?:connect|disconnect|data|non_blocking_connect)|config_(?:connect_timeout|use_non_blocking_socket|enable_reliable_udp|disable_reliable_udp))|buffer_(?:fixed|grow|wrap|fast|vbuffer|network|u8|s8|u16|s16|u32|s32|u64|f16|f32|f64|bool|text|string|seek_start|seek_relative|seek_end|generalerror|outofspace|outofbounds|invalidtype)|gp_(?:face\d|shoulderl|shoulderr|shoulderlb|shoulderrb|select|start|stickl|stickr|padu|padd|padl|padr|axislh|axislv|axisrh|axisrv)|ov_(?:friends|community|players|settings|gamegroup|achievements)|lb_sort_(?:none|ascending|descending)|lb_disp_(?:none|numeric|time_sec|time_ms)|ugc_(?:result_success|filetype_(?:community|microtrans)|visibility_(?:public|friends_only|private)|query_RankedBy(?:Vote|PublicationDate|Trend|NumTimesReported|TotalVotesAsc|VotesUp|TextSearch)|query_(?:AcceptedForGameRankedByAcceptanceDate|FavoritedByFriendsRankedByPublicationDate|CreatedByFriendsRankedByPublicationDate|NotYetRated)|sortorder_CreationOrder(?:Desc|Asc)|sortorder_(?:TitleAsc|LastUpdatedDesc|SubscriptionDateDesc|VoteScoreDesc|ForModeration)|list_(?:Published|VotedOn|VotedUp|VotedDown|WillVoteLater|Favorited|Subscribed|UsedOrPlayed|Followed)|match_(?:Items|Items_Mtx|Items_ReadyToUse|Collections|Artwork|Videos|Screenshots|AllGuides|WebGuides|IntegratedGuides|UsableInGame|ControllerBindings))|vertex_usage_(?:position|colour|color|normal|texcoord|textcoord|blendweight|blendindices|psize|tangent|binormal|fog|depth|sample)|vertex_type_(?:float\d|colour|color|ubyte4)|layerelementtype_(?:undefined|background|instance|oldtilemap|sprite|tilemap|particlesystem|tile)|tile_(?:rotate|flip|mirror|index_mask)|input_type|se_(?:chorus|compressor|echo|equalizer|flanger|gargle|none|reverb)|text_type|(?:obj|scr|spr|rm)\w+)\b/,variable:/\b(?:x|y|(?:x|y)(?:previous|start)|(?:h|v)speed|direction|speed|friction|gravity|gravity_direction|path_(?:index|position|positionprevious|speed|scale|orientation|endaction)|object_index|id|solid|persistent|mask_index|instance_(?:count|id)|alarm|timeline_(?:index|position|speed|running|loop)|visible|sprite_(?:index|width|height|xoffset|yoffset)|image_(?:number|index|speed|depth|xscale|yscale|angle|alpha|blend)|bbox_(?:left|right|top|bottom)|layer|phy_(?:rotation|(?:position|linear_velocity|speed|com|collision|col_normal)_(?:x|y)|angular_(?:velocity|damping)|position_(?:x|y)previous|speed|linear_damping|bullet|fixed_rotation|active|mass|inertia|dynamic|kinematic|sleeping|collision_points)|working_directory|webgl_enabled|view_(?:(?:y|x|w|h)view|(?:y|x|w|h)port|(?:v|h)(?:speed|border)|visible|surface_id|object|enabled|current|angle)|undefined|transition_(?:steps|kind|color)|temp_directory|show_(?:score|lives|health)|secure_mode|score|room_(?:width|speed|persistent|last|height|first|caption)|room|pointer_(?:null|invalid)|os_(?:version|type|device|browser)|mouse_(?:y|x|lastbutton|button)|lives|keyboard_(?:string|lastkey|lastchar|key)|iap_data|health|gamemaker_(?:version|registered|pro)|game_(?:save|project|display)_(?:id|name)|fps_real|fps|event_(?:type|object|number|action)|error_(?:occurred|last)|display_aa|delta_time|debug_mode|cursor_sprite|current_(?:year|weekday|time|second|month|minute|hour|day)|caption_(?:score|lives|health)|browser_(?:width|height)|background_(?:yscale|y|xscale|x|width|vtiled|vspeed|visible|showcolour|showcolor|index|htiled|hspeed|height|foreground|colour|color|blend|alpha)|async_load|application_surface|argument(?:_relitive|_count|\d)|argument|global|local|self|other)\b/}); Prism.languages.gcode={comment:/;.*|\B\(.*?\)\B/,string:{pattern:/"(?:""|[^"])*"/,greedy:!0},keyword:/\b[GM]\d+(?:\.\d+)?\b/,property:/\b[A-Z]/,checksum:{pattern:/\*\d+/,alias:"punctuation"},punctuation:/:/}; Prism.languages.gdscript={comment:/#.*/,string:{pattern:/@?(?:("|')(?:(?!\1)[^\n\\]|\\[\s\S])*\1(?!"|')|"""(?:[^\\]|\\[\s\S])*?""")/,greedy:!0},"class-name":{pattern:/(^(?:class_name|class|extends)[ \t]+|^export\([ \t]*|\bas[ \t]+|(?:\b(?:const|var)[ \t]|[,(])[ \t]*\w+[ \t]*:[ \t]*|->[ \t]*)[a-zA-Z_]\w*/m,lookbehind:!0},keyword:/\b(?:and|as|assert|break|breakpoint|class|class_name|const|continue|elif|else|enum|export|extends|for|func|if|in|is|master|mastersync|match|not|null|onready|or|pass|preload|puppet|puppetsync|remote|remotesync|return|self|setget|signal|static|tool|var|while|yield)\b/,function:/\b[a-z_]\w*(?=[ \t]*\()/i,variable:/\$\w+/,number:[/\b0b[01_]+\b|\b0x[\da-fA-F_]+\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.[\d_]+)(?:e[+-]?[\d_]+)?\b/,/\b(?:INF|NAN|PI|TAU)\b/],constant:/\b[A-Z][A-Z_\d]*\b/,boolean:/\b(?:false|true)\b/,operator:/->|:=|&&|\|\||<<|>>|[-+*/%&|!<>=]=?|[~^]/,punctuation:/[.:,;()[\]{}]/}; Prism.languages.gedcom={"line-value":{pattern:/(^[\t ]*\d+ +(?:@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@ +)?\w+ ).+/m,lookbehind:!0,inside:{pointer:{pattern:/^@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@$/,alias:"variable"}}},tag:{pattern:/(^[\t ]*\d+ +(?:@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@ +)?)\w+/m,lookbehind:!0,alias:"string"},level:{pattern:/(^[\t ]*)\d+/m,lookbehind:!0,alias:"number"},pointer:{pattern:/@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@/,alias:"variable"}}; !function(a){var n="(?:\r?\n|\r)[ \t]*\\|.+\\|(?:(?!\\|).)*";Prism.languages.gherkin={pystring:{pattern:/("""|''')[\s\S]+?\1/,alias:"string"},comment:{pattern:/(^[ \t]*)#.*/m,lookbehind:!0},tag:{pattern:/(^[ \t]*)@\S*/m,lookbehind:!0},feature:{pattern:/((?:^|\r?\n|\r)[ \t]*)(?:Ability|Ahoy matey!|Arwedd|Aspekt|Besigheid Behoefte|Business Need|Caracteristica|Característica|Egenskab|Egenskap|Eiginleiki|Feature|Fīča|Fitur|Fonctionnalité|Fonksyonalite|Funcionalidade|Funcionalitat|Functionalitate|Funcţionalitate|Funcționalitate|Functionaliteit|Fungsi|Funkcia|Funkcija|Funkcionalitāte|Funkcionalnost|Funkcja|Funksie|Funktionalität|Funktionalitéit|Funzionalità|Hwaet|Hwæt|Jellemző|Karakteristik|laH|Lastnost|Mak|Mogucnost|Mogućnost|Moznosti|Možnosti|OH HAI|Omadus|Ominaisuus|Osobina|Özellik|perbogh|poQbogh malja'|Potrzeba biznesowa|Požadavek|Požiadavka|Pretty much|Qap|Qu'meH 'ut|Savybė|Tính năng|Trajto|Vermoë|Vlastnosť|Właściwość|Značilnost|Δυνατότητα|Λειτουργία|Могућност|Мөмкинлек|Особина|Свойство|Үзенчәлеклелек|Функционал|Функционалност|Функция|Функціонал|תכונה|خاصية|خصوصیت|صلاحیت|کاروبار کی ضرورت|وِیژگی|रूप लेख|ਖਾਸੀਅਤ|ਨਕਸ਼ ਨੁਹਾਰ|ਮੁਹਾਂਦਰਾ|గుణము|ಹೆಚ್ಚಳ|ความต้องการทางธุรกิจ|ความสามารถ|โครงหลัก|기능|フィーチャ|功能|機能):(?:[^:\r\n]+(?:\r?\n|\r|$))*/,lookbehind:!0,inside:{important:{pattern:/(:)[^\r\n]+/,lookbehind:!0},keyword:/[^:\r\n]+:/}},scenario:{pattern:/(^[ \t]*)(?:Abstract Scenario|Abstrakt Scenario|Achtergrond|Aer|Ær|Agtergrond|All y'all|Antecedentes|Antecedents|Atburðarás|Atburðarásir|Awww, look mate|B4|Background|Baggrund|Bakgrund|Bakgrunn|Bakgrunnur|Beispiele|Beispiller|Bối cảnh|Cefndir|Cenario|Cenário|Cenario de Fundo|Cenário de Fundo|Cenarios|Cenários|Contesto|Context|Contexte|Contexto|Conto|Contoh|Contone|Dæmi|Dasar|Dead men tell no tales|Delineacao do Cenario|Delineação do Cenário|Dis is what went down|Dữ liệu|Dyagram senaryo|Dyagram Senaryo|Egzanp|Ejemplos|Eksempler|Ekzemploj|Enghreifftiau|Esbozo do escenario|Escenari|Escenario|Esempi|Esquema de l'escenari|Esquema del escenario|Esquema do Cenario|Esquema do Cenário|Examples|EXAMPLZ|Exempel|Exemple|Exemples|Exemplos|First off|Fono|Forgatókönyv|Forgatókönyv vázlat|Fundo|Geçmiş|ghantoH|Grundlage|Hannergrond|Háttér|Heave to|Istorik|Juhtumid|Keadaan|Khung kịch bản|Khung tình huống|Kịch bản|Koncept|Konsep skenario|Kontèks|Kontekst|Kontekstas|Konteksts|Kontext|Konturo de la scenaro|Latar Belakang|lut|lut chovnatlh|lutmey|Lýsing Atburðarásar|Lýsing Dæma|Menggariskan Senario|MISHUN|MISHUN SRSLY|mo'|Náčrt Scenára|Náčrt Scénáře|Náčrt Scenáru|Oris scenarija|Örnekler|Osnova|Osnova Scenára|Osnova scénáře|Osnutek|Ozadje|Paraugs|Pavyzdžiai|Példák|Piemēri|Plan du scénario|Plan du Scénario|Plan senaryo|Plan Senaryo|Plang vum Szenario|Pozadí|Pozadie|Pozadina|Príklady|Příklady|Primer|Primeri|Primjeri|Przykłady|Raamstsenaarium|Reckon it's like|Rerefons|Scenár|Scénář|Scenarie|Scenarij|Scenarijai|Scenarijaus šablonas|Scenariji|Scenārijs|Scenārijs pēc parauga|Scenarijus|Scenario|Scénario|Scenario Amlinellol|Scenario Outline|Scenario Template|Scenariomal|Scenariomall|Scenarios|Scenariu|Scenariusz|Scenaro|Schema dello scenario|Se ðe|Se the|Se þe|Senario|Senaryo|Senaryo deskripsyon|Senaryo Deskripsyon|Senaryo taslağı|Shiver me timbers|Situācija|Situai|Situasie|Situasie Uiteensetting|Skenario|Skenario konsep|Skica|Structura scenariu|Structură scenariu|Struktura scenarija|Stsenaarium|Swa|Swa hwaer swa|Swa hwær swa|Szablon scenariusza|Szenario|Szenariogrundriss|Tapaukset|Tapaus|Tapausaihio|Taust|Tausta|Template Keadaan|Template Senario|Template Situai|The thing of it is|Tình huống|Variantai|Voorbeelde|Voorbeelden|Wharrimean is|Yo-ho-ho|You'll wanna|Założenia|Παραδείγματα|Περιγραφή Σεναρίου|Σενάρια|Σενάριο|Υπόβαθρο|Кереш|Контекст|Концепт|Мисаллар|Мисоллар|Основа|Передумова|Позадина|Предистория|Предыстория|Приклади|Пример|Примери|Примеры|Рамка на сценарий|Скица|Структура сценарија|Структура сценария|Структура сценарію|Сценарий|Сценарий структураси|Сценарийның төзелеше|Сценарији|Сценарио|Сценарій|Тарих|Үрнәкләр|דוגמאות|רקע|תבנית תרחיש|תרחיש|الخلفية|الگوی سناریو|امثلة|پس منظر|زمینه|سناریو|سيناريو|سيناريو مخطط|مثالیں|منظر نامے کا خاکہ|منظرنامہ|نمونه ها|उदाहरण|परिदृश्य|परिदृश्य रूपरेखा|पृष्ठभूमि|ਉਦਾਹਰਨਾਂ|ਪਟਕਥਾ|ਪਟਕਥਾ ਢਾਂਚਾ|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਿਛੋਕੜ|ఉదాహరణలు|కథనం|నేపథ్యం|సన్నివేశం|ಉದಾಹರಣೆಗಳು|ಕಥಾಸಾರಾಂಶ|ವಿವರಣೆ|ಹಿನ್ನೆಲೆ|โครงสร้างของเหตุการณ์|ชุดของตัวอย่าง|ชุดของเหตุการณ์|แนวคิด|สรุปเหตุการณ์|เหตุการณ์|배경|시나리오|시나리오 개요|예|サンプル|シナリオ|シナリオアウトライン|シナリオテンプレ|シナリオテンプレート|テンプレ|例|例子|剧本|剧本大纲|劇本|劇本大綱|场景|场景大纲|場景|場景大綱|背景):[^:\r\n]*/m,lookbehind:!0,inside:{important:{pattern:/(:)[^\r\n]*/,lookbehind:!0},keyword:/[^:\r\n]+:/}},"table-body":{pattern:RegExp("("+n+")(?:"+n+")+"),lookbehind:!0,inside:{outline:{pattern:/<[^>]+>/,alias:"variable"},td:{pattern:/\s*[^\s|][^|]*/,alias:"string"},punctuation:/\|/}},"table-head":{pattern:RegExp(n),inside:{th:{pattern:/\s*[^\s|][^|]*/,alias:"variable"},punctuation:/\|/}},atrule:{pattern:/(^[ \t]+)(?:'ach|'a|'ej|7|a|A také|A taktiež|A tiež|A zároveň|Aber|Ac|Adott|Akkor|Ak|Aleshores|Ale|Ali|Allora|Alors|Als|Ama|Amennyiben|Amikor|Ampak|an|AN|Ananging|And y'all|And|Angenommen|Anrhegedig a|An|Apabila|Atès|Atesa|Atunci|Avast!|Aye|A|awer|Bagi|Banjur|Bet|Biết|Blimey!|Buh|But at the end of the day I reckon|But y'all|But|BUT|Cal|Când|Cando|Cand|Ce|Cuando|Če|Ða ðe|Ða|Dadas|Dada|Dados|Dado|DaH ghu' bejlu'|dann|Dann|Dano|Dan|Dar|Dat fiind|Data|Date fiind|Date|Dati fiind|Dati|Daţi fiind|Dați fiind|Dato|DEN|Den youse gotta|Dengan|De|Diberi|Diyelim ki|Donada|Donat|Donitaĵo|Do|Dun|Duota|Ðurh|Eeldades|Ef|Eğer ki|Entao|Então|Entón|Entonces|En|Epi|E|És|Etant donnée|Etant donné|Et|Étant données|Étant donnée|Étant donné|Etant données|Etant donnés|Étant donnés|Fakat|Gangway!|Gdy|Gegeben seien|Gegeben sei|Gegeven|Gegewe|ghu' noblu'|Gitt|Given y'all|Given|Givet|Givun|Ha|Cho|I CAN HAZ|In|Ir|It's just unbelievable|I|Ja|Jeśli|Jeżeli|Kadar|Kada|Kad|Kai|Kaj|Když|Keď|Kemudian|Ketika|Khi|Kiedy|Ko|Kuid|Kui|Kun|Lan|latlh|Le sa a|Let go and haul|Le|Lè sa a|Lè|Logo|Lorsqu'<|Lorsque|mä|Maar|Mais|Mając|Majd|Maka|Manawa|Mas|Ma|Menawa|Men|Mutta|Nalikaning|Nalika|Nanging|Når|När|Nato|Nhưng|Niin|Njuk|O zaman|Og|Och|Oletetaan|Onda|Ond|Oraz|Pak|Pero|Però|Podano|Pokiaľ|Pokud|Potem|Potom|Privzeto|Pryd|qaSDI'|Quando|Quand|Quan|Så|Sed|Se|Siis|Sipoze ke|Sipoze Ke|Sipoze|Si|Şi|Și|Soit|Stel|Tada|Tad|Takrat|Tak|Tapi|Ter|Tetapi|Tha the|Tha|Then y'all|Then|Thì|Thurh|Toda|Too right|ugeholl|Und|Un|Và|vaj|Vendar|Ve|wann|Wanneer|WEN|Wenn|When y'all|When|Wtedy|Wun|Y'know|Yeah nah|Yna|Youse know like when|Youse know when youse got|Y|Za predpokladu|Za předpokladu|Zadani|Zadano|Zadan|Zadate|Zadato|Zakładając|Zaradi|Zatati|Þa þe|Þa|Þá|Þegar|Þurh|Αλλά|Δεδομένου|Και|Όταν|Τότε|А також|Агар|Але|Али|Аммо|А|Әгәр|Әйтик|Әмма|Бирок|Ва|Вә|Дадено|Дано|Допустим|Если|Задате|Задати|Задато|И|І|К тому же|Када|Кад|Когато|Когда|Коли|Ләкин|Лекин|Нәтиҗәдә|Нехай|Но|Онда|Припустимо, що|Припустимо|Пусть|Также|Та|Тогда|Тоді|То|Унда|Һәм|Якщо|אבל|אזי|אז|בהינתן|וגם|כאשר|آنگاه|اذاً|اگر|اما|اور|با فرض|بالفرض|بفرض|پھر|تب|ثم|جب|عندما|فرض کیا|لكن|لیکن|متى|هنگامی|و|अगर|और|कदा|किन्तु|चूंकि|जब|तथा|तदा|तब|परन्तु|पर|यदि|ਅਤੇ|ਜਦੋਂ|ਜਿਵੇਂ ਕਿ|ਜੇਕਰ|ਤਦ|ਪਰ|అప్పుడు|ఈ పరిస్థితిలో|కాని|చెప్పబడినది|మరియు|ಆದರೆ|ನಂತರ|ನೀಡಿದ|ಮತ್ತು|ಸ್ಥಿತಿಯನ್ನು|กำหนดให้|ดังนั้น|แต่|เมื่อ|และ|그러면<|그리고<|단<|만약<|만일<|먼저<|조건<|하지만<|かつ<|しかし<|ただし<|ならば<|もし<|並且<|但し<|但是<|假如<|假定<|假設<|假设<|前提<|同时<|同時<|并且<|当<|當<|而且<|那么<|那麼<)(?=[ \t])/m,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'/,inside:{outline:{pattern:/<[^>]+>/,alias:"variable"}}},outline:{pattern:/<[^>]+>/,alias:"variable"}}}(); Prism.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/m,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/m}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m}; Prism.languages.glsl=Prism.languages.extend("c",{keyword:/\b(?:attribute|const|uniform|varying|buffer|shared|coherent|volatile|restrict|readonly|writeonly|atomic_uint|layout|centroid|flat|smooth|noperspective|patch|sample|break|continue|do|for|while|switch|case|default|if|else|subroutine|in|out|inout|float|double|int|void|bool|true|false|invariant|precise|discard|return|d?mat[234](?:x[234])?|[ibdu]?vec[234]|uint|lowp|mediump|highp|precision|[iu]?sampler[123]D|[iu]?samplerCube|sampler[12]DShadow|samplerCubeShadow|[iu]?sampler[12]DArray|sampler[12]DArrayShadow|[iu]?sampler2DRect|sampler2DRectShadow|[iu]?samplerBuffer|[iu]?sampler2DMS(?:Array)?|[iu]?samplerCubeArray|samplerCubeArrayShadow|[iu]?image[123]D|[iu]?image2DRect|[iu]?imageCube|[iu]?imageBuffer|[iu]?image[12]DArray|[iu]?imageCubeArray|[iu]?image2DMS(?:Array)?|struct|common|partition|active|asm|class|union|enum|typedef|template|this|resource|goto|inline|noinline|public|static|extern|external|interface|long|short|half|fixed|unsigned|superp|input|output|hvec[234]|fvec[234]|sampler3DRect|filter|sizeof|cast|namespace|using)\b/}); Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|iota|nil|true|false)\b/,number:/(?:\b0x[a-f\d]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[-+]?\d+)?)i?/i,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/}),delete Prism.languages.go["class-name"]; Prism.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:Prism.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:true|false)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/[A-Z]\w*Input(?=!?.*$)/m,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},Prism.hooks.add("after-tokenize",function(n){if("graphql"===n.language)for(var o=n.tokens.filter(function(n){return"string"!=typeof n&&"comment"!==n.type&&"scalar"!==n.type}),s=0;s]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),Prism.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment"}}),Prism.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(?:setup|given|when|then|and|cleanup|expect|where):/}),Prism.languages.insertBefore("groovy","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),Prism.hooks.add("wrap",function(e){if("groovy"===e.language&&"string"===e.type){var t=e.content[0];if("'"!=t){var n=/([^\\])(?:\$(?:\{.*?\}|[\w.]+))/;"$"===t&&(n=/([^\$])(?:\$(?:\{.*?\}|[\w.]+))/),e.content=e.content.replace(/</g,"<").replace(/&/g,"&"),e.content=Prism.highlight(e.content,{expression:{pattern:n,lookbehind:!0,inside:Prism.languages.groovy}}),e.classes.push("/"===t?"regex":"gstring")}}}); !function(e){e.languages.haml={"multiline-comment":{pattern:/((?:^|\r?\n|\r)([\t ]*))(?:\/|-#).*(?:(?:\r?\n|\r)\2[\t ].+)*/,lookbehind:!0,alias:"comment"},"multiline-code":[{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*,[\t ]*(?:(?:\r?\n|\r)\2[\t ].*,[\t ]*)*(?:(?:\r?\n|\r)\2[\t ].+)/,lookbehind:!0,inside:e.languages.ruby},{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*\|[\t ]*(?:(?:\r?\n|\r)\2[\t ].*\|[\t ]*)*/,lookbehind:!0,inside:e.languages.ruby}],filter:{pattern:/((?:^|\r?\n|\r)([\t ]*)):[\w-]+(?:(?:\r?\n|\r)(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"}}},markup:{pattern:/((?:^|\r?\n|\r)[\t ]*)<.+/,lookbehind:!0,inside:e.languages.markup},doctype:{pattern:/((?:^|\r?\n|\r)[\t ]*)!!!(?: .+)?/,lookbehind:!0},tag:{pattern:/((?:^|\r?\n|\r)[\t ]*)[%.#][\w\-#.]*[\w\-](?:\([^)]+\)|\{(?:\{[^}]+\}|[^{}])+\}|\[[^\]]+\])*[\/<>]*/,lookbehind:!0,inside:{attributes:[{pattern:/(^|[^#])\{(?:\{[^}]+\}|[^{}])+\}/,lookbehind:!0,inside:e.languages.ruby},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*)(?:"(?:\\.|[^\\"\r\n])*"|[^)\s]+)/,lookbehind:!0},"attr-name":/[\w:-]+(?=\s*!?=|\s*[,)])/,punctuation:/[=(),]/}},{pattern:/\[[^\]]+\]/,inside:e.languages.ruby}],punctuation:/[<>]/}},code:{pattern:/((?:^|\r?\n|\r)[\t ]*(?:[~-]|[&!]?=)).+/,lookbehind:!0,inside:e.languages.ruby},interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:e.languages.ruby}},punctuation:{pattern:/((?:^|\r?\n|\r)[\t ]*)[~=\-&!]+/,lookbehind:!0}};for(var t=["css",{filter:"coffee",language:"coffeescript"},"erb","javascript","less","markdown","ruby","scss","textile"],n={},r=0,a=t.length;r@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",function(a){e.languages["markup-templating"].buildPlaceholders(a,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)}),e.hooks.add("after-tokenize",function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"handlebars")}),e.languages.hbs=e.languages.handlebars}(Prism); Prism.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\/].*|$)|\{-[\s\S]*?-\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\']|\\(?:[abfnrtv\\"'&]|\^[A-Z@[\]^_]|NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:"string"},string:{pattern:/"(?:[^\\"]|\\(?:\S|\s+\\))*"/,greedy:!0},keyword:/\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b/,"import-statement":{pattern:/(^[\t ]*)import\s+(?:qualified\s+)?(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*(?:\s+as\s+(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:import|qualified|as|hiding)\b/,punctuation:/\./}},builtin:/\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0o[0-7]+|0x[0-9a-f]+)\b/i,operator:[{pattern:/`(?:[A-Z][\w']*\.)*[_a-z][\w']*`/,greedy:!0},{pattern:/(\s)\.(?=\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\/][-!#$%*+=?&@|~.:<>^\\\/]*|\.[-!#$%*+=?&@|~.:<>^\\\/]+/],hvariable:{pattern:/\b(?:[A-Z][\w']*\.)*[_a-z][\w']*/,inside:{punctuation:/\./}},constant:{pattern:/\b(?:[A-Z][\w']*\.)*[A-Z][\w']*/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:]/},Prism.languages.hs=Prism.languages.haskell; Prism.languages.haxe=Prism.languages.extend("clike",{string:{pattern:/(["'])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0,inside:{interpolation:{pattern:/(^|[^\\])\$(?:\w+|\{[^}]+\})/,lookbehind:!0,inside:{interpolation:{pattern:/^\$\w*/,alias:"variable"}}}}},keyword:/\bthis\b|\b(?:abstract|as|break|case|cast|catch|class|continue|default|do|dynamic|else|enum|extends|extern|from|for|function|if|implements|import|in|inline|interface|macro|new|null|override|public|private|return|static|super|switch|throw|to|try|typedef|using|var|while)(?!\.)\b/,operator:/\.{3}|\+\+?|-[->]?|[=!]=?|&&?|\|\|?|<[<=]?|>[>=]?|[*\/%~^]/}),Prism.languages.insertBefore("haxe","class-name",{regex:{pattern:/~\/(?:[^\/\\\r\n]|\\.)+\/[igmsu]*/,greedy:!0}}),Prism.languages.insertBefore("haxe","keyword",{preprocessor:{pattern:/#\w+/,alias:"builtin"},metadata:{pattern:/@:?\w+/,alias:"symbol"},reification:{pattern:/\$(?:\w+|(?=\{))/,alias:"variable"}}),Prism.languages.haxe.string.inside.interpolation.inside.rest=Prism.languages.haxe,delete Prism.languages.haxe["class-name"]; Prism.languages.hcl={comment:/(?:\/\/|#).*|\/\*[\s\S]*?(?:\*\/|$)/,heredoc:{pattern:/<<-?(\w+\b)[\s\S]*?^[ \t]*\1/m,greedy:!0,alias:"string"},keyword:[{pattern:/(?:resource|data)\s+(?:"(?:\\[\s\S]|[^\\"])*")(?=\s+"[\w-]+"\s+\{)/i,inside:{type:{pattern:/(resource|data|\s+)(?:"(?:\\[\s\S]|[^\\"])*")/i,lookbehind:!0,alias:"variable"}}},{pattern:/(?:provider|provisioner|variable|output|module|backend)\s+(?:[\w-]+|"(?:\\[\s\S]|[^\\"])*")\s+(?=\{)/i,inside:{type:{pattern:/(provider|provisioner|variable|output|module|backend)\s+(?:[\w-]+|"(?:\\[\s\S]|[^\\"])*")\s+/i,lookbehind:!0,alias:"variable"}}},/[\w-]+(?=\s+\{)/],property:[/[-\w\.]+(?=\s*=(?!=))/,/"(?:\\[\s\S]|[^\\"])+"(?=\s*[:=])/],string:{pattern:/"(?:[^\\$"]|\\[\s\S]|\$(?:(?=")|\$+(?!\$)|[^"${])|\$\{(?:[^{}"]|"(?:[^\\"]|\\[\s\S])*")*\})*"/,greedy:!0,inside:{interpolation:{pattern:/(^|[^$])\$\{(?:[^{}"]|"(?:[^\\"]|\\[\s\S])*")*\}/,lookbehind:!0,inside:{type:{pattern:/(\b(?:terraform|var|self|count|module|path|data|local)\b\.)[\w\*]+/i,lookbehind:!0,alias:"variable"},keyword:/\b(?:terraform|var|self|count|module|path|data|local)\b/i,function:/\w+(?=\()/,string:{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0},number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,punctuation:/[!\$#%&'()*+,.\/;<=>@\[\\\]^`{|}~?:]/}}}},number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,boolean:/\b(?:true|false)\b/i,punctuation:/[=\[\]{}]/}; Prism.languages.hlsl=Prism.languages.extend("c",{"class-name":[Prism.languages.c["class-name"],/\b(?:AppendStructuredBuffer|BlendState|Buffer|ByteAddressBuffer|CompileShader|ComputeShader|ConsumeStructuredBuffer|DepthStencilState|DepthStencilView|DomainShader|GeometryShader|Hullshader|InputPatch|LineStream|OutputPatch|PixelShader|PointStream|RasterizerState|RenderTargetView|RWBuffer|RWByteAddressBuffer|RWStructuredBuffer|RWTexture(?:1D|1DArray|2D|2DArray|3D)|SamplerComparisonState|SamplerState|StructuredBuffer|Texture(?:1D|1DArray|2D|2DArray|2DMS|2DMSArray|3D|Cube|CubeArray)|TriangleStream|VertexShader)\b/],keyword:[/\b(?:asm|asm_fragment|auto|break|case|catch|cbuffer|centroid|char|class|column_major|compile|compile_fragment|const|const_cast|continue|default|delete|discard|do|dynamic_cast|else|enum|explicit|export|extern|for|friend|fxgroup|goto|groupshared|if|in|inline|inout|interface|line|lineadj|linear|long|matrix|mutable|namespace|new|nointerpolation|noperspective|operator|out|packoffset|pass|pixelfragment|point|precise|private|protected|public|register|reinterpret_cast|return|row_major|sample|sampler|shared|short|signed|sizeof|snorm|stateblock|stateblock_state|static|static_cast|string|struct|switch|tbuffer|technique|technique10|technique11|template|texture|this|throw|triangle|triangleadj|try|typedef|typename|uniform|union|unorm|unsigned|using|vector|vertexfragment|virtual|void|volatile|while)\b/,/\b(?:bool|double|dword|float|half|int|min(?:10float|12int|16(?:float|int|uint))|uint)(?:[1-4](?:x[1-4])?)?\b/],number:/(?:(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+)?|\b0x[\da-fA-F]+)[fFhHlLuU]?\b/,boolean:/\b(?:false|true)\b/}); Prism.languages.hoon={constant:/%(?:\.[ny]|[\w-]+)/,comment:{pattern:/::.*/,greedy:!0},"class-name":[{pattern:/@(?:[A-Za-z0-9-]*[A-Za-z0-9])?/},/\*/],function:/(?:\+[-+] {2})?(?:[a-z](?:[a-z0-9-]*[a-z0-9])?)/,string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},keyword:/:_|\.[\^\+\*=\?]|![><:\.=\?!]|=[>|:,\.\-\^<+;/~\*\?]|\?[>|:\.\-\^<\+&~=@!]|\|[\$_%:\.\-\^~\*=@\?]|\+[|\$\+\*]|:[_\-\^\+~\*]|%[_:\.\-\^\+~\*=]|\^[|:\.\-\+&~\*=\?]|\$[|_%:<>\-\^&~@=\?]|;[:<\+;\/~\*=]|~[>|\$_%<\+\/&=\?!]|--|==/}; !function(t){t.languages.http={"request-line":{pattern:/^(?:GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH|PRI|SEARCH)\s(?:https?:\/\/|\/)\S*\sHTTP\/[0-9.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[0-9.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[0-9.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[0-9.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},"header-name":{pattern:/^[\w-]+:(?=.)/m,alias:"keyword"}};var a,e,s,n=t.languages,r={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css},i={"application/json":!0,"application/xml":!0};for(var p in r)if(r[p]){a=a||{};var o=i[p]?(void 0,s=(e=p).replace(/^[a-z]+\//,""),"(?:"+e+"|\\w+/(?:[\\w.-]+\\+)+"+s+"(?![+\\w.-]))"):p;a[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+o+"(?:(?:\\r\\n?|\\n).+)*)(?:\\r?\\n|\\r){2}[\\s\\S]*","i"),lookbehind:!0,inside:r[p]}}a&&t.languages.insertBefore("http","header-name",a)}(Prism); Prism.languages.hpkp={directive:{pattern:/\b(?:(?:includeSubDomains|preload|strict)(?: |;)|pin-sha256="[a-zA-Z\d+=/]+"|(?:max-age|report-uri)=|report-to )/,alias:"keyword"},safe:{pattern:/\b\d{7,}\b/,alias:"selector"},unsafe:{pattern:/\b\d{1,6}\b/,alias:"function"}}; Prism.languages.hsts={directive:{pattern:/\b(?:max-age=|includeSubDomains|preload)/,alias:"keyword"},safe:{pattern:/\b\d{8,}\b/,alias:"selector"},unsafe:{pattern:/\b\d{1,7}\b/,alias:"function"}}; Prism.languages.ichigojam={comment:/(?:\B'|REM)(?:[^\n\r]*)/i,string:{pattern:/"(?:""|[!#$%&'()*,\/:;<=>?^\w +\-.])*"/i,greedy:!0},number:/\B#[0-9A-F]+|\B`[01]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,keyword:/\b(?:BEEP|BPS|CASE|CLEAR|CLK|CLO|CLP|CLS|CLT|CLV|CONT|COPY|ELSE|END|FILE|FILES|FOR|GOSUB|GSB|GOTO|IF|INPUT|KBD|LED|LET|LIST|LOAD|LOCATE|LRUN|NEW|NEXT|OUT|RIGHT|PLAY|POKE|PRINT|PWM|REM|RENUM|RESET|RETURN|RTN|RUN|SAVE|SCROLL|SLEEP|SRND|STEP|STOP|SUB|TEMPO|THEN|TO|UART|VIDEO|WAIT)(?:\$|\b)/i,function:/\b(?:ABS|ANA|ASC|BIN|BTN|DEC|END|FREE|HELP|HEX|I2CR|I2CW|IN|INKEY|LEN|LINE|PEEK|RND|SCR|SOUND|STR|TICK|USR|VER|VPEEK|ZER)(?:\$|\b)/i,label:/(?:\B@\S+)/i,operator:/<[=>]?|>=?|\|\||&&|[+\-*\/=|&^~!]|\b(?:AND|NOT|OR)\b/i,punctuation:/[\[,;:()\]]/}; Prism.languages.icon={comment:/#.*/,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n_]|\\.|_(?!\1)(?:\r\n|[\s\S]))*\1/,greedy:!0},number:/\b(?:\d+r[a-z\d]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b|\.\d+\b/i,"builtin-keyword":{pattern:/&(?:allocated|ascii|clock|collections|cset|current|date|dateline|digits|dump|e|error(?:number|text|value)?|errout|fail|features|file|host|input|lcase|letters|level|line|main|null|output|phi|pi|pos|progname|random|regions|source|storage|subject|time|trace|ucase|version)\b/,alias:"variable"},directive:{pattern:/\$\w+/,alias:"builtin"},keyword:/\b(?:break|by|case|create|default|do|else|end|every|fail|global|if|initial|invocable|link|local|next|not|of|procedure|record|repeat|return|static|suspend|then|to|until|while)\b/,function:/\b(?!\d)\w+(?=\s*[({]|\s*!\s*\[)/,operator:/[+-]:(?!=)|(?:[\/?@^%&]|\+\+?|--?|==?=?|~==?=?|\*\*?|\|\|\|?|<(?:->?|>?=?)(?::=)?|:(?:=:?)?|[!.\\|~]/,punctuation:/[\[\](){},;]/}; !function(e){function s(e,t){return t<=0?"[]":e.replace(//g,function(){return s(e,t-1)})}var t=/'[{}:=,](?:[^']|'')*'(?!')/,n={pattern:/''/,greedy:!0,alias:"operator"},r={pattern:t,greedy:!0,inside:{escape:n}},a=s("\\{(?:[^{}']|'(?![{},'])|''||)*\\}".replace(//g,function(){return t.source}),8),i={pattern:RegExp(a),inside:{message:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:null},"message-delimiter":{pattern:/./,alias:"punctuation"}}};e.languages["icu-message-format"]={argument:{pattern:RegExp(a),greedy:!0,inside:{content:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:{"argument-name":{pattern:/^(\s*)[^{}:=,\s]+/,lookbehind:!0},"choice-style":{pattern:/^(\s*,\s*choice\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{punctuation:/\|/,range:{pattern:/^(\s*)[+-]?(?:\d+(?:\.\d*)?|\u221e)\s*[<#\u2264]/,lookbehind:!0,inside:{operator:/[<#\u2264]/,number:/\S+/}},rest:null}},"plural-style":{pattern:/^(\s*,\s*(?:plural|selectordinal)\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{offset:/^offset:\s*\d+/,"nested-message":i,selector:{pattern:/=\d+|[^{}:=,\s]+/,inside:{keyword:/^(?:zero|one|two|few|many|other)$/}}}},"select-style":{pattern:/^(\s*,\s*select\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{"nested-message":i,selector:{pattern:/[^{}:=,\s]+/,inside:{keyword:/^other$/}}}},keyword:/\b(?:choice|plural|select|selectordinal)\b/,"arg-type":{pattern:/\b(?:number|date|time|spellout|ordinal|duration)\b/,alias:"keyword"},"arg-skeleton":{pattern:/(,\s*)::[^{}:=,\s]+/,lookbehind:!0},"arg-style":{pattern:/(,\s*)(?:short|medium|long|full|integer|currency|percent)(?=\s*$)/,lookbehind:!0},"arg-style-text":{pattern:RegExp("(^\\s*,\\s*(?=\\S))"+s("(?:[^{}']|'[^']*'|\\{(?:)?\\})+",8)+"$"),lookbehind:!0,alias:"string"},punctuation:/,/}},"argument-delimiter":{pattern:/./,alias:"operator"}}},escape:n,string:r},i.inside.message.inside=e.languages["icu-message-format"],e.languages["icu-message-format"].argument.inside.content.inside["choice-style"].inside.rest=e.languages["icu-message-format"]}(Prism); Prism.languages.idris=Prism.languages.extend("haskell",{comment:{pattern:/(?:(?:--|\|\|\|).*$|\{-[\s\S]*?-\})/m},keyword:/\b(?:Type|case|class|codata|constructor|corecord|data|do|dsl|else|export|if|implementation|implicit|import|impossible|in|infix|infixl|infixr|instance|interface|let|module|mutual|namespace|of|parameters|partial|postulate|private|proof|public|quoteGoal|record|rewrite|syntax|then|total|using|where|with)\b/,"import-statement":{pattern:/(^\s*)import\s+(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*/m,lookbehind:!0},builtin:void 0}),Prism.languages.idr=Prism.languages.idris; !function(n){n.languages.ignore={comment:/^#.*/m,entry:{pattern:/\S(?:.*(?:(?:\\ )|\S))?/,alias:"string",inside:{operator:/^!|\*\*?|\?/,regex:{pattern:/(^|[^\\])\[[^\[\]]*\]/,lookbehind:!0},punctuation:/\//}}},n.languages.gitignore=n.languages.ignore,n.languages.hgignore=n.languages.ignore,n.languages.npmignore=n.languages.ignore}(Prism); Prism.languages.inform7={string:{pattern:/"[^"]*"/,inside:{substitution:{pattern:/\[[^\[\]]+\]/,inside:{delimiter:{pattern:/\[|\]/,alias:"punctuation"}}}}},comment:{pattern:/\[[^\[\]]+\]/,greedy:!0},title:{pattern:/^[ \t]*(?:volume|book|part(?! of)|chapter|section|table)\b.+/im,alias:"important"},number:{pattern:/(^|[^-])(?:\b\d+(?:\.\d+)?(?:\^\d+)?(?:(?!\d)\w+)?|\b(?:one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve))\b(?!-)/i,lookbehind:!0},verb:{pattern:/(^|[^-])\b(?:applying to|are|attacking|answering|asking|be(?:ing)?|burning|buying|called|carries|carry(?! out)|carrying|climbing|closing|conceal(?:s|ing)?|consulting|contain(?:s|ing)?|cutting|drinking|dropping|eating|enclos(?:es?|ing)|entering|examining|exiting|getting|giving|going|ha(?:ve|s|ving)|hold(?:s|ing)?|impl(?:y|ies)|incorporat(?:es?|ing)|inserting|is|jumping|kissing|listening|locking|looking|mean(?:s|ing)?|opening|provid(?:es?|ing)|pulling|pushing|putting|relat(?:es?|ing)|removing|searching|see(?:s|ing)?|setting|showing|singing|sleeping|smelling|squeezing|switching|support(?:s|ing)?|swearing|taking|tasting|telling|thinking|throwing|touching|turning|tying|unlock(?:s|ing)?|var(?:y|ies|ying)|waiting|waking|waving|wear(?:s|ing)?)\b(?!-)/i,lookbehind:!0,alias:"operator"},keyword:{pattern:/(^|[^-])\b(?:after|before|carry out|check|continue the action|definition(?= *:)|do nothing|else|end (?:if|unless|the story)|every turn|if|include|instead(?: of)?|let|move|no|now|otherwise|repeat|report|resume the story|rule for|running through|say(?:ing)?|stop the action|test|try(?:ing)?|understand|unless|use|when|while|yes)\b(?!-)/i,lookbehind:!0},property:{pattern:/(^|[^-])\b(?:adjacent(?! to)|carried|closed|concealed|contained|dark|described|edible|empty|enclosed|enterable|even|female|fixed in place|full|handled|held|improper-named|incorporated|inedible|invisible|lighted|lit|lock(?:able|ed)|male|marked for listing|mentioned|negative|neuter|non-(?:empty|full|recurring)|odd|opaque|open(?:able)?|plural-named|portable|positive|privately-named|proper-named|provided|publically-named|pushable between rooms|recurring|related|rubbing|scenery|seen|singular-named|supported|swinging|switch(?:able|ed(?: on| off)?)|touch(?:able|ed)|transparent|unconcealed|undescribed|unlit|unlocked|unmarked for listing|unmentioned|unopenable|untouchable|unvisited|variable|visible|visited|wearable|worn)\b(?!-)/i,lookbehind:!0,alias:"symbol"},position:{pattern:/(^|[^-])\b(?:above|adjacent to|back side of|below|between|down|east|everywhere|front side|here|in|inside(?: from)?|north(?:east|west)?|nowhere|on(?: top of)?|other side|outside(?: from)?|parts? of|regionally in|south(?:east|west)?|through|up|west|within)\b(?!-)/i,lookbehind:!0,alias:"keyword"},type:{pattern:/(^|[^-])\b(?:actions?|activit(?:y|ies)|actors?|animals?|backdrops?|containers?|devices?|directions?|doors?|holders?|kinds?|lists?|m[ae]n|nobody|nothing|nouns?|numbers?|objects?|people|persons?|player(?:'s holdall)?|regions?|relations?|rooms?|rule(?:book)?s?|scenes?|someone|something|supporters?|tables?|texts?|things?|time|vehicles?|wom[ae]n)\b(?!-)/i,lookbehind:!0,alias:"variable"},punctuation:/[.,:;(){}]/},Prism.languages.inform7.string.inside.substitution.inside.rest=Prism.languages.inform7,Prism.languages.inform7.string.inside.substitution.inside.rest.text={pattern:/\S(?:\s*\S)*/,alias:"comment"}; Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},header:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}; Prism.languages.io={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0}],"triple-quoted-string":{pattern:/"""(?:\\[\s\S]|(?!""")[^\\])*"""/,greedy:!0,alias:"string"},string:{pattern:/"(?:\\.|[^\\\r\n"])*"/,greedy:!0},keyword:/\b(?:activate|activeCoroCount|asString|block|break|catch|clone|collectGarbage|compileString|continue|do|doFile|doMessage|doString|else|elseif|exit|for|foreach|forward|getSlot|getEnvironmentVariable|hasSlot|if|ifFalse|ifNil|ifNilEval|ifTrue|isActive|isNil|isResumable|list|message|method|parent|pass|pause|perform|performWithArgList|print|println|proto|raise|raiseResumable|removeSlot|resend|resume|schedulerSleepSeconds|self|sender|setSchedulerSleepSeconds|setSlot|shallowCopy|slotNames|super|system|then|thisBlock|thisContext|call|try|type|uniqueId|updateSlot|wait|while|write|yield)\b/,builtin:/\b(?:Array|AudioDevice|AudioMixer|Block|Box|Buffer|CFunction|CGI|Color|Curses|DBM|DNSResolver|DOConnection|DOProxy|DOServer|Date|Directory|Duration|DynLib|Error|Exception|FFT|File|Fnmatch|Font|Future|GL|GLE|GLScissor|GLU|GLUCylinder|GLUQuadric|GLUSphere|GLUT|Host|Image|Importer|LinkList|List|Lobby|Locals|MD5|MP3Decoder|MP3Encoder|Map|Message|Movie|Notification|Number|Object|OpenGL|Point|Protos|Regex|SGML|SGMLElement|SGMLParser|SQLite|Server|Sequence|ShowMessage|SleepyCat|SleepyCatCursor|Socket|SocketManager|Sound|Soup|Store|String|Tree|UDPSender|UPDReceiver|URL|User|Warning|WeakLink|Random|BigNum)\b/,boolean:/\b(?:true|false|nil)\b/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e-?\d+)?/i,operator:/[=!*/%+\-^&|]=|>>?=?|<+*\-%$|,#][.:]?|[?^]\.?|[;\[]:?|[~}"i][.:]|[ACeEIjLor]\.|(?:[_\/\\qsux]|_?\d):)/,alias:"keyword"},number:/\b_?(?:(?!\d:)\d+(?:\.\d+)?(?:(?:[ejpx]|ad|ar)_?\d+(?:\.\d+)?)*(?:b_?[\da-z]+(?:\.[\da-z]+)?)?|_\b(?!\.))/,adverb:{pattern:/[~}]|[\/\\]\.?|[bfM]\.|t[.:]/,alias:"builtin"},operator:/[=a][.:]|_\./,conjunction:{pattern:/&(?:\.:?|:)?|[.:@][.:]?|[!D][.:]|[;dHT]\.|`:?|[\^LS]:|"/,alias:"variable"},punctuation:/[()]/}; !function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",a={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{"class-name":[a,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); !function(a){var e=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;a.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:e,variable:/\$+(?:\w+\b|(?=\{))/i,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*[\w|]\|\s*)(?:null|false)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?[\w|]\|\s*)(?:null|false)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:null|false)\b/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:a.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];a.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:e,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),a.hooks.add("before-tokenize",function(e){if(/<\?/.test(e.code)){a.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/gi)}}),a.hooks.add("after-tokenize",function(e){a.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism); !function(p){var a=p.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:param|arg|arguments)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(a,"addSupport",{value:function(a,e){"string"==typeof a&&(a=[a]),a.forEach(function(a){!function(a,e){var n="doc-comment",t=p.languages[a];if(t){var r=t[n];if(!r){var o={"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}};r=(t=p.languages.insertBefore(a,"comment",o))[n]}if(r instanceof RegExp&&(r=t[n]={pattern:r}),Array.isArray(r))for(var i=0,s=r.length;i/g,function(){return"#\\s*\\w+(?:\\s*\\([^()]*\\))?"});a.languages.javadoc=a.languages.extend("javadoclike",{}),a.languages.insertBefore("javadoc","keyword",{reference:{pattern:RegExp("(@(?:exception|throws|see|link|linkplain|value)\\s+(?:\\*\\s*)?)(?:"+n+")"),lookbehind:!0,inside:{function:{pattern:/(#\s*)\w+(?=\s*\()/,lookbehind:!0},field:{pattern:/(#\s*)\w+/,lookbehind:!0},namespace:{pattern:/\b(?:[a-z]\w*\s*\.\s*)+/,inside:{punctuation:/\./}},"class-name":/\b[A-Z]\w*/,keyword:a.languages.java.keyword,punctuation:/[#()[\],.]/}},"class-name":{pattern:/(@param\s+)<[A-Z]\w*>/,lookbehind:!0,inside:{punctuation:/[.<>]/}},"code-section":[{pattern:/(\{@code\s+(?!\s))(?:[^\s{}]|\s+(?![\s}])|\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})+(?=\s*\})/,lookbehind:!0,inside:{code:{pattern:e,lookbehind:!0,inside:a.languages.java,alias:"language-java"}}},{pattern:/(<(code|pre|tt)>(?!)\s*)\S(?:\S|\s+\S)*?(?=\s*<\/\2>)/,lookbehind:!0,inside:{line:{pattern:e,lookbehind:!0,inside:{tag:a.languages.markup.tag,entity:a.languages.markup.entity,code:{pattern:/.+/,inside:a.languages.java,alias:"language-java"}}}}}],tag:a.languages.markup.tag,entity:a.languages.markup.entity}),a.languages.javadoclike.addSupport("java",a.languages.javadoc)}(Prism); Prism.languages.javastacktrace={summary:{pattern:/^[\t ]*(?:(?:Caused by:|Suppressed:|Exception in thread "[^"]*")[\t ]+)?[\w$.]+(?::.*)?$/m,inside:{keyword:{pattern:/^(\s*)(?:(?:Caused by|Suppressed)(?=:)|Exception in thread)/m,lookbehind:!0},string:{pattern:/^(\s*)"[^"]*"/,lookbehind:!0},exceptions:{pattern:/^(:?\s*)[\w$.]+(?=:|$)/,lookbehind:!0,inside:{"class-name":/[\w$]+(?=$|:)/,namespace:/[a-z]\w*/,punctuation:/[.:]/}},message:{pattern:/(:\s*)\S.*/,lookbehind:!0,alias:"string"},punctuation:/:/}},"stack-frame":{pattern:/^[\t ]*at (?:[\w$./]|@[\w$.+-]*\/)+(?:)?\([^()]*\)/m,inside:{keyword:{pattern:/^(\s*)at(?= )/,lookbehind:!0},source:[{pattern:/(\()\w+\.\w+:\d+(?=\))/,lookbehind:!0,inside:{file:/^\w+\.\w+/,punctuation:/:/,"line-number":{pattern:/\d+/,alias:"number"}}},{pattern:/(\()[^()]*(?=\))/,lookbehind:!0,inside:{keyword:/^(?:Unknown Source|Native Method)$/}}],"class-name":/[\w$]+(?=\.(?:|[\w$]+)\()/,function:/(?:|[\w$]+)(?=\()/,"class-loader":{pattern:/(\s)[a-z]\w*(?:\.[a-z]\w*)*(?=\/[\w@$.]*\/)/,lookbehind:!0,alias:"namespace",inside:{punctuation:/\./}},module:{pattern:/([\s/])[a-z]\w*(?:\.[a-z]\w*)*(?:@[\w$.+-]*)?(?=\/)/,lookbehind:!0,inside:{version:{pattern:/(@)[\s\S]+/,lookbehind:!0,alias:"number"},punctuation:/[@.]/}},namespace:{pattern:/(?:[a-z]\w*\.)+/,inside:{punctuation:/\./}},punctuation:/[()/.]/}},more:{pattern:/^[\t ]*\.{3} \d+ [a-z]+(?: [a-z]+)*/m,inside:{punctuation:/\.{3}/,number:/\d+/,keyword:/\b[a-z]+(?: [a-z]+)*\b/}}}; Prism.languages.jexl={string:/(["'])(?:\\[\s\S]|(?!\1)[^\\])*\1/,transform:{pattern:/(\|\s*)[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][\wа-яА-Я\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*/,alias:"function",lookbehind:!0},function:/[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][\wа-яА-Я\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*\s*(?=\()/,number:/\b\d+(?:\.\d+)?\b|\B\.\d+\b/,operator:/[<>!]=?|-|\+|&&|==|\|\|?|\/\/?|[?:*^%]/,boolean:/\b(?:true|false)\b/,keyword:/\bin\b/,punctuation:/[{}[\](),.]/}; Prism.languages.jolie=Prism.languages.extend("clike",{string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/\b(?:include|define|is_defined|undef|main|init|outputPort|inputPort|Location|Protocol|Interfaces|RequestResponse|OneWay|type|interface|extender|throws|cset|csets|forward|Aggregates|Redirects|embedded|courier|execution|sequential|concurrent|single|scope|install|throw|comp|cH|default|global|linkIn|linkOut|synchronized|this|new|for|if|else|while|in|Jolie|Java|Javascript|nullProcess|spawn|constants|with|provide|until|exit|foreach|instanceof|over|service)\b/,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?l?/i,operator:/-[-=>]?|\+[+=]?|<[<=]?|[>=*!]=?|&&|\|\||[:?\/%^]/,punctuation:/[,.]/,builtin:/\b(?:undefined|string|int|void|long|Byte|bool|double|float|char|any)\b/,symbol:/[|;@]/}),delete Prism.languages.jolie["class-name"],Prism.languages.insertBefore("jolie","keyword",{function:{pattern:/((?:\b(?:outputPort|inputPort|in|service|courier)\b|@)\s*)\w+/,lookbehind:!0},aggregates:{pattern:/(\bAggregates\s*:\s*)(?:\w+(?:\s+with\s+\w+)?\s*,\s*)*\w+(?:\s+with\s+\w+)?/,lookbehind:!0,inside:{"with-extension":{pattern:/\bwith\s+\w+/,inside:{keyword:/\bwith\b/}},function:{pattern:/\w+/},punctuation:{pattern:/,/}}},redirects:{pattern:/(\bRedirects\s*:\s*)(?:\w+\s*=>\s*\w+\s*,\s*)*(?:\w+\s*=>\s*\w+)/,lookbehind:!0,inside:{punctuation:{pattern:/,/},function:{pattern:/\w+/},symbol:{pattern:/=>/}}}}); !function(e){var n="\\\\\\((?:[^()]|\\([^()]*\\))*\\)",t=RegExp('"(?:[^"\r\n\\\\]|\\\\[^\r\n(]|__)*"'.replace(/__/g,function(){return n})),i={interpolation:{pattern:RegExp("((?:^|[^\\\\])(?:\\\\{2})*)"+n),lookbehind:!0,inside:{content:{pattern:/^(\\\()[\s\S]+(?=\)$)/,lookbehind:!0,inside:null},punctuation:/^\\\(|\)$/}}},a=e.languages.jq={comment:/#.*/,property:{pattern:RegExp(t.source+"(?=\\s*:(?!:))"),greedy:!0,inside:i},string:{pattern:t,greedy:!0,inside:i},function:{pattern:/(\bdef\s+)[a-z_]\w+/i,lookbehind:!0},variable:/\B\$\w+/,"property-literal":{pattern:/\b[a-z_]\w*(?=\s*:(?!:))/i,alias:"property"},keyword:/\b(?:as|break|catch|def|elif|else|end|foreach|if|import|include|label|module|modulemeta|null|reduce|then|try|while)\b/,boolean:/\b(?:true|false)\b/,number:/(?:\b\d+\.|\B\.)?\b\d+(?:[eE][+-]?\d+)?\b/,operator:[{pattern:/\|=?/,alias:"pipe"},/\.\.|[!=<>]?=|\?\/\/|\/\/=?|[-+*/%]=?|[<>?]|\b(?:and|or|not)\b/],"c-style-function":{pattern:/\b[a-z_]\w*(?=\s*\()/i,alias:"function"},punctuation:/::|[()\[\]{},:;]|\.(?=\s*[\[\w$])/,dot:{pattern:/\./,alias:"important"}};i.interpolation.inside.content.inside=a}(Prism); !function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|as|declare|implements|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter;var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism); !function(e){var a=e.languages.javascript,n="\\{(?:[^{}]|\\{(?:[^{}]|\\{[^{}]*\\})*\\})+\\}",t="(@(?:param|arg|argument|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(t+"(?:(?!\\s)[$\\w\\xA0-\\uFFFF.])+(?=\\s|$)"),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(t+"\\[(?:(?!\\s)[$\\w\\xA0-\\uFFFF.])+(?:=[^[\\]]+)?\\](?=\\s|$)"),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:a,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp("(@(?:augments|extends|class|interface|memberof!?|template|this|typedef)\\s+(?:\\s+)?)[A-Z]\\w*(?:\\.[A-Z]\\w*)*".replace(//g,function(){return n})),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{string:a.string,number:a.number,boolean:a.boolean,keyword:e.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:a,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(Prism); !function(a){function e(a,e){return RegExp(a.replace(//g,function(){return"(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*"}),e)}a.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+a.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),a.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+a.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),a.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:(?:Uint|Int)(?:8|16|32)|Uint8Clamped|Float(?:32|64))?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|(?:Weak)?(?:Set|Map)|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),a.languages.insertBefore("javascript","keyword",{imports:{pattern:e("(\\bimport\\b\\s*)(?:(?:\\s*,\\s*(?:\\*\\s*as\\s+|\\{[^{}]*\\}))?|\\*\\s*as\\s+|\\{[^{}]*\\})(?=\\s*\\bfrom\\b)"),lookbehind:!0,inside:a.languages.javascript},exports:{pattern:e("(\\bexport\\b\\s*)(?:\\*(?:\\s*as\\s+)?(?=\\s*\\bfrom\\b)|\\{[^{}]*\\})"),lookbehind:!0,inside:a.languages.javascript}}),a.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|for|finally|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),a.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),a.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:e("(\\.\\s*)#?"),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|location|navigator|performance|(?:local|session)Storage|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var t=["function","function-variable","method","method-variable","property-access"],r=0;r|.*(?:node_modules|\(\)|\(|$|\(internal\/|\(node\.js)).*/m,alias:"comment"},filename:{pattern:/(\bat\s+(?!\s)|\()(?:[a-zA-Z]:)?[^():]+(?=:)/,lookbehind:!0,alias:"url"},function:{pattern:/(at\s+(?:new\s+)?)(?!\s)[_$a-zA-Z\xA0-\uFFFF<][.$\w\xA0-\uFFFF<>]*/,lookbehind:!0,inside:{punctuation:/\./}},punctuation:/[()]/,keyword:/\b(?:at|new)\b/,alias:{pattern:/\[(?:as\s+)?(?!\s)[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\]/,alias:"variable"},"line-number":{pattern:/:[0-9]+(?::[0-9]+)?\b/,alias:"number",inside:{punctuation:/:/}}}}}; !function(u){var e=u.languages.javascript["template-string"],n=e.pattern.source,a=e.inside.interpolation,i=a.inside["interpolation-punctuation"],r=a.pattern.source;function t(e,t){if(u.languages[e])return{pattern:RegExp("((?:"+t+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:e}}}}function s(e,t,n){var r={code:e,grammar:t,language:n};return u.hooks.run("before-tokenize",r),r.tokens=u.tokenize(r.code,r.grammar),u.hooks.run("after-tokenize",r),r.tokens}function d(e){var t={};t["interpolation-punctuation"]=i;var n=u.tokenize(e,t);if(3===n.length){var r=[1,1];r.push.apply(r,s(n[1],u.languages.javascript,"javascript")),n.splice.apply(n,r)}return new u.Token("interpolation",n,a.alias,e)}function c(a,e,i){var t=u.tokenize(a,{interpolation:{pattern:RegExp(r),lookbehind:!0}}),f=0,y={},n=s(t.map(function(e){if("string"==typeof e)return e;for(var t,n=e.content;-1!==a.indexOf((r=f++,t="___"+i.toUpperCase()+"_"+r+"___")););return y[t]=n,t;var r}).join(""),e,i),v=Object.keys(y);return f=0,function e(t){for(var n=0;n=v.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=v[f],i="string"==typeof r?r:r.content,s=i.indexOf(a);if(-1!==s){++f;var o=i.substring(0,s),p=d(y[a]),l=i.substring(s+a.length),g=[];if(o&&g.push(o),g.push(p),l){var u=[l];e(u),g.push.apply(g,u)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(g)),n+=g.length-1):r.content=g}}else{var c=r.content;Array.isArray(c)?e(c):e([c])}}}(n),new u.Token(i,n,"language-"+i,a)}u.languages.javascript["template-string"]=[t("css","\\b(?:styled(?:\\([^)]*\\))?(?:\\s*\\.\\s*\\w+(?:\\([^)]*\\))*)*|css(?:\\s*\\.\\s*(?:global|resolve))?|createGlobalStyle|keyframes)"),t("html","\\bhtml|\\.\\s*(?:inner|outer)HTML\\s*\\+?="),t("svg","\\bsvg"),t("markdown","\\b(?:md|markdown)"),t("graphql","\\b(?:gql|graphql(?:\\s*\\.\\s*experimental)?)"),t("sql","\\bsql"),e].filter(Boolean);var o={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}u.hooks.add("after-tokenize",function(e){e.language in o&&!function e(t){for(var n=0,r=t.length;n]?|<(?:<=?|[=:|])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥'√∛]/,punctuation:/::?|[{}[\]();,.?]/,constant:/\b(?:(?:NaN|Inf)(?:16|32|64)?|im|pi)\b|[πℯ]/}; Prism.languages.keyman={comment:/\bc\s.*/i,function:/\[\s*(?:(?:CTRL|SHIFT|ALT|LCTRL|RCTRL|LALT|RALT|CAPS|NCAPS)\s+)*(?:[TKU]_[\w?]+|".+?"|'.+?')\s*\]/i,string:/("|').*?\1/,bold:[/&(?:baselayout|bitmap|capsononly|capsalwaysoff|shiftfreescaps|copyright|ethnologuecode|hotkey|includecodes|keyboardversion|kmw_embedcss|kmw_embedjs|kmw_helpfile|kmw_helptext|kmw_rtl|language|layer|layoutfile|message|mnemoniclayout|name|oldcharposmatching|platform|targets|version|visualkeyboard|windowslanguages)\b/i,/\b(?:bitmap|bitmaps|caps on only|caps always off|shift frees caps|copyright|hotkey|language|layout|message|name|version)\b/i],keyword:/\b(?:any|baselayout|beep|call|context|deadkey|dk|if|index|layer|notany|nul|outs|platform|return|reset|save|set|store|use)\b/i,atrule:/\b(?:ansi|begin|unicode|group|using keys|match|nomatch)\b/i,number:/\b(?:U\+[\dA-F]+|d\d+|x[\da-f]+|\d+)\b/i,operator:/[+>\\,()]/,tag:/\$(?:keyman|kmfl|weaver|keymanweb|keymanonly):/i}; !function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"],e.languages.insertBefore("kotlin","string",{"raw-string":{pattern:/("""|''')[\s\S]*?\1/,alias:"string"}}),e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}});var n=[{pattern:/\$\{[^}]+\}/,inside:{delimiter:{pattern:/^\$\{|\}$/,alias:"variable"},rest:e.languages.kotlin}},{pattern:/\$\w+/,alias:"variable"}];e.languages.kotlin.string.inside=e.languages.kotlin["raw-string"].inside={interpolation:n},e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(Prism); !function(n){function o(n,o){return RegExp(n.replace(//g,"\\s\\x00-\\x1f\\x22-\\x2f\\x3a-\\x3f\\x5b-\\x5e\\x60\\x7b-\\x7e"),o)}n.languages.kumir={comment:{pattern:/\|.*/},prolog:{pattern:/#.*/,greedy:!0},string:{pattern:/"[^\n\r"]*"|'[^\n\r']*'/,greedy:!0},boolean:{pattern:o("(^|[])(?:да|нет)(?=[]|$)"),lookbehind:!0},"operator-word":{pattern:o("(^|[])(?:и|или|не)(?=[]|$)"),lookbehind:!0,alias:"keyword"},"system-variable":{pattern:o("(^|[])знач(?=[]|$)"),lookbehind:!0,alias:"keyword"},type:[{pattern:o("(^|[])(?:вещ|лит|лог|сим|цел)(?:\\x20*таб)?(?=[]|$)"),lookbehind:!0,alias:"builtin"},{pattern:o("(^|[])(?:компл|сканкод|файл|цвет)(?=[]|$)"),lookbehind:!0,alias:"important"}],keyword:{pattern:o("(^|[])(?:алг|арг(?:\\x20*рез)?|ввод|ВКЛЮЧИТЬ|вс[её]|выбор|вывод|выход|дано|для|до|дс|если|иначе|исп|использовать|кон(?:(?:\\x20+|_)исп)?|кц(?:(?:\\x20+|_)при)?|надо|нач|нс|нц|от|пауза|пока|при|раза?|рез|стоп|таб|то|утв|шаг)(?=[]|$)"),lookbehind:!0},name:{pattern:o("(^|[])[^\\d][^]*(?:\\x20+[^]+)*(?=[]|$)"),lookbehind:!0},number:{pattern:o("(^|[])(?:\\B\\$[\\da-f]+\\b|(?:\\b\\d+(?:\\.\\d*)?|\\B\\.\\d+)(?:e[+-]?\\d+)?)(?=[]|$)","i"),lookbehind:!0},punctuation:/:=|[(),:;\[\]]/,"operator-char":{pattern:/\*\*?|<[=>]?|>=?|[-+/=]/,alias:"operator"}},n.languages.kum=n.languages.kumir}(Prism); !function(a){var e=/\\(?:[^a-z()[\]]|[a-z*]+)/i,n={"equation-command":{pattern:e,alias:"regex"}};a.languages.latex={comment:/%.*/m,cdata:{pattern:/(\\begin\{((?:verbatim|lstlisting)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0},equation:[{pattern:/\$\$(?:\\[\s\S]|[^\\$])+\$\$|\$(?:\\[\s\S]|[^\\$])+\$|\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]/,inside:n,alias:"string"},{pattern:/(\\begin\{((?:equation|math|eqnarray|align|multline|gather)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0,inside:n,alias:"string"}],keyword:{pattern:/(\\(?:begin|end|ref|cite|label|usepackage|documentclass)(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0},url:{pattern:/(\\url\{)[^}]+(?=\})/,lookbehind:!0},headline:{pattern:/(\\(?:part|chapter|section|subsection|frametitle|subsubsection|paragraph|subparagraph|subsubparagraph|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0,alias:"class-name"},function:{pattern:e,alias:"selector"},punctuation:/[[\]{}&]/},a.languages.tex=a.languages.latex,a.languages.context=a.languages.latex}(Prism); !function(t){t.languages.latte={comment:/^\{\*[\s\S]*/,ld:{pattern:/^\{(?:[=_]|\/?(?!\d|\w+\()\w+)?/,inside:{punctuation:/^\{\/?/,tag:{pattern:/.+/,alias:"important"}}},rd:{pattern:/\}$/,inside:{punctuation:/.+/}},php:{pattern:/\S(?:[\s\S]*\S)?/,alias:"language-php",inside:t.languages.php}};var e=t.languages.extend("markup",{});t.languages.insertBefore("inside","attr-value",{"n-attr":{pattern:/n:[\w-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+))?/,inside:{"attr-name":{pattern:/^[^\s=]+/,alias:"important"},"attr-value":{pattern:/=[\s\S]+/,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}],php:{pattern:/\S(?:[\s\S]*\S)?/,inside:t.languages.php}}}}}},e.tag),t.hooks.add("before-tokenize",function(a){if("latte"===a.language){t.languages["markup-templating"].buildPlaceholders(a,"latte",/\{\*[\s\S]*?\*\}|\{[^'"\s{}*](?:[^"'/{}]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|\/\*(?:[^*]|\*(?!\/))*\*\/)*?\}/g),a.grammar=e}}),t.hooks.add("after-tokenize",function(a){t.languages["markup-templating"].tokenizePlaceholders(a,"latte")})}(Prism); Prism.languages.less=Prism.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,operator:/[+\-*\/]/}),Prism.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}); Prism.languages.scheme={comment:/;.*|#;\s*(?:\((?:[^()]|\([^()]*\))*\)|\[(?:[^\[\]]|\[[^\[\]]*\])*\])|#\|(?:[^#|]|#(?!\|)|\|(?!#)|#\|(?:[^#|]|#(?!\|)|\|(?!#))*\|#)*\|#/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},symbol:{pattern:/'[^()\[\]#'\s]+/,greedy:!0},character:{pattern:/#\\(?:[ux][a-fA-F\d]+\b|[-a-zA-Z]+\b|[\uD800-\uDBFF][\uDC00-\uDFFF]|\S)/,greedy:!0,alias:"string"},"lambda-parameter":[{pattern:/((?:^|[^'`#])[(\[]lambda\s+)(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)/,lookbehind:!0},{pattern:/((?:^|[^'`#])[(\[]lambda\s+[(\[])[^()\[\]']+/,lookbehind:!0}],keyword:{pattern:/((?:^|[^'`#])[(\[])(?:begin|case(?:-lambda)?|cond(?:-expand)?|define(?:-library|-macro|-record-type|-syntax|-values)?|defmacro|delay(?:-force)?|do|else|export|except|guard|if|import|include(?:-ci|-library-declarations)?|lambda|let(?:rec)?(?:-syntax|-values|\*)?|let\*-values|only|parameterize|prefix|(?:quasi-?)?quote|rename|set!|syntax-(?:case|rules)|unless|unquote(?:-splicing)?|when)(?=[()\[\]\s]|$)/,lookbehind:!0},builtin:{pattern:/((?:^|[^'`#])[(\[])(?:abs|and|append|apply|assoc|ass[qv]|binary-port\?|boolean=?\?|bytevector(?:-append|-copy|-copy!|-length|-u8-ref|-u8-set!|\?)?|caar|cadr|call-with-(?:current-continuation|port|values)|call\/cc|car|cdar|cddr|cdr|ceiling|char(?:->integer|-ready\?|\?|<\?|<=\?|=\?|>\?|>=\?)|close-(?:input-port|output-port|port)|complex\?|cons|current-(?:error|input|output)-port|denominator|dynamic-wind|eof-object\??|eq\?|equal\?|eqv\?|error|error-object(?:-irritants|-message|\?)|eval|even\?|exact(?:-integer-sqrt|-integer\?|\?)?|expt|features|file-error\?|floor(?:-quotient|-remainder|\/)?|flush-output-port|for-each|gcd|get-output-(?:bytevector|string)|inexact\??|input-port(?:-open\?|\?)|integer(?:->char|\?)|lcm|length|list(?:->string|->vector|-copy|-ref|-set!|-tail|\?)?|make-(?:bytevector|list|parameter|string|vector)|map|max|member|memq|memv|min|modulo|negative\?|newline|not|null\?|number(?:->string|\?)|numerator|odd\?|open-(?:input|output)-(?:bytevector|string)|or|output-port(?:-open\?|\?)|pair\?|peek-char|peek-u8|port\?|positive\?|procedure\?|quotient|raise|raise-continuable|rational\?|rationalize|read-(?:bytevector|bytevector!|char|error\?|line|string|u8)|real\?|remainder|reverse|round|set-c[ad]r!|square|string(?:->list|->number|->symbol|->utf8|->vector|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?|<\?|<=\?|=\?|>\?|>=\?)?|substring|symbol(?:->string|\?|=\?)|syntax-error|textual-port\?|truncate(?:-quotient|-remainder|\/)?|u8-ready\?|utf8->string|values|vector(?:->list|->string|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?)?|with-exception-handler|write-(?:bytevector|char|string|u8)|zero\?)(?=[()\[\]\s]|$)/,lookbehind:!0},operator:{pattern:/((?:^|[^'`#])[(\[])(?:[-+*%/]|[<>]=?|=>?)(?=[()\[\]\s]|$)/,lookbehind:!0},number:{pattern:RegExp(function(r){for(var e in r)r[e]=r[e].replace(/<[\w\s]+>/g,function(e){return"(?:"+r[e].trim()+")"});return r[e]}({"":"\\d+(?:/\\d+)|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?","":"[+-]?|[+-](?:inf|nan)\\.0","":"[+-](?:|(?:inf|nan)\\.0)?i","":"(?:@|)?|","":"(?:#d(?:#[ei])?|#[ei](?:#d)?)?","":"[0-9a-f]+(?:/[0-9a-f]+)?","":"[+-]?|[+-](?:inf|nan)\\.0","":"[+-](?:|(?:inf|nan)\\.0)?i","":"(?:@|)?|","":"#[box](?:#[ei])?|(?:#[ei])?#[box]","":"(^|[()\\[\\]\\s])(?:|)(?=[()\\[\\]\\s]|$)"}),"i"),lookbehind:!0},boolean:{pattern:/(^|[()\[\]\s])#(?:[ft]|false|true)(?=[()\[\]\s]|$)/,lookbehind:!0},function:{pattern:/((?:^|[^'`#])[(\[])(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)(?=[()\[\]\s]|$)/,lookbehind:!0},identifier:{pattern:/(^|[()\[\]\s])\|(?:[^\\|]|\\.)*\|(?=[()\[\]\s]|$)/,lookbehind:!0,greedy:!0},punctuation:/[()\[\]']/}; !function(e){for(var n='\\((?:[^();"#\\\\]|\\\\[^]|;.*(?!.)|"(?:[^"\\\\]|\\\\.)*"|#(?:\\{(?:(?!#\\})[^])*#\\}|[^{])|)*\\)',i=0;i<5;i++)n=n.replace(//g,function(){return n});n=n.replace(//g,"[^\\s\\S]");var d=e.languages.lilypond={comment:/%(?:(?!\{).*|\{[\s\S]*?%\})/,"embedded-scheme":{pattern:RegExp('(^|[=\\s])#(?:"(?:[^"\\\\]|\\\\.)*"|[^\\s()"]*(?:[^\\s()]|))'.replace(//g,function(){return n}),"m"),lookbehind:!0,greedy:!0,inside:{scheme:{pattern:/^(#)[\s\S]+$/,lookbehind:!0,alias:"language-scheme",inside:{"embedded-lilypond":{pattern:/#\{[\s\S]*?#\}/,greedy:!0,inside:{punctuation:/^#\{|#\}$/,lilypond:{pattern:/[\s\S]+/,alias:"language-lilypond",inside:null}}},rest:e.languages.scheme}},punctuation:/#/}},string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},"class-name":{pattern:/(\\new\s+)[\w-]+/,lookbehind:!0},keyword:{pattern:/\\[a-z][-\w]*/i,inside:{punctuation:/^\\/}},operator:/[=|]|<<|>>/,punctuation:{pattern:/(^|[a-z\d])(?:'+|,+|[_^]?-[_^]?(?:[-+^!>._]|(?=\d))|[_^]\.?|[.!])|[{}()[\]<>^~]|\\[()[\]<>\\!]|--|__/,lookbehind:!0},number:/\b\d+(?:\/\d+)?\b/};d["embedded-scheme"].inside.scheme.inside["embedded-lilypond"].inside.lilypond.inside=d,e.languages.ly=d}(Prism); Prism.languages.liquid={comment:{pattern:/(^\{%\s*comment\s*%\})[\s\S]+(?=\{%\s*endcomment\s*%\}$)/,lookbehind:!0},delimiter:{pattern:/^\{(?:\{\{|[%\{])-?|-?(?:\}\}|[%\}])\}$/,alias:"punctuation"},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},keyword:/\b(?:as|assign|break|continue|cycle|decrement|echo|else|elsif|(?:end)?(?:capture|case|comment|for|form|if|paginate|style|raw|tablerow|unless)|in|include|increment|limit|liquid|offset|range|render|reversed|section|when|with)\b/,object:/\b(?:address|all_country_option_tags|article|block|blog|cart|checkout|collection|color|comment|country|country_option_tags|currency|current_page|current_tags|customer|customer_address|date|discount_allocation|discount_application|external_video|filter|filter_value|font|forloop|form|fulfillment|generic_file|gift_card|group|handle|image|line_item|link|linklist|localization|location|measurement|media|metafield|model|model_source|order|page|page_description|page_image|page_title|paginate|part|policy|product|product_option|recommendations|request|robots|routes|rule|script|search|section|selling_plan|selling_plan_allocation|selling_plan_group|shipping_method|shop|shop_locale|sitemap|store_availability|tablerow|tax_line|template|theme|transaction|unit_price_measurement|user_agent|variant|video|video_source)\b/,function:[{pattern:/(\|\s*)\w+/,lookbehind:!0,alias:"filter"},{pattern:/(\.\s*)(?:first|last|size)/,lookbehind:!0}],boolean:/\b(?:true|false|nil)\b/,range:{pattern:/\.\./,alias:"operator"},number:/\b\d+(?:\.\d+)?\b/,operator:/[!=]=|<>|[<>]=?|[|?:=-]|\b(?:and|or|contains(?=\s))\b/,punctuation:/[.,\[\]()]/,empty:{pattern:/\bempty\b/,alias:"keyword"}},Prism.hooks.add("before-tokenize",function(e){var a=!1;Prism.languages["markup-templating"].buildPlaceholders(e,"liquid",/\{%\s*comment\s*%\}[\s\S]*?\{%\s*endcomment\s*%\}|\{(?:%[\s\S]*?%|\{\{[\s\S]*?\}\}|\{[\s\S]*?\})\}/g,function(e){var t=/^\{%-?\s*(\w+)/.exec(e);if(t){var n=t[1];if("raw"===n&&!a)return a=!0;if("endraw"===n)return!(a=!1)}return!a})}),Prism.hooks.add("after-tokenize",function(e){Prism.languages["markup-templating"].tokenizePlaceholders(e,"liquid")}); !function(e){function n(e){return RegExp("(\\()"+e+"(?=[\\s\\)])")}function a(e){return RegExp("([\\s([])"+e+"(?=[\\s)])")}var t="[-+*/_~!@$%^=<>{}\\w]+",r="(\\()",s="(?=\\))",i="(?=\\s)",o={heading:{pattern:/;;;.*/,alias:["comment","title"]},comment:/;.*/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0,inside:{argument:/[-A-Z]+(?=[.,\s])/,symbol:RegExp("`"+t+"'")}},"quoted-symbol":{pattern:RegExp("#?'"+t),alias:["variable","symbol"]},"lisp-property":{pattern:RegExp(":"+t),alias:"property"},splice:{pattern:RegExp(",@?"+t),alias:["symbol","variable"]},keyword:[{pattern:RegExp(r+"(?:(?:lexical-)?let\\*?|(?:cl-)?letf|if|when|while|unless|cons|cl-loop|and|or|not|cond|setq|error|message|null|require|provide|use-package)"+i),lookbehind:!0},{pattern:RegExp(r+"(?:for|do|collect|return|finally|append|concat|in|by)"+i),lookbehind:!0}],declare:{pattern:n("declare"),lookbehind:!0,alias:"keyword"},interactive:{pattern:n("interactive"),lookbehind:!0,alias:"keyword"},boolean:{pattern:a("(?:t|nil)"),lookbehind:!0},number:{pattern:a("[-+]?\\d+(?:\\.\\d*)?"),lookbehind:!0},defvar:{pattern:RegExp(r+"def(?:var|const|custom|group)\\s+"+t),lookbehind:!0,inside:{keyword:/^def[a-z]+/,variable:RegExp(t)}},defun:{pattern:RegExp(r+"(?:cl-)?(?:defun\\*?|defmacro)\\s+"+t+"\\s+\\([\\s\\S]*?\\)"),lookbehind:!0,inside:{keyword:/^(?:cl-)?def\S+/,arguments:null,function:{pattern:RegExp("(^\\s)"+t),lookbehind:!0},punctuation:/[()]/}},lambda:{pattern:RegExp(r+"lambda\\s+\\(\\s*(?:&?"+t+"(?:\\s+&?"+t+")*\\s*)?\\)"),lookbehind:!0,inside:{keyword:/^lambda/,arguments:null,punctuation:/[()]/}},car:{pattern:RegExp(r+t),lookbehind:!0},punctuation:[/(?:['`,]?\(|[)\[\]])/,{pattern:/(\s)\.(?=\s)/,lookbehind:!0}]},l={"lisp-marker":RegExp("&[-+*/_~!@$%^=<>{}\\w]+"),rest:{argument:{pattern:RegExp(t),alias:"variable"},varform:{pattern:RegExp(r+t+"\\s+\\S[\\s\\S]*"+s),lookbehind:!0,inside:{string:o.string,boolean:o.boolean,number:o.number,symbol:o.symbol,punctuation:/[()]/}}}},p="\\S+(?:\\s+\\S+)*",d={pattern:RegExp(r+"[\\s\\S]*"+s),lookbehind:!0,inside:{"rest-vars":{pattern:RegExp("&(?:rest|body)\\s+"+p),inside:l},"other-marker-vars":{pattern:RegExp("&(?:optional|aux)\\s+"+p),inside:l},keys:{pattern:RegExp("&key\\s+"+p+"(?:\\s+&allow-other-keys)?"),inside:l},argument:{pattern:RegExp(t),alias:"variable"},punctuation:/[()]/}};o.lambda.inside.arguments=d,o.defun.inside.arguments=e.util.clone(d),o.defun.inside.arguments.inside.sublist=d,e.languages.lisp=o,e.languages.elisp=o,e.languages.emacs=o,e.languages["emacs-lisp"]=o}(Prism); Prism.languages.livescript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0}],"interpolated-string":{pattern:/(^|[^"])("""|")(?:\\[\s\S]|(?!\2)[^\\])*\2(?!")/,lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(^|[^\\])#[a-z_](?:-?[a-z]|[\d_])*/m,lookbehind:!0},interpolation:{pattern:/(^|[^\\])#\{[^}]+\}/m,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^#\{|\}$/,alias:"variable"}}},string:/[\s\S]+/}},string:[{pattern:/('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/<\[[\s\S]*?\]>/,greedy:!0},/\\[^\s,;\])}]+/],regex:[{pattern:/\/\/(?:\[[^\r\n\]]*\]|\\.|(?!\/\/)[^\\\[])+\/\/[gimyu]{0,5}/,greedy:!0,inside:{comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0}}},{pattern:/\/(?:\[[^\r\n\]]*\]|\\.|[^/\\\r\n\[])+\/[gimyu]{0,5}/,greedy:!0}],keyword:{pattern:/(^|(?!-).)\b(?:break|case|catch|class|const|continue|default|do|else|extends|fallthrough|finally|for(?: ever)?|function|if|implements|it|let|loop|new|null|otherwise|own|return|super|switch|that|then|this|throw|try|unless|until|var|void|when|while|yield)(?!-)\b/m,lookbehind:!0},"keyword-operator":{pattern:/(^|[^-])\b(?:(?:delete|require|typeof)!|(?:and|by|delete|export|from|import(?: all)?|in|instanceof|is(?:nt| not)?|not|of|or|til|to|typeof|with|xor)(?!-)\b)/m,lookbehind:!0,alias:"operator"},boolean:{pattern:/(^|[^-])\b(?:false|no|off|on|true|yes)(?!-)\b/m,lookbehind:!0},argument:{pattern:/(^|(?!\.&\.)[^&])&(?!&)\d*/m,lookbehind:!0,alias:"variable"},number:/\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,identifier:/[a-z_](?:-?[a-z]|[\d_])*/i,operator:[{pattern:/( )\.(?= )/,lookbehind:!0},/\.(?:[=~]|\.\.?)|\.(?:[&|^]|<<|>>>?)\.|:(?:=|:=?)|&&|\|[|>]|<(?:<[>=?]?|-(?:->?|>)?|\+\+?|@@?|%%?|\*\*?|!(?:~?=|--?>|~?~>)?|~(?:~?>|=)?|==?|\^\^?|[\/?]/],punctuation:/[(){}\[\]|.,:;`]/},Prism.languages.livescript["interpolated-string"].inside.interpolation.inside.rest=Prism.languages.livescript; Prism.languages.llvm={comment:/;.*/,string:{pattern:/"[^"]*"/,greedy:!0},boolean:/\b(?:true|false)\b/,variable:/[%@!#](?:(?!\d)(?:[-$.\w]|\\[a-f\d]{2})+|\d+)/i,label:/(?!\d)(?:[-$.\w]|\\[a-f\d]{2})+:/i,type:{pattern:/\b(?:double|float|fp128|half|i[1-9]\d*|label|metadata|ppc_fp128|token|void|x86_fp80|x86_mmx)\b/,alias:"class-name"},keyword:/\b[a-z_][a-z_0-9]*\b/,number:/[+-]?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b|\b0x[\dA-Fa-f]+\b|\b0xK[\dA-Fa-f]{20}\b|\b0x[ML][\dA-Fa-f]{32}\b|\b0xH[\dA-Fa-f]{4}\b/,punctuation:/[{}[\];(),.!*=<>]/}; Prism.languages.log={string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?![st] | \w)(?:[^'\\\r\n]|\\.)*'/,greedy:!0},level:[{pattern:/\b(?:ALERT|CRIT|CRITICAL|EMERG|EMERGENCY|ERR|ERROR|FAILURE|FATAL|SEVERE)\b/,alias:["error","important"]},{pattern:/\b(?:WARN|WARNING|WRN)\b/,alias:["warning","important"]},{pattern:/\b(?:DISPLAY|INF|INFO|NOTICE|STATUS)\b/,alias:["info","keyword"]},{pattern:/\b(?:DBG|DEBUG|FINE)\b/,alias:["debug","keyword"]},{pattern:/\b(?:FINER|FINEST|TRACE|TRC|VERBOSE|VRB)\b/,alias:["trace","comment"]}],property:{pattern:/((?:^|[\]|])[ \t]*)[a-z_](?:[\w-]|\b\/\b)*(?:[. ]\(?\w(?:[\w-]|\b\/\b)*\)?)*:(?=\s)/im,lookbehind:!0},separator:{pattern:/(^|[^-+])-{3,}|={3,}|\*{3,}|- - /m,lookbehind:!0,alias:"comment"},url:/\b(?:https?|ftp|file):\/\/[^\s|,;'"]*[^\s|,;'">.]/,email:{pattern:/(^|\s)[-\w+.]+@[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+(?=\s)/,lookbehind:!0,alias:"url"},"ip-address":{pattern:/\b(?:\d{1,3}(?:\.\d{1,3}){3})\b/i,alias:"constant"},"mac-address":{pattern:/\b[a-f0-9]{2}(?::[a-f0-9]{2}){5}\b/i,alias:"constant"},domain:{pattern:/(^|\s)[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*\.[a-z][a-z0-9-]+(?=\s)/,lookbehind:!0,alias:"constant"},uuid:{pattern:/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i,alias:"constant"},hash:{pattern:/\b(?:[a-f0-9]{32}){1,2}\b/i,alias:"constant"},"file-path":{pattern:/\b[a-z]:[\\/][^\s|,;:(){}\[\]"']+|(^|[\s:\[\](>|])\.{0,2}\/\w[^\s|,;:(){}\[\]"']*/i,lookbehind:!0,greedy:!0,alias:"string"},date:{pattern:RegExp("\\b\\d{4}[-/]\\d{2}[-/]\\d{2}(?:T(?=\\d{1,2}:)|(?=\\s\\d{1,2}:))|\\b\\d{1,4}[-/ ](?:\\d{1,2}|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[-/ ]\\d{2,4}T?\\b|\\b(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)(?:\\s{1,2}(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))?|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\s{1,2}\\d{1,2}\\b","i"),alias:"number"},time:{pattern:/\b\d{1,2}:\d{1,2}:\d{1,2}(?:[.,:]\d+)?(?:\s?[+-]\d{2}:?\d{2}|Z)?\b/,alias:"number"},boolean:/\b(?:true|false|null)\b/i,number:{pattern:/(^|[^.\w])(?:0x[a-f0-9]+|0o[0-7]+|0b[01]+|v?\d[\da-f]*(?:\.\d+)*(?:e[+-]?\d+)?[a-z]{0,3}\b)\b(?!\.\w)/i,lookbehind:!0},operator:/[;:?<=>~/@!$%&+\-|^(){}*#]/,punctuation:/[\[\].,]/}; Prism.languages.lolcode={comment:[/\bOBTW\s[\s\S]*?\sTLDR\b/,/\bBTW.+/],string:{pattern:/"(?::.|[^":])*"/,inside:{variable:/:\{[^}]+\}/,symbol:[/:\([a-f\d]+\)/i,/:\[[^\]]+\]/,/:[)>o":]/]},greedy:!0},number:/(?:\B-)?(?:\b\d+(?:\.\d*)?|\B\.\d+)/,symbol:{pattern:/(^|\s)(?:A )?(?:YARN|NUMBR|NUMBAR|TROOF|BUKKIT|NOOB)(?=\s|,|$)/,lookbehind:!0,inside:{keyword:/A(?=\s)/}},label:{pattern:/((?:^|\s)(?:IM IN YR|IM OUTTA YR) )[a-zA-Z]\w*/,lookbehind:!0,alias:"string"},function:{pattern:/((?:^|\s)(?:I IZ|HOW IZ I|IZ) )[a-zA-Z]\w*/,lookbehind:!0},keyword:[{pattern:/(^|\s)(?:O HAI IM|KTHX|HAI|KTHXBYE|I HAS A|ITZ(?: A)?|R|AN|MKAY|SMOOSH|MAEK|IS NOW(?: A)?|VISIBLE|GIMMEH|O RLY\?|YA RLY|NO WAI|OIC|MEBBE|WTF\?|OMG|OMGWTF|GTFO|IM IN YR|IM OUTTA YR|FOUND YR|YR|TIL|WILE|UPPIN|NERFIN|I IZ|HOW IZ I|IF U SAY SO|SRS|HAS A|LIEK(?: A)?|IZ)(?=\s|,|$)/,lookbehind:!0},/'Z(?=\s|,|$)/],boolean:{pattern:/(^|\s)(?:WIN|FAIL)(?=\s|,|$)/,lookbehind:!0},variable:{pattern:/(^|\s)IT(?=\s|,|$)/,lookbehind:!0},operator:{pattern:/(^|\s)(?:NOT|BOTH SAEM|DIFFRINT|(?:SUM|DIFF|PRODUKT|QUOSHUNT|MOD|BIGGR|SMALLR|BOTH|EITHER|WON|ALL|ANY) OF)(?=\s|,|$)/,lookbehind:!0},punctuation:/\.{3}|…|,|!/}; Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}; !function(s){function n(n){return n=n.replace(//g,function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"}),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var e="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",t="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,function(){return e}),a="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";s.languages.markdown=s.languages.extend("markup",{}),s.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"font-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:s.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+t+a+"(?:"+t+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+t+a+")(?:"+t+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(e),inside:s.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+t+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+t+"$"),inside:{"table-header":{pattern:RegExp(e),alias:"important",inside:s.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(e){["url","bold","italic","strike","code-snippet"].forEach(function(n){e!==n&&(s.languages.markdown[e].inside.content.inside[n]=s.languages.markdown[n])})}),s.hooks.add("after-tokenize",function(n){"markdown"!==n.language&&"md"!==n.language||!function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},u=String.fromCodePoint||String.fromCharCode;s.languages.md=s.languages.markdown}(Prism); Prism.languages.matlab={comment:[/%\{[\s\S]*?\}%/,/%.+/],string:{pattern:/\B'(?:''|[^'\r\n])*'/,greedy:!0},number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+)?(?:[ij])?|\b[ij]\b/,keyword:/\b(?:break|case|catch|continue|else|elseif|end|for|function|if|inf|NaN|otherwise|parfor|pause|pi|return|switch|try|while)\b/,function:/\b(?!\d)\w+(?=\s*\()/,operator:/\.?[*^\/\\']|[+\-:@]|[<>=~]=?|&&?|\|\|?/,punctuation:/\.{3}|[.,;\[\](){}!]/}; Prism.languages.mel={comment:/\/\/.*/,code:{pattern:/`(?:\\.|[^\\`\r\n])*`/,greedy:!0,alias:"italic",inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"}}},string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},variable:/\$\w+/,number:/\b0x[\da-fA-F]+\b|\b\d+(?:\.\d*)?|\B\.\d+/,flag:{pattern:/-[^\d\W]\w*/,alias:"operator"},keyword:/\b(?:break|case|continue|default|do|else|float|for|global|if|in|int|matrix|proc|return|string|switch|vector|while)\b/,function:/\b\w+(?=\()|\b(?:about|abs|addAttr|addAttributeEditorNodeHelp|addDynamic|addNewShelfTab|addPP|addPanelCategory|addPrefixToName|advanceToNextDrivenKey|affectedNet|affects|aimConstraint|air|alias|aliasAttr|align|alignCtx|alignCurve|alignSurface|allViewFit|ambientLight|angle|angleBetween|animCone|animCurveEditor|animDisplay|animView|annotate|appendStringArray|applicationName|applyAttrPreset|applyTake|arcLenDimContext|arcLengthDimension|arclen|arrayMapper|art3dPaintCtx|artAttrCtx|artAttrPaintVertexCtx|artAttrSkinPaintCtx|artAttrTool|artBuildPaintMenu|artFluidAttrCtx|artPuttyCtx|artSelectCtx|artSetPaintCtx|artUserPaintCtx|assignCommand|assignInputDevice|assignViewportFactories|attachCurve|attachDeviceAttr|attachSurface|attrColorSliderGrp|attrCompatibility|attrControlGrp|attrEnumOptionMenu|attrEnumOptionMenuGrp|attrFieldGrp|attrFieldSliderGrp|attrNavigationControlGrp|attrPresetEditWin|attributeExists|attributeInfo|attributeMenu|attributeQuery|autoKeyframe|autoPlace|bakeClip|bakeFluidShading|bakePartialHistory|bakeResults|bakeSimulation|basename|basenameEx|batchRender|bessel|bevel|bevelPlus|binMembership|bindSkin|blend2|blendShape|blendShapeEditor|blendShapePanel|blendTwoAttr|blindDataType|boneLattice|boundary|boxDollyCtx|boxZoomCtx|bufferCurve|buildBookmarkMenu|buildKeyframeMenu|button|buttonManip|CBG|cacheFile|cacheFileCombine|cacheFileMerge|cacheFileTrack|camera|cameraView|canCreateManip|canvas|capitalizeString|catch|catchQuiet|ceil|changeSubdivComponentDisplayLevel|changeSubdivRegion|channelBox|character|characterMap|characterOutlineEditor|characterize|chdir|checkBox|checkBoxGrp|checkDefaultRenderGlobals|choice|circle|circularFillet|clamp|clear|clearCache|clip|clipEditor|clipEditorCurrentTimeCtx|clipSchedule|clipSchedulerOutliner|clipTrimBefore|closeCurve|closeSurface|cluster|cmdFileOutput|cmdScrollFieldExecuter|cmdScrollFieldReporter|cmdShell|coarsenSubdivSelectionList|collision|color|colorAtPoint|colorEditor|colorIndex|colorIndexSliderGrp|colorSliderButtonGrp|colorSliderGrp|columnLayout|commandEcho|commandLine|commandPort|compactHairSystem|componentEditor|compositingInterop|computePolysetVolume|condition|cone|confirmDialog|connectAttr|connectControl|connectDynamic|connectJoint|connectionInfo|constrain|constrainValue|constructionHistory|container|containsMultibyte|contextInfo|control|convertFromOldLayers|convertIffToPsd|convertLightmap|convertSolidTx|convertTessellation|convertUnit|copyArray|copyFlexor|copyKey|copySkinWeights|cos|cpButton|cpCache|cpClothSet|cpCollision|cpConstraint|cpConvClothToMesh|cpForces|cpGetSolverAttr|cpPanel|cpProperty|cpRigidCollisionFilter|cpSeam|cpSetEdit|cpSetSolverAttr|cpSolver|cpSolverTypes|cpTool|cpUpdateClothUVs|createDisplayLayer|createDrawCtx|createEditor|createLayeredPsdFile|createMotionField|createNewShelf|createNode|createRenderLayer|createSubdivRegion|cross|crossProduct|ctxAbort|ctxCompletion|ctxEditMode|ctxTraverse|currentCtx|currentTime|currentTimeCtx|currentUnit|curve|curveAddPtCtx|curveCVCtx|curveEPCtx|curveEditorCtx|curveIntersect|curveMoveEPCtx|curveOnSurface|curveSketchCtx|cutKey|cycleCheck|cylinder|dagPose|date|defaultLightListCheckBox|defaultNavigation|defineDataServer|defineVirtualDevice|deformer|deg_to_rad|delete|deleteAttr|deleteShadingGroupsAndMaterials|deleteShelfTab|deleteUI|deleteUnusedBrushes|delrandstr|detachCurve|detachDeviceAttr|detachSurface|deviceEditor|devicePanel|dgInfo|dgdirty|dgeval|dgtimer|dimWhen|directKeyCtx|directionalLight|dirmap|dirname|disable|disconnectAttr|disconnectJoint|diskCache|displacementToPoly|displayAffected|displayColor|displayCull|displayLevelOfDetail|displayPref|displayRGBColor|displaySmoothness|displayStats|displayString|displaySurface|distanceDimContext|distanceDimension|doBlur|dolly|dollyCtx|dopeSheetEditor|dot|dotProduct|doubleProfileBirailSurface|drag|dragAttrContext|draggerContext|dropoffLocator|duplicate|duplicateCurve|duplicateSurface|dynCache|dynControl|dynExport|dynExpression|dynGlobals|dynPaintEditor|dynParticleCtx|dynPref|dynRelEdPanel|dynRelEditor|dynamicLoad|editAttrLimits|editDisplayLayerGlobals|editDisplayLayerMembers|editRenderLayerAdjustment|editRenderLayerGlobals|editRenderLayerMembers|editor|editorTemplate|effector|emit|emitter|enableDevice|encodeString|endString|endsWith|env|equivalent|equivalentTol|erf|error|eval|evalDeferred|evalEcho|event|exactWorldBoundingBox|exclusiveLightCheckBox|exec|executeForEachObject|exists|exp|expression|expressionEditorListen|extendCurve|extendSurface|extrude|fcheck|fclose|feof|fflush|fgetline|fgetword|file|fileBrowserDialog|fileDialog|fileExtension|fileInfo|filetest|filletCurve|filter|filterCurve|filterExpand|filterStudioImport|findAllIntersections|findAnimCurves|findKeyframe|findMenuItem|findRelatedSkinCluster|finder|firstParentOf|fitBspline|flexor|floatEq|floatField|floatFieldGrp|floatScrollBar|floatSlider|floatSlider2|floatSliderButtonGrp|floatSliderGrp|floor|flow|fluidCacheInfo|fluidEmitter|fluidVoxelInfo|flushUndo|fmod|fontDialog|fopen|formLayout|format|fprint|frameLayout|fread|freeFormFillet|frewind|fromNativePath|fwrite|gamma|gauss|geometryConstraint|getApplicationVersionAsFloat|getAttr|getClassification|getDefaultBrush|getFileList|getFluidAttr|getInputDeviceRange|getMayaPanelTypes|getModifiers|getPanel|getParticleAttr|getPluginResource|getenv|getpid|glRender|glRenderEditor|globalStitch|gmatch|goal|gotoBindPose|grabColor|gradientControl|gradientControlNoAttr|graphDollyCtx|graphSelectContext|graphTrackCtx|gravity|grid|gridLayout|group|groupObjectsByName|HfAddAttractorToAS|HfAssignAS|HfBuildEqualMap|HfBuildFurFiles|HfBuildFurImages|HfCancelAFR|HfConnectASToHF|HfCreateAttractor|HfDeleteAS|HfEditAS|HfPerformCreateAS|HfRemoveAttractorFromAS|HfSelectAttached|HfSelectAttractors|HfUnAssignAS|hardenPointCurve|hardware|hardwareRenderPanel|headsUpDisplay|headsUpMessage|help|helpLine|hermite|hide|hilite|hitTest|hotBox|hotkey|hotkeyCheck|hsv_to_rgb|hudButton|hudSlider|hudSliderButton|hwReflectionMap|hwRender|hwRenderLoad|hyperGraph|hyperPanel|hyperShade|hypot|iconTextButton|iconTextCheckBox|iconTextRadioButton|iconTextRadioCollection|iconTextScrollList|iconTextStaticLabel|ikHandle|ikHandleCtx|ikHandleDisplayScale|ikSolver|ikSplineHandleCtx|ikSystem|ikSystemInfo|ikfkDisplayMethod|illustratorCurves|image|imfPlugins|inheritTransform|insertJoint|insertJointCtx|insertKeyCtx|insertKnotCurve|insertKnotSurface|instance|instanceable|instancer|intField|intFieldGrp|intScrollBar|intSlider|intSliderGrp|interToUI|internalVar|intersect|iprEngine|isAnimCurve|isConnected|isDirty|isParentOf|isSameObject|isTrue|isValidObjectName|isValidString|isValidUiName|isolateSelect|itemFilter|itemFilterAttr|itemFilterRender|itemFilterType|joint|jointCluster|jointCtx|jointDisplayScale|jointLattice|keyTangent|keyframe|keyframeOutliner|keyframeRegionCurrentTimeCtx|keyframeRegionDirectKeyCtx|keyframeRegionDollyCtx|keyframeRegionInsertKeyCtx|keyframeRegionMoveKeyCtx|keyframeRegionScaleKeyCtx|keyframeRegionSelectKeyCtx|keyframeRegionSetKeyCtx|keyframeRegionTrackCtx|keyframeStats|lassoContext|lattice|latticeDeformKeyCtx|launch|launchImageEditor|layerButton|layeredShaderPort|layeredTexturePort|layout|layoutDialog|lightList|lightListEditor|lightListPanel|lightlink|lineIntersection|linearPrecision|linstep|listAnimatable|listAttr|listCameras|listConnections|listDeviceAttachments|listHistory|listInputDeviceAxes|listInputDeviceButtons|listInputDevices|listMenuAnnotation|listNodeTypes|listPanelCategories|listRelatives|listSets|listTransforms|listUnselected|listerEditor|loadFluid|loadNewShelf|loadPlugin|loadPluginLanguageResources|loadPrefObjects|localizedPanelLabel|lockNode|loft|log|longNameOf|lookThru|ls|lsThroughFilter|lsType|lsUI|Mayatomr|mag|makeIdentity|makeLive|makePaintable|makeRoll|makeSingleSurface|makeTubeOn|makebot|manipMoveContext|manipMoveLimitsCtx|manipOptions|manipRotateContext|manipRotateLimitsCtx|manipScaleContext|manipScaleLimitsCtx|marker|match|max|memory|menu|menuBarLayout|menuEditor|menuItem|menuItemToShelf|menuSet|menuSetPref|messageLine|min|minimizeApp|mirrorJoint|modelCurrentTimeCtx|modelEditor|modelPanel|mouse|movIn|movOut|move|moveIKtoFK|moveKeyCtx|moveVertexAlongDirection|multiProfileBirailSurface|mute|nParticle|nameCommand|nameField|namespace|namespaceInfo|newPanelItems|newton|nodeCast|nodeIconButton|nodeOutliner|nodePreset|nodeType|noise|nonLinear|normalConstraint|normalize|nurbsBoolean|nurbsCopyUVSet|nurbsCube|nurbsEditUV|nurbsPlane|nurbsSelect|nurbsSquare|nurbsToPoly|nurbsToPolygonsPref|nurbsToSubdiv|nurbsToSubdivPref|nurbsUVSet|nurbsViewDirectionVector|objExists|objectCenter|objectLayer|objectType|objectTypeUI|obsoleteProc|oceanNurbsPreviewPlane|offsetCurve|offsetCurveOnSurface|offsetSurface|openGLExtension|openMayaPref|optionMenu|optionMenuGrp|optionVar|orbit|orbitCtx|orientConstraint|outlinerEditor|outlinerPanel|overrideModifier|paintEffectsDisplay|pairBlend|palettePort|paneLayout|panel|panelConfiguration|panelHistory|paramDimContext|paramDimension|paramLocator|parent|parentConstraint|particle|particleExists|particleInstancer|particleRenderInfo|partition|pasteKey|pathAnimation|pause|pclose|percent|performanceOptions|pfxstrokes|pickWalk|picture|pixelMove|planarSrf|plane|play|playbackOptions|playblast|plugAttr|plugNode|pluginInfo|pluginResourceUtil|pointConstraint|pointCurveConstraint|pointLight|pointMatrixMult|pointOnCurve|pointOnSurface|pointPosition|poleVectorConstraint|polyAppend|polyAppendFacetCtx|polyAppendVertex|polyAutoProjection|polyAverageNormal|polyAverageVertex|polyBevel|polyBlendColor|polyBlindData|polyBoolOp|polyBridgeEdge|polyCacheMonitor|polyCheck|polyChipOff|polyClipboard|polyCloseBorder|polyCollapseEdge|polyCollapseFacet|polyColorBlindData|polyColorDel|polyColorPerVertex|polyColorSet|polyCompare|polyCone|polyCopyUV|polyCrease|polyCreaseCtx|polyCreateFacet|polyCreateFacetCtx|polyCube|polyCut|polyCutCtx|polyCylinder|polyCylindricalProjection|polyDelEdge|polyDelFacet|polyDelVertex|polyDuplicateAndConnect|polyDuplicateEdge|polyEditUV|polyEditUVShell|polyEvaluate|polyExtrudeEdge|polyExtrudeFacet|polyExtrudeVertex|polyFlipEdge|polyFlipUV|polyForceUV|polyGeoSampler|polyHelix|polyInfo|polyInstallAction|polyLayoutUV|polyListComponentConversion|polyMapCut|polyMapDel|polyMapSew|polyMapSewMove|polyMergeEdge|polyMergeEdgeCtx|polyMergeFacet|polyMergeFacetCtx|polyMergeUV|polyMergeVertex|polyMirrorFace|polyMoveEdge|polyMoveFacet|polyMoveFacetUV|polyMoveUV|polyMoveVertex|polyNormal|polyNormalPerVertex|polyNormalizeUV|polyOptUvs|polyOptions|polyOutput|polyPipe|polyPlanarProjection|polyPlane|polyPlatonicSolid|polyPoke|polyPrimitive|polyPrism|polyProjection|polyPyramid|polyQuad|polyQueryBlindData|polyReduce|polySelect|polySelectConstraint|polySelectConstraintMonitor|polySelectCtx|polySelectEditCtx|polySeparate|polySetToFaceNormal|polySewEdge|polyShortestPathCtx|polySmooth|polySoftEdge|polySphere|polySphericalProjection|polySplit|polySplitCtx|polySplitEdge|polySplitRing|polySplitVertex|polyStraightenUVBorder|polySubdivideEdge|polySubdivideFacet|polyToSubdiv|polyTorus|polyTransfer|polyTriangulate|polyUVSet|polyUnite|polyWedgeFace|popen|popupMenu|pose|pow|preloadRefEd|print|progressBar|progressWindow|projFileViewer|projectCurve|projectTangent|projectionContext|projectionManip|promptDialog|propModCtx|propMove|psdChannelOutliner|psdEditTextureFile|psdExport|psdTextureFile|putenv|pwd|python|querySubdiv|quit|rad_to_deg|radial|radioButton|radioButtonGrp|radioCollection|radioMenuItemCollection|rampColorPort|rand|randomizeFollicles|randstate|rangeControl|readTake|rebuildCurve|rebuildSurface|recordAttr|recordDevice|redo|reference|referenceEdit|referenceQuery|refineSubdivSelectionList|refresh|refreshAE|registerPluginResource|rehash|reloadImage|removeJoint|removeMultiInstance|removePanelCategory|rename|renameAttr|renameSelectionList|renameUI|render|renderGlobalsNode|renderInfo|renderLayerButton|renderLayerParent|renderLayerPostProcess|renderLayerUnparent|renderManip|renderPartition|renderQualityNode|renderSettings|renderThumbnailUpdate|renderWindowEditor|renderWindowSelectContext|renderer|reorder|reorderDeformers|requires|reroot|resampleFluid|resetAE|resetPfxToPolyCamera|resetTool|resolutionNode|retarget|reverseCurve|reverseSurface|revolve|rgb_to_hsv|rigidBody|rigidSolver|roll|rollCtx|rootOf|rot|rotate|rotationInterpolation|roundConstantRadius|rowColumnLayout|rowLayout|runTimeCommand|runup|sampleImage|saveAllShelves|saveAttrPreset|saveFluid|saveImage|saveInitialState|saveMenu|savePrefObjects|savePrefs|saveShelf|saveToolSettings|scale|scaleBrushBrightness|scaleComponents|scaleConstraint|scaleKey|scaleKeyCtx|sceneEditor|sceneUIReplacement|scmh|scriptCtx|scriptEditorInfo|scriptJob|scriptNode|scriptTable|scriptToShelf|scriptedPanel|scriptedPanelType|scrollField|scrollLayout|sculpt|searchPathArray|seed|selLoadSettings|select|selectContext|selectCurveCV|selectKey|selectKeyCtx|selectKeyframeRegionCtx|selectMode|selectPref|selectPriority|selectType|selectedNodes|selectionConnection|separator|setAttr|setAttrEnumResource|setAttrMapping|setAttrNiceNameResource|setConstraintRestPosition|setDefaultShadingGroup|setDrivenKeyframe|setDynamic|setEditCtx|setEditor|setFluidAttr|setFocus|setInfinity|setInputDeviceMapping|setKeyCtx|setKeyPath|setKeyframe|setKeyframeBlendshapeTargetWts|setMenuMode|setNodeNiceNameResource|setNodeTypeFlag|setParent|setParticleAttr|setPfxToPolyCamera|setPluginResource|setProject|setStampDensity|setStartupMessage|setState|setToolTo|setUITemplate|setXformManip|sets|shadingConnection|shadingGeometryRelCtx|shadingLightRelCtx|shadingNetworkCompare|shadingNode|shapeCompare|shelfButton|shelfLayout|shelfTabLayout|shellField|shortNameOf|showHelp|showHidden|showManipCtx|showSelectionInTitle|showShadingGroupAttrEditor|showWindow|sign|simplify|sin|singleProfileBirailSurface|size|sizeBytes|skinCluster|skinPercent|smoothCurve|smoothTangentSurface|smoothstep|snap2to2|snapKey|snapMode|snapTogetherCtx|snapshot|soft|softMod|softModCtx|sort|sound|soundControl|source|spaceLocator|sphere|sphrand|spotLight|spotLightPreviewPort|spreadSheetEditor|spring|sqrt|squareSurface|srtContext|stackTrace|startString|startsWith|stitchAndExplodeShell|stitchSurface|stitchSurfacePoints|strcmp|stringArrayCatenate|stringArrayContains|stringArrayCount|stringArrayInsertAtIndex|stringArrayIntersector|stringArrayRemove|stringArrayRemoveAtIndex|stringArrayRemoveDuplicates|stringArrayRemoveExact|stringArrayToString|stringToStringArray|strip|stripPrefixFromName|stroke|subdAutoProjection|subdCleanTopology|subdCollapse|subdDuplicateAndConnect|subdEditUV|subdListComponentConversion|subdMapCut|subdMapSewMove|subdMatchTopology|subdMirror|subdToBlind|subdToPoly|subdTransferUVsToCache|subdiv|subdivCrease|subdivDisplaySmoothness|substitute|substituteAllString|substituteGeometry|substring|surface|surfaceSampler|surfaceShaderList|swatchDisplayPort|switchTable|symbolButton|symbolCheckBox|sysFile|system|tabLayout|tan|tangentConstraint|texLatticeDeformContext|texManipContext|texMoveContext|texMoveUVShellContext|texRotateContext|texScaleContext|texSelectContext|texSelectShortestPathCtx|texSmudgeUVContext|texWinToolCtx|text|textCurves|textField|textFieldButtonGrp|textFieldGrp|textManip|textScrollList|textToShelf|textureDisplacePlane|textureHairColor|texturePlacementContext|textureWindow|threadCount|threePointArcCtx|timeControl|timePort|timerX|toNativePath|toggle|toggleAxis|toggleWindowVisibility|tokenize|tokenizeList|tolerance|tolower|toolButton|toolCollection|toolDropped|toolHasOptions|toolPropertyWindow|torus|toupper|trace|track|trackCtx|transferAttributes|transformCompare|transformLimits|translator|trim|trunc|truncateFluidCache|truncateHairCache|tumble|tumbleCtx|turbulence|twoPointArcCtx|uiRes|uiTemplate|unassignInputDevice|undo|undoInfo|ungroup|uniform|unit|unloadPlugin|untangleUV|untitledFileName|untrim|upAxis|updateAE|userCtx|uvLink|uvSnapshot|validateShelfName|vectorize|view2dToolCtx|viewCamera|viewClipPlane|viewFit|viewHeadOn|viewLookAt|viewManip|viewPlace|viewSet|visor|volumeAxis|vortex|waitCursor|warning|webBrowser|webBrowserPrefs|whatIs|window|windowPref|wire|wireContext|workspace|wrinkle|wrinkleContext|writeTake|xbmLangPathList|xform)\b/,operator:[/\+[+=]?|-[-=]?|&&|\|\||[<>]=|[*\/!=]=?|[%^]/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,:;?\[\](){}]/},Prism.languages.mel.code.inside.rest=Prism.languages.mel; Prism.languages.mizar={comment:/::.+/,keyword:/@proof\b|\b(?:according|aggregate|all|and|antonym|are|as|associativity|assume|asymmetry|attr|be|begin|being|by|canceled|case|cases|clusters?|coherence|commutativity|compatibility|connectedness|consider|consistency|constructors|contradiction|correctness|def|deffunc|define|definitions?|defpred|do|does|equals|end|environ|ex|exactly|existence|for|from|func|given|hence|hereby|holds|idempotence|identity|iff?|implies|involutiveness|irreflexivity|is|it|let|means|mode|non|not|notations?|now|of|or|otherwise|over|per|pred|prefix|projectivity|proof|provided|qua|reconsider|redefine|reduce|reducibility|reflexivity|registrations?|requirements|reserve|sch|schemes?|section|selector|set|sethood|st|struct|such|suppose|symmetry|synonym|take|that|the|then|theorems?|thesis|thus|to|transitivity|uniqueness|vocabular(?:y|ies)|when|where|with|wrt)\b/,parameter:{pattern:/\$(?:10|\d)/,alias:"variable"},variable:/\b\w+(?=:)/,number:/(?:\b|-)\d+\b/,operator:/\.\.\.|->|&|\.?=/,punctuation:/\(#|#\)|[,:;\[\](){}]/}; !function($){var e=["$eq","$gt","$gte","$in","$lt","$lte","$ne","$nin","$and","$not","$nor","$or","$exists","$type","$expr","$jsonSchema","$mod","$regex","$text","$where","$geoIntersects","$geoWithin","$near","$nearSphere","$all","$elemMatch","$size","$bitsAllClear","$bitsAllSet","$bitsAnyClear","$bitsAnySet","$comment","$elemMatch","$meta","$slice","$currentDate","$inc","$min","$max","$mul","$rename","$set","$setOnInsert","$unset","$addToSet","$pop","$pull","$push","$pullAll","$each","$position","$slice","$sort","$bit","$addFields","$bucket","$bucketAuto","$collStats","$count","$currentOp","$facet","$geoNear","$graphLookup","$group","$indexStats","$limit","$listLocalSessions","$listSessions","$lookup","$match","$merge","$out","$planCacheStats","$project","$redact","$replaceRoot","$replaceWith","$sample","$set","$skip","$sort","$sortByCount","$unionWith","$unset","$unwind","$abs","$accumulator","$acos","$acosh","$add","$addToSet","$allElementsTrue","$and","$anyElementTrue","$arrayElemAt","$arrayToObject","$asin","$asinh","$atan","$atan2","$atanh","$avg","$binarySize","$bsonSize","$ceil","$cmp","$concat","$concatArrays","$cond","$convert","$cos","$dateFromParts","$dateToParts","$dateFromString","$dateToString","$dayOfMonth","$dayOfWeek","$dayOfYear","$degreesToRadians","$divide","$eq","$exp","$filter","$first","$floor","$function","$gt","$gte","$hour","$ifNull","$in","$indexOfArray","$indexOfBytes","$indexOfCP","$isArray","$isNumber","$isoDayOfWeek","$isoWeek","$isoWeekYear","$last","$last","$let","$literal","$ln","$log","$log10","$lt","$lte","$ltrim","$map","$max","$mergeObjects","$meta","$min","$millisecond","$minute","$mod","$month","$multiply","$ne","$not","$objectToArray","$or","$pow","$push","$radiansToDegrees","$range","$reduce","$regexFind","$regexFindAll","$regexMatch","$replaceOne","$replaceAll","$reverseArray","$round","$rtrim","$second","$setDifference","$setEquals","$setIntersection","$setIsSubset","$setUnion","$size","$sin","$slice","$split","$sqrt","$stdDevPop","$stdDevSamp","$strcasecmp","$strLenBytes","$strLenCP","$substr","$substrBytes","$substrCP","$subtract","$sum","$switch","$tan","$toBool","$toDate","$toDecimal","$toDouble","$toInt","$toLong","$toObjectId","$toString","$toLower","$toUpper","$trim","$trunc","$type","$week","$year","$zip","$comment","$explain","$hint","$max","$maxTimeMS","$min","$orderby","$query","$returnKey","$showDiskLoc","$natural"],t="(?:"+(e=e.map(function($){return $.replace("$","\\$")})).join("|")+")\\b";$.languages.mongodb=$.languages.extend("javascript",{}),$.languages.insertBefore("mongodb","string",{property:{pattern:/(?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)(?=\s*:)/,greedy:!0,inside:{keyword:RegExp("^(['\"])?"+t+"(?:\\1)?$")}}}),$.languages.mongodb.string.inside={url:{pattern:/https?:\/\/[-\w@:%.+~#=]{1,256}\.[a-z0-9()]{1,6}\b[-\w()@:%+.~#?&/=]*/i,greedy:!0},entity:{pattern:/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/,greedy:!0}},$.languages.insertBefore("mongodb","constant",{builtin:{pattern:RegExp("\\b(?:"+["ObjectId","Code","BinData","DBRef","Timestamp","NumberLong","NumberDecimal","MaxKey","MinKey","RegExp","ISODate","UUID"].join("|")+")\\b"),alias:"keyword"}})}(Prism); Prism.languages.monkey={string:/"[^"\r\n]*"/,comment:[{pattern:/^#Rem\s[\s\S]*?^#End/im,greedy:!0},{pattern:/'.+/,greedy:!0}],preprocessor:{pattern:/(^[ \t]*)#.+/m,lookbehind:!0,alias:"comment"},function:/\b\w+(?=\()/,"type-char":{pattern:/(\w)[?%#$]/,lookbehind:!0,alias:"variable"},number:{pattern:/((?:\.\.)?)(?:(?:\b|\B-\.?|\B\.)\d+(?:(?!\.\.)\.\d*)?|\$[\da-f]+)/i,lookbehind:!0},keyword:/\b(?:Void|Strict|Public|Private|Property|Bool|Int|Float|String|Array|Object|Continue|Exit|Import|Extern|New|Self|Super|Try|Catch|Eachin|True|False|Extends|Abstract|Final|Select|Case|Default|Const|Local|Global|Field|Method|Function|Class|End|If|Then|Else|ElseIf|EndIf|While|Wend|Repeat|Until|Forever|For|To|Step|Next|Return|Module|Interface|Implements|Inline|Throw|Null)\b/i,operator:/\.\.|<[=>]?|>=?|:?=|(?:[+\-*\/&~|]|\b(?:Mod|Shl|Shr)\b)=?|\b(?:And|Not|Or)\b/i,punctuation:/[.,:;()\[\]]/}; Prism.languages.moonscript={comment:/--.*/,string:[{pattern:/'[^']*'|\[(=*)\[[\s\S]*?\]\1\]/,greedy:!0},{pattern:/"[^"]*"/,greedy:!0,inside:{interpolation:{pattern:/#\{[^{}]*\}/,inside:{moonscript:{pattern:/(^#\{)[\s\S]+(?=\})/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/#\{|\}/,alias:"punctuation"}}}}}],"class-name":[{pattern:/(\b(?:class|extends)[ \t]+)\w+/,lookbehind:!0},/\b[A-Z]\w*/],keyword:/\b(?:class|continue|do|else|elseif|export|extends|for|from|if|import|in|local|nil|return|self|super|switch|then|unless|using|when|while|with)\b/,variable:/@@?\w*/,property:{pattern:/\b(?!\d)\w+(?=:)|(:)(?!\d)\w+/,lookbehind:!0},function:{pattern:/\b(?:_G|_VERSION|assert|collectgarbage|coroutine\.(?:running|create|resume|status|wrap|yield)|debug\.(?:debug|gethook|getinfo|getlocal|getupvalue|setlocal|setupvalue|sethook|traceback|getfenv|getmetatable|getregistry|setfenv|setmetatable)|dofile|error|getfenv|getmetatable|io\.(?:stdin|stdout|stderr|close|flush|input|lines|open|output|popen|read|tmpfile|type|write)|ipairs|load|loadfile|loadstring|math\.(?:abs|acos|asin|atan|atan2|ceil|sin|cos|tan|deg|exp|floor|log|log10|max|min|fmod|modf|cosh|sinh|tanh|pow|rad|sqrt|frexp|ldexp|random|randomseed|pi)|module|next|os\.(?:clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)|package\.(?:cpath|loaded|loadlib|path|preload|seeall)|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string\.(?:byte|char|dump|find|len|lower|rep|sub|upper|format|gsub|gmatch|match|reverse)|table\.(?:maxn|concat|sort|insert|remove)|tonumber|tostring|type|unpack|xpcall)\b/,inside:{punctuation:/\./}},boolean:/\b(?:false|true)\b/,number:/(?:\B\.\d+|\b\d+\.\d+|\b\d+(?=[eE]))(?:[eE][-+]?\d+)?\b|\b(?:0x[a-fA-F\d]+|\d+)(?:U?LL)?\b/,operator:/\.{3}|[-=]>|~=|(?:[-+*/%<>!=]|\.\.)=?|[:#^]|\b(?:and|or)\b=?|\b(?:not)\b/,punctuation:/[.,()[\]{}\\]/},Prism.languages.moonscript.string[1].inside.interpolation.inside.moonscript.inside=Prism.languages.moonscript,Prism.languages.moon=Prism.languages.moonscript; Prism.languages.n1ql={comment:/\/\*[\s\S]*?(?:$|\*\/)/,parameter:/\$[\w.]+/,string:{pattern:/(["'])(?:\\[\s\S]|(?!\1)[^\\]|\1\1)*\1/,greedy:!0},identifier:{pattern:/`(?:\\[\s\S]|[^\\`]|``)*`/,greedy:!0},function:/\b(?:ABS|ACOS|ARRAY_AGG|ARRAY_APPEND|ARRAY_AVG|ARRAY_CONCAT|ARRAY_CONTAINS|ARRAY_COUNT|ARRAY_DISTINCT|ARRAY_FLATTEN|ARRAY_IFNULL|ARRAY_INSERT|ARRAY_INTERSECT|ARRAY_LENGTH|ARRAY_MAX|ARRAY_MIN|ARRAY_POSITION|ARRAY_PREPEND|ARRAY_PUT|ARRAY_RANGE|ARRAY_REMOVE|ARRAY_REPEAT|ARRAY_REPLACE|ARRAY_REVERSE|ARRAY_SORT|ARRAY_STAR|ARRAY_SUM|ARRAY_SYMDIFF|ARRAY_SYMDIFFN|ARRAY_UNION|ASIN|ATAN|ATAN2|AVG|BASE64|BASE64_DECODE|BASE64_ENCODE|BITAND|BITCLEAR|BITNOT|BITOR|BITSET|BITSHIFT|BITTEST|BITXOR|CEIL|CLOCK_LOCAL|CLOCK_MILLIS|CLOCK_STR|CLOCK_TZ|CLOCK_UTC|CONTAINS|CONTAINS_TOKEN|CONTAINS_TOKEN_LIKE|CONTAINS_TOKEN_REGEXP|COS|COUNT|CURL|DATE_ADD_MILLIS|DATE_ADD_STR|DATE_DIFF_MILLIS|DATE_DIFF_STR|DATE_FORMAT_STR|DATE_PART_MILLIS|DATE_PART_STR|DATE_RANGE_MILLIS|DATE_RANGE_STR|DATE_TRUNC_MILLIS|DATE_TRUNC_STR|DECODE_JSON|DEGREES|DURATION_TO_STR|E|ENCODED_SIZE|ENCODE_JSON|EXP|FLOOR|GREATEST|HAS_TOKEN|IFINF|IFMISSING|IFMISSINGORNULL|IFNAN|IFNANORINF|IFNULL|INITCAP|ISARRAY|ISATOM|ISBOOLEAN|ISNUMBER|ISOBJECT|ISSTRING|IsBitSET|LEAST|LENGTH|LN|LOG|LOWER|LTRIM|MAX|META|MILLIS|MILLIS_TO_LOCAL|MILLIS_TO_STR|MILLIS_TO_TZ|MILLIS_TO_UTC|MILLIS_TO_ZONE_NAME|MIN|MISSINGIF|NANIF|NEGINFIF|NOW_LOCAL|NOW_MILLIS|NOW_STR|NOW_TZ|NOW_UTC|NULLIF|OBJECT_ADD|OBJECT_CONCAT|OBJECT_INNER_PAIRS|OBJECT_INNER_VALUES|OBJECT_LENGTH|OBJECT_NAMES|OBJECT_PAIRS|OBJECT_PUT|OBJECT_REMOVE|OBJECT_RENAME|OBJECT_REPLACE|OBJECT_UNWRAP|OBJECT_VALUES|PAIRS|PI|POLY_LENGTH|POSINFIF|POSITION|POWER|RADIANS|RANDOM|REGEXP_CONTAINS|REGEXP_LIKE|REGEXP_POSITION|REGEXP_REPLACE|REPEAT|REPLACE|REVERSE|ROUND|RTRIM|SIGN|SIN|SPLIT|SQRT|STR_TO_DURATION|STR_TO_MILLIS|STR_TO_TZ|STR_TO_UTC|STR_TO_ZONE_NAME|SUBSTR|SUFFIXES|SUM|TAN|TITLE|TOARRAY|TOATOM|TOBOOLEAN|TOKENS|TONUMBER|TOOBJECT|TOSTRING|TRIM|TRUNC|TYPE|UPPER|WEEKDAY_MILLIS|WEEKDAY_STR)(?=\s*\()/i,keyword:/\b(?:ALL|ALTER|ANALYZE|AS|ASC|BEGIN|BINARY|BOOLEAN|BREAK|BUCKET|BUILD|BY|CALL|CAST|CLUSTER|COLLATE|COLLECTION|COMMIT|CONNECT|CONTINUE|CORRELATE|COVER|CREATE|DATABASE|DATASET|DATASTORE|DECLARE|DECREMENT|DELETE|DERIVED|DESC|DESCRIBE|DISTINCT|DO|DROP|EACH|ELEMENT|EXCEPT|EXCLUDE|EXECUTE|EXPLAIN|FETCH|FLATTEN|FOR|FORCE|FROM|FUNCTION|GRANT|GROUP|GSI|HAVING|IF|IGNORE|ILIKE|INCLUDE|INCREMENT|INDEX|INFER|INLINE|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KEYS|KEYSPACE|KNOWN|LAST|LEFT|LET|LETTING|LIMIT|LSM|MAP|MAPPING|MATCHED|MATERIALIZED|MERGE|MINUS|MISSING|NAMESPACE|NEST|NULL|NUMBER|OBJECT|OFFSET|ON|OPTION|ORDER|OUTER|OVER|PARSE|PARTITION|PASSWORD|PATH|POOL|PREPARE|PRIMARY|PRIVATE|PRIVILEGE|PROCEDURE|PUBLIC|RAW|REALM|REDUCE|RENAME|RETURN|RETURNING|REVOKE|RIGHT|ROLE|ROLLBACK|SATISFIES|SCHEMA|SELECT|SELF|SEMI|SET|SHOW|SOME|START|STATISTICS|STRING|SYSTEM|TO|TRANSACTION|TRIGGER|TRUNCATE|UNDER|UNION|UNIQUE|UNKNOWN|UNNEST|UNSET|UPDATE|UPSERT|USE|USER|USING|VALIDATE|VALUE|VALUES|VIA|VIEW|WHERE|WHILE|WITH|WORK|XOR)\b/i,boolean:/\b(?:TRUE|FALSE)\b/i,number:/(?:\b\d+\.|\B\.)\d+e[+\-]?\d+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/%]|!=|==?|\|\||<[>=]?|>=?|\b(?:AND|ANY|ARRAY|BETWEEN|CASE|ELSE|END|EVERY|EXISTS|FIRST|IN|LIKE|NOT|OR|THEN|VALUED|WHEN|WITHIN)\b/i,punctuation:/[;[\](),.{}:]/}; Prism.languages.n4js=Prism.languages.extend("javascript",{keyword:/\b(?:any|Array|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),Prism.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),Prism.languages.n4jsd=Prism.languages.n4js; Prism.languages["nand2tetris-hdl"]={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,keyword:/\b(?:CHIP|IN|OUT|PARTS|BUILTIN|CLOCKED)\b/,boolean:/\b(?:true|false)\b/,function:/\b[A-Za-z][A-Za-z0-9]*(?=\()/,number:/\b\d+\b/,operator:/=|\.\./,punctuation:/[{}[\];(),:]/}; !function(e){var a=/\{[^\r\n\[\]{}]*\}/,n={"quoted-string":{pattern:/"(?:[^"\\]|\\.)*"/,alias:"operator"},"command-param-id":{pattern:/(\s)\w+:/,lookbehind:!0,alias:"property"},"command-param-value":[{pattern:a,alias:"selector"},{pattern:/([\t ])\S+/,lookbehind:!0,greedy:!0,alias:"operator"},{pattern:/\S(?:.*\S)?/,alias:"operator"}]};function t(e){return"string"==typeof e?e:Array.isArray(e)?e.map(t).join(""):t(e.content)}e.languages.naniscript={comment:{pattern:/^([\t ]*);.*/m,lookbehind:!0},define:{pattern:/^>.+/m,alias:"tag",inside:{value:{pattern:/(^>\w+[\t ]+)(?!\s)[^{}\r\n]+/,lookbehind:!0,alias:"operator"},key:{pattern:/(^>)\w+/,lookbehind:!0}}},label:{pattern:/^([\t ]*)#[\t ]*\w+[\t ]*$/m,lookbehind:!0,alias:"regex"},command:{pattern:/^([\t ]*)@\w+(?=[\t ]|$).*/m,lookbehind:!0,alias:"function",inside:{"command-name":/^@\w+/,expression:{pattern:a,greedy:!0,alias:"selector"},"command-params":{pattern:/\s*\S[\s\S]*/,inside:n}}},"generic-text":{pattern:/(^[ \t]*)[^#@>;\s].*/m,lookbehind:!0,alias:"punctuation",inside:{"escaped-char":/\\[{}\[\]"]/,expression:{pattern:a,greedy:!0,alias:"selector"},"inline-command":{pattern:/\[[\t ]*\w[^\r\n\[\]]*\]/,greedy:!0,alias:"function",inside:{"command-params":{pattern:/(^\[[\t ]*\w+\b)[\s\S]+(?=\]$)/,lookbehind:!0,inside:n},"command-param-name":{pattern:/^(\[[\t ]*)\w+/,lookbehind:!0,alias:"name"},"start-stop-char":/[\[\]]/}}}}},e.languages.nani=e.languages.naniscript,e.hooks.add("after-tokenize",function(e){e.tokens.forEach(function(e){if("string"!=typeof e&&"generic-text"===e.type){var a=t(e);(function(e){for(var a=[],n=0;n=&|$!]/}; Prism.languages.neon={comment:{pattern:/#.*/,greedy:!0},datetime:{pattern:/(^|[[{(=:,\s])\d\d\d\d-\d\d?-\d\d?(?:(?:[Tt]| +)\d\d?:\d\d:\d\d(?:\.\d*)? *(?:Z|[-+]\d\d?(?::?\d\d)?)?)?(?=$|[\]}),\s])/,lookbehind:!0,alias:"number"},key:{pattern:/(^|[[{(,\s])[^,:=[\]{}()'"\s]+(?=\s*:(?:$|[\]}),\s])|\s*=)/,lookbehind:!0,alias:"atrule"},number:{pattern:/(^|[[{(=:,\s])[+-]?(?:0x[\da-fA-F]+|0o[0-7]+|0b[01]+|(?:\d+(?:\.\d*)?|\.?\d+)(?:[eE][+-]?\d+)?)(?=$|[\]}),:=\s])/,lookbehind:!0},boolean:{pattern:/(^|[[{(=:,\s])(?:true|false|yes|no)(?=$|[\]}),:=\s])/i,lookbehind:!0},null:{pattern:/(^|[[{(=:,\s])(?:null)(?=$|[\]}),:=\s])/i,lookbehind:!0,alias:"keyword"},string:{pattern:/(^|[[{(=:,\s])(?:('''|""")\r?\n(?:(?:[^\r\n]|\r?\n(?![\t ]*\2))*\r?\n)?[\t ]*\2|'[^'\r\n]*'|"(?:\\.|[^\\"\r\n])*")/,lookbehind:!0,greedy:!0},literal:{pattern:/(^|[[{(=:,\s])(?:[^#"',:=[\]{}()\s`-]|[:-][^"',=[\]{}()\s])(?:[^,:=\]})(\s]|:(?![\s,\]})]|$)|[ \t]+[^#,:=\]})(\s])*/,lookbehind:!0,alias:"string"},punctuation:/[,:=[\]{}()-]/}; Prism.languages.nevod={comment:/\/\/.*|(?:\/\*[\s\S]*?(?:\*\/|$))/,string:{pattern:/(?:"(?:""|[^"])*"(?!")|'(?:''|[^'])*'(?!'))!?\*?/,greedy:!0,inside:{"string-attrs":/!$|!\*$|\*$/}},namespace:{pattern:/(@namespace\s+)[a-zA-Z0-9\-.]+(?=\s*\{)/,lookbehind:!0},pattern:{pattern:/(@pattern\s+)?#?[a-zA-Z0-9\-.]+(?:\s*\(\s*(?:~\s*)?[a-zA-Z0-9\-.]+\s*(?:,\s*(?:~\s*)?[a-zA-Z0-9\-.]*)*\))?(?=\s*=)/,lookbehind:!0,inside:{"pattern-name":{pattern:/^#?[a-zA-Z0-9\-.]+/,alias:"class-name"},fields:{pattern:/\(.*\)/,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},punctuation:/[,()]/,operator:{pattern:/~/,alias:"field-hidden-mark"}}}}},search:{pattern:/(@search\s+|#)[a-zA-Z0-9\-.]+(?:\.\*)?(?=\s*;)/,alias:"function",lookbehind:!0},keyword:/@(?:require|namespace|pattern|search|inside|outside|having|where)\b/,"standard-pattern":{pattern:/\b(?:Word|Punct|Symbol|Space|LineBreak|Start|End|Alpha|AlphaNum|Num|NumAlpha|Blank|WordBreak|Any)(?:\([a-zA-Z0-9\-.,\s+]*\))?/,inside:{"standard-pattern-name":{pattern:/^[a-zA-Z0-9\-.]+/,alias:"builtin"},quantifier:{pattern:/\b\d+(?:\s*\+|\s*-\s*\d+)?(?!\w)/,alias:"number"},"standard-pattern-attr":{pattern:/[a-zA-Z0-9\-.]+/,alias:"builtin"},punctuation:/[,()]/}},quantifier:{pattern:/\b\d+(?:\s*\+|\s*-\s*\d+)?(?!\w)/,alias:"number"},operator:[{pattern:/=/,alias:"pattern-def"},{pattern:/&/,alias:"conjunction"},{pattern:/~/,alias:"exception"},{pattern:/\?/,alias:"optionality"},{pattern:/[[\]]/,alias:"repetition"},{pattern:/[{}]/,alias:"variation"},{pattern:/[+_]/,alias:"sequence"},{pattern:/\.{2,3}/,alias:"span"}],"field-capture":[{pattern:/([a-zA-Z0-9\-.]+\s*\()\s*[a-zA-Z0-9\-.]+\s*:\s*[a-zA-Z0-9\-.]+(?:\s*,\s*[a-zA-Z0-9\-.]+\s*:\s*[a-zA-Z0-9\-.]+)*(?=\s*\))/,lookbehind:!0,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},colon:/:/}},{pattern:/[a-zA-Z0-9\-.]+\s*:/,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},colon:/:/}}],punctuation:/[:;,()]/,name:/[a-zA-Z0-9\-.]+/}; !function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;Prism.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(); Prism.languages.nim={comment:/#.*/,string:{pattern:/(?:(?:\b(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+)?(?:"""[\s\S]*?"""(?!")|"(?:\\[\s\S]|""|[^"\\])*")|'(?:\\(?:\d+|x[\da-fA-F]{2}|.)|[^'])')/,greedy:!0},number:/\b(?:0[xXoObB][\da-fA-F_]+|\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:[eE][+-]?\d[\d_]*)?)(?:'?[iuf]\d*)?/,keyword:/\b(?:addr|as|asm|atomic|bind|block|break|case|cast|concept|const|continue|converter|defer|discard|distinct|do|elif|else|end|enum|except|export|finally|for|from|func|generic|if|import|include|interface|iterator|let|macro|method|mixin|nil|object|out|proc|ptr|raise|ref|return|static|template|try|tuple|type|using|var|when|while|with|without|yield)\b/,function:{pattern:/(?:(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+|`[^`\r\n]+`)\*?(?:\[[^\]]+\])?(?=\s*\()/,inside:{operator:/\*$/}},ignore:{pattern:/`[^`\r\n]+`/,inside:{punctuation:/`/}},operator:{pattern:/(^|[({\[](?=\.\.)|(?![({\[]\.).)(?:(?:[=+\-*\/<>@$~&%|!?^:\\]|\.\.|\.(?![)}\]]))+|\b(?:and|div|of|or|in|is|isnot|mod|not|notin|shl|shr|xor)\b)/m,lookbehind:!0},punctuation:/[({\[]\.|\.[)}\]]|[`(){}\[\],:]/}; Prism.languages.nix={comment:/\/\*[\s\S]*?\*\/|#.*/,string:{pattern:/"(?:[^"\\]|\\[\s\S])*"|''(?:(?!'')[\s\S]|''(?:'|\\|\$\{))*''/,greedy:!0,inside:{interpolation:{pattern:/(^|(?:^|(?!'').)[^\\])\$\{(?:[^{}]|\{[^}]*\})*\}/,lookbehind:!0,inside:{antiquotation:{pattern:/^\$(?=\{)/,alias:"variable"}}}}},url:[/\b(?:[a-z]{3,7}:\/\/)[\w\-+%~\/.:#=?&]+/,{pattern:/([^\/])(?:[\w\-+%~.:#=?&]*(?!\/\/)[\w\-+%~\/.:#=?&])?(?!\/\/)\/[\w\-+%~\/.:#=?&]*/,lookbehind:!0}],antiquotation:{pattern:/\$(?=\{)/,alias:"variable"},number:/\b\d+\b/,keyword:/\b(?:assert|builtins|else|if|in|inherit|let|null|or|then|with)\b/,function:/\b(?:abort|add|all|any|attrNames|attrValues|baseNameOf|compareVersions|concatLists|currentSystem|deepSeq|derivation|dirOf|div|elem(?:At)?|fetch(?:url|Tarball)|filter(?:Source)?|fromJSON|genList|getAttr|getEnv|hasAttr|hashString|head|import|intersectAttrs|is(?:Attrs|Bool|Function|Int|List|Null|String)|length|lessThan|listToAttrs|map|mul|parseDrvName|pathExists|read(?:Dir|File)|removeAttrs|replaceStrings|seq|sort|stringLength|sub(?:string)?|tail|throw|to(?:File|JSON|Path|String|XML)|trace|typeOf)\b|\bfoldl'\B/,boolean:/\b(?:true|false)\b/,operator:/[=!<>]=?|\+\+?|\|\||&&|\/\/|->?|[?@]/,punctuation:/[{}()[\].,:;]/},Prism.languages.nix.string.inside.interpolation.inside.rest=Prism.languages.nix; Prism.languages.nsis={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|[#;].*)/,lookbehind:!0},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:{pattern:/(^[\t ]*)(?:Abort|Add(?:BrandingImage|Size)|AdvSplash|Allow(?:RootDirInstall|SkipFiles)|AutoCloseWindow|Banner|BG(?:Font|Gradient|Image)|BrandingText|BringToFront|Call(?:InstDLL)?|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|Create(?:Directory|Font|ShortCut)|Delete(?:INISec|INIStr|RegKey|RegValue)?|Detail(?:Print|sButtonText)|Dialer|Dir(?:Text|Var|Verify)|EnableWindow|Enum(?:RegKey|RegValue)|Exch|Exec(?:Shell(?:Wait)?|Wait)?|ExpandEnvStrings|File(?:BufSize|Close|ErrorText|Open|Read|ReadByte|ReadUTF16LE|ReadWord|WriteUTF16LE|Seek|Write|WriteByte|WriteWord)?|Find(?:Close|First|Next|Window)|FlushINI|Get(?:CurInstType|CurrentAddress|DlgItem|DLLVersion(?:Local)?|ErrorLevel|FileTime(?:Local)?|FullPathName|Function(?:Address|End)?|InstDirError|LabelAddress|TempFileName)|Goto|HideWindow|Icon|If(?:Abort|Errors|FileExists|RebootFlag|Silent)|InitPluginsDir|Install(?:ButtonText|Colors|Dir(?:RegKey)?)|InstProgressFlags|Inst(?:Type(?:GetText|SetText)?)|Int(?:64|Ptr)?CmpU?|Int(?:64)?Fmt|Int(?:Ptr)?Op|IsWindow|Lang(?:DLL|String)|License(?:BkColor|Data|ForceSelection|LangString|Text)|LoadLanguageFile|LockWindow|Log(?:Set|Text)|Manifest(?:DPIAware|SupportedOS)|Math|MessageBox|MiscButtonText|Name|Nop|ns(?:Dialogs|Exec)|NSISdl|OutFile|Page(?:Callbacks)?|PE(?:DllCharacteristics|SubsysVer)|Pop|Push|Quit|Read(?:EnvStr|INIStr|RegDWORD|RegStr)|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|Section(?:End|GetFlags|GetInstTypes|GetSize|GetText|Group|In|SetFlags|SetInstTypes|SetSize|SetText)?|SendMessage|Set(?:AutoClose|BrandingImage|Compress|Compressor(?:DictSize)?|CtlColors|CurInstType|DatablockOptimize|DateSave|Details(?:Print|View)|ErrorLevel|Errors|FileAttributes|Font|OutPath|Overwrite|PluginUnload|RebootFlag|RegView|ShellVarContext|Silent)|Show(?:InstDetails|UninstDetails|Window)|Silent(?:Install|UnInstall)|Sleep|SpaceTexts|Splash|StartMenu|Str(?:CmpS?|Cpy|Len)|SubCaption|System|Unicode|Uninstall(?:ButtonText|Caption|Icon|SubCaption|Text)|UninstPage|UnRegDLL|UserInfo|Var|VI(?:AddVersionKey|FileVersion|ProductVersion)|VPatch|WindowIcon|Write(?:INIStr|Reg(?:Bin|DWORD|ExpandStr|MultiStr|None|Str)|Uninstaller)|XPStyle)\b/m,lookbehind:!0},property:/\b(?:admin|all|auto|both|colored|false|force|hide|highest|lastused|leave|listonly|none|normal|notset|off|on|open|print|show|silent|silentlog|smooth|textonly|true|user|ARCHIVE|FILE_(?:ATTRIBUTE_ARCHIVE|ATTRIBUTE_NORMAL|ATTRIBUTE_OFFLINE|ATTRIBUTE_READONLY|ATTRIBUTE_SYSTEM|ATTRIBUTE_TEMPORARY)|HK(?:(?:CR|CU|LM)(?:32|64)?|DD|PD|U)|HKEY_(?:CLASSES_ROOT|CURRENT_CONFIG|CURRENT_USER|DYN_DATA|LOCAL_MACHINE|PERFORMANCE_DATA|USERS)|ID(?:ABORT|CANCEL|IGNORE|NO|OK|RETRY|YES)|MB_(?:ABORTRETRYIGNORE|DEFBUTTON1|DEFBUTTON2|DEFBUTTON3|DEFBUTTON4|ICONEXCLAMATION|ICONINFORMATION|ICONQUESTION|ICONSTOP|OK|OKCANCEL|RETRYCANCEL|RIGHT|RTLREADING|SETFOREGROUND|TOPMOST|USERICON|YESNO)|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)\b/,constant:/\$\{[\w\.:\^-]+\}|\$\([\w\.:\^-]+\)/i,variable:/\$\w+/i,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|\+\+?|<=?|>=?|==?=?|&&?|\|\|?|[?*\/~^%]/,punctuation:/[{}[\];(),.:]/,important:{pattern:/(^[\t ]*)!(?:addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversion|gettlbversion|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|verbose|warning)\b/im,lookbehind:!0}}; Prism.languages.objectivec=Prism.languages.extend("c",{string:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|@"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,keyword:/\b(?:asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete Prism.languages.objectivec["class-name"],Prism.languages.objc=Prism.languages.objectivec; Prism.languages.ocaml={comment:/\(\*[\s\S]*?\*\)/,string:[{pattern:/"(?:\\.|[^\\\r\n"])*"/,greedy:!0},{pattern:/(['`])(?:\\(?:\d+|x[\da-f]+|.)|(?!\1)[^\\\r\n])\1/i,greedy:!0}],number:/\b(?:0x[\da-f][\da-f_]+|(?:0[bo])?\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?[\d_]+)?)/i,directive:{pattern:/\B#\w+/,alias:"important"},label:{pattern:/\B~\w+/,alias:"function"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"variable"},module:{pattern:/\b[A-Z]\w+/,alias:"variable"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,operator:/:=|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/[(){}\[\]|.,:;]|\b_\b/}; !function(E){E.languages.opencl=E.languages.extend("c",{keyword:/\b(?:__attribute__|(?:__)?(?:constant|global|kernel|local|private|read_only|read_write|write_only)|auto|break|case|complex|const|continue|default|do|(?:float|double)(?:16(?:x(?:1|16|2|4|8))?|1x(?:1|16|2|4|8)|2(?:x(?:1|16|2|4|8))?|3|4(?:x(?:1|16|2|4|8))?|8(?:x(?:1|16|2|4|8))?)?|else|enum|extern|for|goto|(?:u?(?:char|short|int|long)|half|quad|bool)(?:2|3|4|8|16)?|if|imaginary|inline|packed|pipe|register|restrict|return|signed|sizeof|static|struct|switch|typedef|uniform|union|unsigned|void|volatile|while)\b/,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[fuhl]{0,4}/i,boolean:/\b(?:false|true)\b/,"constant-opencl-kernel":{pattern:/\b(?:CHAR_(?:BIT|MAX|MIN)|CLK_(?:ADDRESS_(?:CLAMP(?:_TO_EDGE)?|NONE|REPEAT)|FILTER_(?:LINEAR|NEAREST)|(?:LOCAL|GLOBAL)_MEM_FENCE|NORMALIZED_COORDS_(?:FALSE|TRUE))|CL_(?:BGRA|(?:HALF_)?FLOAT|INTENSITY|LUMINANCE|A?R?G?B?[Ax]?|(?:(?:UN)?SIGNED|[US]NORM)_(?:INT(?:8|16|32))|UNORM_(?:INT_101010|SHORT_(?:555|565)))|(?:DBL|FLT|HALF)_(?:DIG|EPSILON|MANT_DIG|(?:MIN|MAX)(?:(?:_10)?_EXP)?)|FLT_RADIX|HUGE_VALF?|INFINITY|(?:INT|LONG|SCHAR|SHRT)_(?:MAX|MIN)|(?:UCHAR|USHRT|UINT|ULONG)_MAX|MAXFLOAT|M_(?:[12]_PI|2_SQRTPI|E|LN(?:2|10)|LOG(?:10|2)E?|PI(?:_[24])?|SQRT(?:1_2|2))(?:_F|_H)?|NAN)\b/,alias:"constant"}}),E.languages.insertBefore("opencl","class-name",{"builtin-type":{pattern:/\b(?:_cl_(?:command_queue|context|device_id|event|kernel|mem|platform_id|program|sampler)|cl_(?:image_format|mem_fence_flags)|clk_event_t|event_t|image(?:1d_(?:array_|buffer_)?t|2d_(?:array_(?:depth_|msaa_depth_|msaa_)?|depth_|msaa_depth_|msaa_)?t|3d_t)|intptr_t|ndrange_t|ptrdiff_t|queue_t|reserve_id_t|sampler_t|size_t|uintptr_t)\b/,alias:"keyword"}});var _={"type-opencl-host":{pattern:/\b(?:cl_(?:GLenum|GLint|GLuin|addressing_mode|bitfield|bool|buffer_create_type|build_status|channel_(?:order|type)|(?:u?(?:char|short|int|long)|float|double)(?:2|3|4|8|16)?|command_(?:queue(?:_info|_properties)?|type)|context(?:_info|_properties)?|device_(?:exec_capabilities|fp_config|id|info|local_mem_type|mem_cache_type|type)|(?:event|sampler)(?:_info)?|filter_mode|half|image_info|kernel(?:_info|_work_group_info)?|map_flags|mem(?:_flags|_info|_object_type)?|platform_(?:id|info)|profiling_info|program(?:_build_info|_info)?))\b/,alias:"keyword"},"boolean-opencl-host":{pattern:/\bCL_(?:TRUE|FALSE)\b/,alias:"boolean"},"constant-opencl-host":{pattern:/\bCL_(?:A|ABGR|ADDRESS_(?:CLAMP(?:_TO_EDGE)?|MIRRORED_REPEAT|NONE|REPEAT)|ARGB|BGRA|BLOCKING|BUFFER_CREATE_TYPE_REGION|BUILD_(?:ERROR|IN_PROGRESS|NONE|PROGRAM_FAILURE|SUCCESS)|COMMAND_(?:ACQUIRE_GL_OBJECTS|BARRIER|COPY_(?:BUFFER(?:_RECT|_TO_IMAGE)?|IMAGE(?:_TO_BUFFER)?)|FILL_(?:BUFFER|IMAGE)|MAP(?:_BUFFER|_IMAGE)|MARKER|MIGRATE(?:_SVM)?_MEM_OBJECTS|NATIVE_KERNEL|NDRANGE_KERNEL|READ_(?:BUFFER(?:_RECT)?|IMAGE)|RELEASE_GL_OBJECTS|SVM_(?:FREE|MAP|MEMCPY|MEMFILL|UNMAP)|TASK|UNMAP_MEM_OBJECT|USER|WRITE_(?:BUFFER(?:_RECT)?|IMAGE))|COMPILER_NOT_AVAILABLE|COMPILE_PROGRAM_FAILURE|COMPLETE|CONTEXT_(?:DEVICES|INTEROP_USER_SYNC|NUM_DEVICES|PLATFORM|PROPERTIES|REFERENCE_COUNT)|DEPTH(?:_STENCIL)?|DEVICE_(?:ADDRESS_BITS|AFFINITY_DOMAIN_(?:L[1-4]_CACHE|NEXT_PARTITIONABLE|NUMA)|AVAILABLE|BUILT_IN_KERNELS|COMPILER_AVAILABLE|DOUBLE_FP_CONFIG|ENDIAN_LITTLE|ERROR_CORRECTION_SUPPORT|EXECUTION_CAPABILITIES|EXTENSIONS|GLOBAL_(?:MEM_(?:CACHELINE_SIZE|CACHE_SIZE|CACHE_TYPE|SIZE)|VARIABLE_PREFERRED_TOTAL_SIZE)|HOST_UNIFIED_MEMORY|IL_VERSION|IMAGE(?:2D_MAX_(?:HEIGHT|WIDTH)|3D_MAX_(?:DEPTH|HEIGHT|WIDTH)|_BASE_ADDRESS_ALIGNMENT|_MAX_ARRAY_SIZE|_MAX_BUFFER_SIZE|_PITCH_ALIGNMENT|_SUPPORT)|LINKER_AVAILABLE|LOCAL_MEM_SIZE|LOCAL_MEM_TYPE|MAX_(?:CLOCK_FREQUENCY|COMPUTE_UNITS|CONSTANT_ARGS|CONSTANT_BUFFER_SIZE|GLOBAL_VARIABLE_SIZE|MEM_ALLOC_SIZE|NUM_SUB_GROUPS|ON_DEVICE_(?:EVENTS|QUEUES)|PARAMETER_SIZE|PIPE_ARGS|READ_IMAGE_ARGS|READ_WRITE_IMAGE_ARGS|SAMPLERS|WORK_GROUP_SIZE|WORK_ITEM_DIMENSIONS|WORK_ITEM_SIZES|WRITE_IMAGE_ARGS)|MEM_BASE_ADDR_ALIGN|MIN_DATA_TYPE_ALIGN_SIZE|NAME|NATIVE_VECTOR_WIDTH_(?:CHAR|DOUBLE|FLOAT|HALF|INT|LONG|SHORT)|NOT_(?:AVAILABLE|FOUND)|OPENCL_C_VERSION|PARENT_DEVICE|PARTITION_(?:AFFINITY_DOMAIN|BY_AFFINITY_DOMAIN|BY_COUNTS|BY_COUNTS_LIST_END|EQUALLY|FAILED|MAX_SUB_DEVICES|PROPERTIES|TYPE)|PIPE_MAX_(?:ACTIVE_RESERVATIONS|PACKET_SIZE)|PLATFORM|PREFERRED_(?:GLOBAL_ATOMIC_ALIGNMENT|INTEROP_USER_SYNC|LOCAL_ATOMIC_ALIGNMENT|PLATFORM_ATOMIC_ALIGNMENT|VECTOR_WIDTH_(?:CHAR|DOUBLE|FLOAT|HALF|INT|LONG|SHORT))|PRINTF_BUFFER_SIZE|PROFILE|PROFILING_TIMER_RESOLUTION|QUEUE_(?:ON_(?:DEVICE_(?:MAX_SIZE|PREFERRED_SIZE|PROPERTIES)|HOST_PROPERTIES)|PROPERTIES)|REFERENCE_COUNT|SINGLE_FP_CONFIG|SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS|SVM_(?:ATOMICS|CAPABILITIES|COARSE_GRAIN_BUFFER|FINE_GRAIN_BUFFER|FINE_GRAIN_SYSTEM)|TYPE(?:_ACCELERATOR|_ALL|_CPU|_CUSTOM|_DEFAULT|_GPU)?|VENDOR(?:_ID)?|VERSION)|DRIVER_VERSION|EVENT_(?:COMMAND_(?:EXECUTION_STATUS|QUEUE|TYPE)|CONTEXT|REFERENCE_COUNT)|EXEC_(?:KERNEL|NATIVE_KERNEL|STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST)|FILTER_(?:LINEAR|NEAREST)|FLOAT|FP_(?:CORRECTLY_ROUNDED_DIVIDE_SQRT|DENORM|FMA|INF_NAN|ROUND_TO_INF|ROUND_TO_NEAREST|ROUND_TO_ZERO|SOFT_FLOAT)|GLOBAL|HALF_FLOAT|IMAGE_(?:ARRAY_SIZE|BUFFER|DEPTH|ELEMENT_SIZE|FORMAT|FORMAT_MISMATCH|FORMAT_NOT_SUPPORTED|HEIGHT|NUM_MIP_LEVELS|NUM_SAMPLES|ROW_PITCH|SLICE_PITCH|WIDTH)|INTENSITY|INVALID_(?:ARG_INDEX|ARG_SIZE|ARG_VALUE|BINARY|BUFFER_SIZE|BUILD_OPTIONS|COMMAND_QUEUE|COMPILER_OPTIONS|CONTEXT|DEVICE|DEVICE_PARTITION_COUNT|DEVICE_QUEUE|DEVICE_TYPE|EVENT|EVENT_WAIT_LIST|GLOBAL_OFFSET|GLOBAL_WORK_SIZE|GL_OBJECT|HOST_PTR|IMAGE_DESCRIPTOR|IMAGE_FORMAT_DESCRIPTOR|IMAGE_SIZE|KERNEL|KERNEL_ARGS|KERNEL_DEFINITION|KERNEL_NAME|LINKER_OPTIONS|MEM_OBJECT|MIP_LEVEL|OPERATION|PIPE_SIZE|PLATFORM|PROGRAM|PROGRAM_EXECUTABLE|PROPERTY|QUEUE_PROPERTIES|SAMPLER|VALUE|WORK_DIMENSION|WORK_GROUP_SIZE|WORK_ITEM_SIZE)|KERNEL_(?:ARG_(?:ACCESS_(?:NONE|QUALIFIER|READ_ONLY|READ_WRITE|WRITE_ONLY)|ADDRESS_(?:CONSTANT|GLOBAL|LOCAL|PRIVATE|QUALIFIER)|INFO_NOT_AVAILABLE|NAME|TYPE_(?:CONST|NAME|NONE|PIPE|QUALIFIER|RESTRICT|VOLATILE))|ATTRIBUTES|COMPILE_NUM_SUB_GROUPS|COMPILE_WORK_GROUP_SIZE|CONTEXT|EXEC_INFO_SVM_FINE_GRAIN_SYSTEM|EXEC_INFO_SVM_PTRS|FUNCTION_NAME|GLOBAL_WORK_SIZE|LOCAL_MEM_SIZE|LOCAL_SIZE_FOR_SUB_GROUP_COUNT|MAX_NUM_SUB_GROUPS|MAX_SUB_GROUP_SIZE_FOR_NDRANGE|NUM_ARGS|PREFERRED_WORK_GROUP_SIZE_MULTIPLE|PRIVATE_MEM_SIZE|PROGRAM|REFERENCE_COUNT|SUB_GROUP_COUNT_FOR_NDRANGE|WORK_GROUP_SIZE)|LINKER_NOT_AVAILABLE|LINK_PROGRAM_FAILURE|LOCAL|LUMINANCE|MAP_(?:FAILURE|READ|WRITE|WRITE_INVALIDATE_REGION)|MEM_(?:ALLOC_HOST_PTR|ASSOCIATED_MEMOBJECT|CONTEXT|COPY_HOST_PTR|COPY_OVERLAP|FLAGS|HOST_NO_ACCESS|HOST_PTR|HOST_READ_ONLY|HOST_WRITE_ONLY|KERNEL_READ_AND_WRITE|MAP_COUNT|OBJECT_(?:ALLOCATION_FAILURE|BUFFER|IMAGE1D|IMAGE1D_ARRAY|IMAGE1D_BUFFER|IMAGE2D|IMAGE2D_ARRAY|IMAGE3D|PIPE)|OFFSET|READ_ONLY|READ_WRITE|REFERENCE_COUNT|SIZE|SVM_ATOMICS|SVM_FINE_GRAIN_BUFFER|TYPE|USES_SVM_POINTER|USE_HOST_PTR|WRITE_ONLY)|MIGRATE_MEM_OBJECT_(?:CONTENT_UNDEFINED|HOST)|MISALIGNED_SUB_BUFFER_OFFSET|NONE|NON_BLOCKING|OUT_OF_(?:HOST_MEMORY|RESOURCES)|PIPE_(?:MAX_PACKETS|PACKET_SIZE)|PLATFORM_(?:EXTENSIONS|HOST_TIMER_RESOLUTION|NAME|PROFILE|VENDOR|VERSION)|PROFILING_(?:COMMAND_(?:COMPLETE|END|QUEUED|START|SUBMIT)|INFO_NOT_AVAILABLE)|PROGRAM_(?:BINARIES|BINARY_SIZES|BINARY_TYPE(?:_COMPILED_OBJECT|_EXECUTABLE|_LIBRARY|_NONE)?|BUILD_(?:GLOBAL_VARIABLE_TOTAL_SIZE|LOG|OPTIONS|STATUS)|CONTEXT|DEVICES|IL|KERNEL_NAMES|NUM_DEVICES|NUM_KERNELS|REFERENCE_COUNT|SOURCE)|QUEUED|QUEUE_(?:CONTEXT|DEVICE|DEVICE_DEFAULT|ON_DEVICE|ON_DEVICE_DEFAULT|OUT_OF_ORDER_EXEC_MODE_ENABLE|PROFILING_ENABLE|PROPERTIES|REFERENCE_COUNT|SIZE)|R|RA|READ_(?:ONLY|WRITE)_CACHE|RG|RGB|RGBA|RGBx|RGx|RUNNING|Rx|SAMPLER_(?:ADDRESSING_MODE|CONTEXT|FILTER_MODE|LOD_MAX|LOD_MIN|MIP_FILTER_MODE|NORMALIZED_COORDS|REFERENCE_COUNT)|(?:UN)?SIGNED_INT(?:8|16|32)|SNORM_INT(?:8|16)|SUBMITTED|SUCCESS|UNORM_INT(?:16|24|8|_101010|_101010_2)|UNORM_SHORT_(?:555|565)|VERSION_(?:1_0|1_1|1_2|2_0|2_1)|sBGRA|sRGB|sRGBA|sRGBx)\b/,alias:"constant"},"function-opencl-host":{pattern:/\bcl(?:BuildProgram|CloneKernel|CompileProgram|Create(?:Buffer|CommandQueue(?:WithProperties)?|Context|ContextFromType|Image|Image2D|Image3D|Kernel|KernelsInProgram|Pipe|ProgramWith(?:Binary|BuiltInKernels|IL|Source)|Sampler|SamplerWithProperties|SubBuffer|SubDevices|UserEvent)|Enqueue(?:(?:Barrier|Marker)(?:WithWaitList)?|Copy(?:Buffer(?:Rect|ToImage)?|Image(?:ToBuffer)?)|(?:Fill|Map)(?:Buffer|Image)|MigrateMemObjects|NDRangeKernel|NativeKernel|(?:Read|Write)(?:Buffer(?:Rect)?|Image)|SVM(?:Free|Map|MemFill|Memcpy|MigrateMem|Unmap)|Task|UnmapMemObject|WaitForEvents)|Finish|Flush|Get(?:CommandQueueInfo|ContextInfo|Device(?:AndHostTimer|IDs|Info)|Event(?:Profiling)?Info|ExtensionFunctionAddress(?:ForPlatform)?|HostTimer|ImageInfo|Kernel(?:ArgInfo|Info|SubGroupInfo|WorkGroupInfo)|MemObjectInfo|PipeInfo|Platform(?:IDs|Info)|Program(?:Build)?Info|SamplerInfo|SupportedImageFormats)|LinkProgram|(?:Release|Retain)(?:CommandQueue|Context|Device|Event|Kernel|MemObject|Program|Sampler)|SVM(?:Alloc|Free)|Set(?:CommandQueueProperty|DefaultDeviceCommandQueue|EventCallback|Kernel(?:Arg(?:SVMPointer)?|ExecInfo)|Kernel|MemObjectDestructorCallback|UserEventStatus)|Unload(?:Platform)?Compiler|WaitForEvents)\b/,alias:"function"}};E.languages.insertBefore("c","keyword",_),E.languages.cpp&&(_["type-opencl-host-cpp"]={pattern:/\b(?:Buffer|BufferGL|BufferRenderGL|CommandQueue|Context|Device|DeviceCommandQueue|EnqueueArgs|Event|Image|Image1D|Image1DArray|Image1DBuffer|Image2D|Image2DArray|Image2DGL|Image3D|Image3DGL|ImageFormat|ImageGL|Kernel|KernelFunctor|LocalSpaceArg|Memory|NDRange|Pipe|Platform|Program|Sampler|SVMAllocator|SVMTraitAtomic|SVMTraitCoarse|SVMTraitFine|SVMTraitReadOnly|SVMTraitReadWrite|SVMTraitWriteOnly|UserEvent)\b/,alias:"keyword"},E.languages.insertBefore("cpp","keyword",_))}(Prism); Prism.languages.openqasm={comment:/\/\*[\s\S]*?\*\/|\/\/.*/,string:{pattern:/"[^"\r\n\t]*"|'[^'\r\n\t]*'/,greedy:!0},keyword:/\b(?:barrier|boxas|boxto|break|const|continue|ctrl|def|defcal|defcalgrammar|delay|else|end|for|gate|gphase|if|in|include|inv|kernel|lengthof|let|measure|pow|reset|return|rotary|stretchinf|while|CX|OPENQASM|U)\b|#pragma\b/,"class-name":/\b(?:angle|bit|bool|creg|fixed|float|int|length|qreg|qubit|stretch|uint)\b/,function:/\b(?:sin|cos|tan|exp|ln|sqrt|rotl|rotr|popcount)\b(?=\s*\()/,constant:/\b(?:pi|tau|euler)\b|π|𝜏|ℇ/,number:{pattern:/(^|[^.\w$])(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?(?:dt|ns|us|µs|ms|s)?/i,lookbehind:!0},operator:/->|>>=?|<<=?|&&|\|\||\+\+|--|[!=<>&|~^+\-*/%]=?|@/,punctuation:/[(){}\[\];,:.]/},Prism.languages.qasm=Prism.languages.openqasm; Prism.languages.oz={comment:/\/\*[\s\S]*?\*\/|%.*/,string:{pattern:/"(?:[^"\\]|\\[\s\S])*"/,greedy:!0},atom:{pattern:/'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,alias:"builtin"},keyword:/\$|\[\]|\b(?:_|at|attr|case|catch|choice|class|cond|declare|define|dis|else(?:case|if)?|end|export|fail|false|feat|finally|from|fun|functor|if|import|in|local|lock|meth|nil|not|of|or|prepare|proc|prop|raise|require|self|skip|then|thread|true|try|unit)\b/,function:[/\b[a-z][A-Za-z\d]*(?=\()/,{pattern:/(\{)[A-Z][A-Za-z\d]*\b/,lookbehind:!0}],number:/\b(?:0[bx][\da-f]+|\d+(?:\.\d*)?(?:e~?\d+)?)\b|&(?:[^\\]|\\(?:\d{3}|.))/i,variable:/\b[A-Z][A-Za-z\d]*|`(?:[^`\\]|\\.)+`/,"attr-name":/\b\w+(?=:)/,operator:/:(?:=|::?)|<[-:=]?|=(?:=|=?:?|\\=:?|!!?|[|#+\-*\/,~^@]|\b(?:andthen|div|mod|orelse)\b/,punctuation:/[\[\](){}.:;?]/}; Prism.languages.parigp={comment:/\/\*[\s\S]*?\*\/|\\\\.*/,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"/,greedy:!0},keyword:function(){var r=["breakpoint","break","dbg_down","dbg_err","dbg_up","dbg_x","forcomposite","fordiv","forell","forpart","forprime","forstep","forsubgroup","forvec","for","iferr","if","local","my","next","return","until","while"];return r=r.map(function(r){return r.split("").join(" *")}).join("|"),RegExp("\\b(?:"+r+")\\b")}(),function:/\b\w(?:[\w ]*\w)?(?= *\()/,number:{pattern:/((?:\. *\. *)?)(?:\b\d(?: *\d)*(?: *(?!\. *\.)\.(?: *\d)*)?|\. *\d(?: *\d)*)(?: *e *(?:[+-] *)?\d(?: *\d)*)?/i,lookbehind:!0},operator:/\. *\.|[*\/!](?: *=)?|%(?: *=|(?: *#)?(?: *')*)?|\+(?: *[+=])?|-(?: *[-=>])?|<(?: *>|(?: *<)?(?: *=)?)?|>(?: *>)?(?: *=)?|=(?: *=){0,2}|\\(?: *\/)?(?: *=)?|&(?: *&)?|\| *\||['#~^]/,punctuation:/[\[\]{}().,:;|]/}; !function(e){var n=e.languages.parser=e.languages.extend("markup",{keyword:{pattern:/(^|[^^])(?:\^(?:case|eval|for|if|switch|throw)\b|@(?:BASE|CLASS|GET(?:_DEFAULT)?|OPTIONS|SET_DEFAULT|USE)\b)/,lookbehind:!0},variable:{pattern:/(^|[^^])\B\$(?:\w+|(?=[.{]))(?:(?:\.|::?)\w+)*(?:\.|::?)?/,lookbehind:!0,inside:{punctuation:/\.|:+/}},function:{pattern:/(^|[^^])\B[@^]\w+(?:(?:\.|::?)\w+)*(?:\.|::?)?/,lookbehind:!0,inside:{keyword:{pattern:/(^@)(?:GET_|SET_)/,lookbehind:!0},punctuation:/\.|:+/}},escape:{pattern:/\^(?:[$^;@()\[\]{}"':]|#[a-f\d]*)/i,alias:"builtin"},punctuation:/[\[\](){};]/});n=e.languages.insertBefore("parser","keyword",{"parser-comment":{pattern:/(\s)#.*/,lookbehind:!0,alias:"comment"},expression:{pattern:/(^|[^^])\((?:[^()]|\((?:[^()]|\((?:[^()])*\))*\))*\)/,greedy:!0,lookbehind:!0,inside:{string:{pattern:/(^|[^^])(["'])(?:(?!\2)[^^]|\^[\s\S])*\2/,lookbehind:!0},keyword:n.keyword,variable:n.variable,function:n.function,boolean:/\b(?:true|false)\b/,number:/\b(?:0x[a-f\d]+|\d+(?:\.\d*)?(?:e[+-]?\d+)?)\b/i,escape:n.escape,operator:/[~+*\/\\%]|!(?:\|\|?|=)?|&&?|\|\|?|==|<[<=]?|>[>=]?|-[fd]?|\b(?:def|eq|ge|gt|in|is|le|lt|ne)\b/,punctuation:n.punctuation}}}),e.languages.insertBefore("inside","punctuation",{expression:n.expression,keyword:n.keyword,variable:n.variable,function:n.function,escape:n.escape,"parser-punctuation":{pattern:n.punctuation,alias:"punctuation"}},n.tag.inside["attr-value"])}(Prism); Prism.languages.pascal={comment:[/\(\*[\s\S]+?\*\)/,/\{[\s\S]+?\}/,/\/\/.*/],string:{pattern:/(?:'(?:''|[^'\r\n])*'(?!')|#[&$%]?[a-f\d]+)+|\^[a-z]/i,greedy:!0},keyword:[{pattern:/(^|[^&])\b(?:absolute|array|asm|begin|case|const|constructor|destructor|do|downto|else|end|file|for|function|goto|if|implementation|inherited|inline|interface|label|nil|object|of|operator|packed|procedure|program|record|reintroduce|repeat|self|set|string|then|to|type|unit|until|uses|var|while|with)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:dispose|exit|false|new|true)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:class|dispinterface|except|exports|finalization|finally|initialization|inline|library|on|out|packed|property|raise|resourcestring|threadvar|try)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:absolute|abstract|alias|assembler|bitpacked|break|cdecl|continue|cppdecl|cvar|default|deprecated|dynamic|enumerator|experimental|export|external|far|far16|forward|generic|helper|implements|index|interrupt|iochecks|local|message|name|near|nodefault|noreturn|nostackframe|oldfpccall|otherwise|overload|override|pascal|platform|private|protected|public|published|read|register|reintroduce|result|safecall|saveregisters|softfloat|specialize|static|stdcall|stored|strict|unaligned|unimplemented|varargs|virtual|write)\b/i,lookbehind:!0}],number:[/(?:[&%]\d+|\$[a-f\d]+)/i,/\b\d+(?:\.\d+)?(?:e[+-]?\d+)?/i],operator:[/\.\.|\*\*|:=|<[<=>]?|>[>=]?|[+\-*\/]=?|[@^=]/i,{pattern:/(^|[^&])\b(?:and|as|div|exclude|in|include|is|mod|not|or|shl|shr|xor)\b/,lookbehind:!0}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/},Prism.languages.objectpascal=Prism.languages.pascal; !function(e){var n="(?:\\b\\w+(?:)?|)".replace(//g,function(){return"\\((?:[^()]|\\((?:[^()]|\\([^()]*\\))*\\))*\\)"}),t=e.languages.pascaligo={comment:/\(\*[\s\S]+?\*\)|\/\/.*/,string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1|\^[a-z]/i,greedy:!0},"class-name":[{pattern:RegExp("(\\btype\\s+\\w+\\s+is\\s+)".replace(//g,function(){return n}),"i"),lookbehind:!0,inside:null},{pattern:RegExp("(?=\\s+is\\b)".replace(//g,function(){return n}),"i"),inside:null},{pattern:RegExp("(:\\s*)".replace(//g,function(){return n})),lookbehind:!0,inside:null}],keyword:{pattern:/(^|[^&])\b(?:begin|block|case|const|else|end|fail|for|from|function|if|is|nil|of|remove|return|skip|then|type|var|while|with)\b/i,lookbehind:!0},boolean:{pattern:/(^|[^&])\b(?:True|False)\b/i,lookbehind:!0},builtin:{pattern:/(^|[^&])\b(?:bool|int|list|map|nat|record|string|unit)\b/i,lookbehind:!0},function:/\b\w+(?=\s*\()/i,number:[/%[01]+|&[0-7]+|\$[a-f\d]+/i,/\b\d+(?:\.\d+)?(?:e[+-]?\d+)?(?:mtz|n)?/i],operator:/->|=\/=|\.\.|\*\*|:=|<[<=>]?|>[>=]?|[+\-*\/]=?|[@^=|]|\b(?:and|mod|or)\b/,punctuation:/\(\.|\.\)|[()\[\]:;,.{}]/},i=["comment","keyword","builtin","operator","punctuation"].reduce(function(e,n){return e[n]=t[n],e},{});t["class-name"].forEach(function(e){e.inside=i})}(Prism); Prism.languages.psl={comment:{pattern:/#.*/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"])*"/,greedy:!0,inside:{symbol:/\\[ntrbA-Z"\\]/}},"heredoc-string":{pattern:/<<<([a-zA-Z_]\w*)[\r\n](?:.*[\r\n])*?\1\b/,alias:"string",greedy:!0},keyword:/\b(?:__multi|__single|case|default|do|else|elsif|exit|export|for|foreach|function|if|last|line|local|next|requires|return|switch|until|while|word)\b/,constant:/\b(?:ALARM|CHART_ADD_GRAPH|CHART_DELETE_GRAPH|CHART_DESTROY|CHART_LOAD|CHART_PRINT|EOF|FALSE|False|false|NO|No|no|OFFLINE|OK|PSL_PROF_LOG|R_CHECK_HORIZ|R_CHECK_VERT|R_CLICKER|R_COLUMN|R_FRAME|R_ICON|R_LABEL|R_LABEL_CENTER|R_LIST_MULTIPLE|R_LIST_MULTIPLE_ND|R_LIST_SINGLE|R_LIST_SINGLE_ND|R_MENU|R_POPUP|R_POPUP_SCROLLED|R_RADIO_HORIZ|R_RADIO_VERT|R_ROW|R_SCALE_HORIZ|R_SCALE_VERT|R_SPINNER|R_TEXT_FIELD|R_TEXT_FIELD_LABEL|R_TOGGLE|TRIM_LEADING|TRIM_LEADING_AND_TRAILING|TRIM_REDUNDANT|TRIM_TRAILING|TRUE|True|true|VOID|WARN)\b/,variable:/\b(?:errno|exit_status|PslDebug)\b/,builtin:{pattern:/\b(?:acos|add_diary|annotate|annotate_get|asctime|asin|atan|atexit|ascii_to_ebcdic|batch_set|blackout|cat|ceil|chan_exists|change_state|close|code_cvt|cond_signal|cond_wait|console_type|convert_base|convert_date|convert_locale_date|cos|cosh|create|destroy_lock|dump_hist|date|destroy|difference|dget_text|dcget_text|ebcdic_to_ascii|encrypt|event_archive|event_catalog_get|event_check|event_query|event_range_manage|event_range_query|event_report|event_schedule|event_trigger|event_trigger2|execute|exists|exp|fabs|floor|fmod|full_discovery|file|fopen|ftell|fseek|grep|get_vars|getenv|get|get_chan_info|get_ranges|get_text|gethostinfo|getpid|getpname|history_get_retention|history|index|int|is_var|intersection|isnumber|internal|in_transition|join|kill|length|lines|lock|lock_info|log|loge|log10|matchline|msg_check|msg_get_format|msg_get_severity|msg_printf|msg_sprintf|ntharg|num_consoles|nthargf|nthline|nthlinef|num_bytes|print|proc_exists|process|popen|printf|pconfig|poplines|pow|PslExecute|PslFunctionCall|PslFunctionExists|PslSetOptions|random|read|readln|refresh_parameters|remote_check|remote_close|remote_event_query|remote_event_trigger|remote_file_send|remote_open|remove|replace|rindex|sec_check_priv|sec_store_get|sec_store_set|set_alarm_ranges|set_locale|share|sin|sinh|sleep|sopen|sqrt|srandom|subset|set|substr|system|sprintf|sort|snmp_agent_config|_snmp_debug|snmp_agent_stop|snmp_agent_start|snmp_h_set|snmp_h_get_next|snmp_h_get|snmp_set|snmp_walk|snmp_get_next|snmp_get|snmp_config|snmp_close|snmp_open|snmp_trap_receive|snmp_trap_ignore|snmp_trap_listen|snmp_trap_send|snmp_trap_raise_std_trap|snmp_trap_register_im|splitline|strcasecmp|str_repeat|trim|tail|tan|tanh|time|tmpnam|tolower|toupper|trace_psl_process|text_domain|unlock|unique|union|unset|va_arg|va_start|write)\b/,alias:"builtin-function"},"foreach-variable":{pattern:/(\bforeach\s+(?:(?:\w+\b|"(?:\\.|[^\\"])*")\s+){0,2})[_a-zA-Z]\w*(?=\s*\()/,lookbehind:!0,greedy:!0},function:{pattern:/\b[_a-z]\w*\b(?=\s*\()/i},number:/\b(?:0x[0-9a-f]+|[0-9]+(?:\.[0-9]+)?)\b/i,operator:/--|\+\+|&&=?|\|\|=?|<<=?|>>=?|[=!]~|[-+*/%&|^!=<>]=?|\.|[:?]/,punctuation:/[(){}\[\];,]/}; Prism.languages.pcaxis={string:/"[^"]*"/,keyword:{pattern:/((?:^|;)\s*)[-A-Z\d]+(?:\s*\[[-\w]+\])?(?:\s*\("[^"]*"(?:,\s*"[^"]*")*\))?(?=\s*=)/,lookbehind:!0,greedy:!0,inside:{keyword:/^[-A-Z\d]+/,language:{pattern:/^(\s*)\[[-\w]+\]/,lookbehind:!0,inside:{punctuation:/^\[|\]$/,property:/[-\w]+/}},"sub-key":{pattern:/^(\s*)\S[\s\S]*/,lookbehind:!0,inside:{parameter:{pattern:/"[^"]*"/,alias:"property"},punctuation:/^\(|\)$|,/}}}},operator:/=/,tlist:{pattern:/TLIST\s*\(\s*\w+(?:(?:\s*,\s*"[^"]*")+|\s*,\s*"[^"]*"-"[^"]*")?\s*\)/,greedy:!0,inside:{function:/^TLIST/,property:{pattern:/^(\s*\(\s*)\w+/,lookbehind:!0},string:/"[^"]*"/,punctuation:/[(),]/,operator:/-/}},punctuation:/[;,]/,number:{pattern:/(^|\s)\d+(?:\.\d+)?(?!\S)/,lookbehind:!0},boolean:/YES|NO/},Prism.languages.px=Prism.languages.pcaxis; Prism.languages.peoplecode={comment:RegExp(["/\\*[^]*?\\*/","\\bREM[^;]*;","<\\*(?:[^<*]|\\*(?!>)|<(?!\\*)|<\\*(?:(?!\\*>)[^])*\\*>)*\\*>","/\\+[^]*?\\+/"].join("|")),string:{pattern:/'(?:''|[^'\r\n])*'(?!')|"(?:""|[^"\r\n])*"(?!")/,greedy:!0},variable:/%\w+/,"function-definition":{pattern:/((?:^|[^\w-])(?:function|method)\s+)\w+/i,lookbehind:!0,alias:"function"},"class-name":{pattern:/((?:^|[^-\w])(?:as|catch|class|component|create|extends|global|implements|instance|local|of|property|returns)\s+)\w+(?::\w+)*/i,lookbehind:!0,inside:{punctuation:/:/}},keyword:/\b(?:abstract|alias|as|catch|class|component|constant|create|declare|else|end-(?:class|evaluate|for|function|get|if|method|set|try|while)|evaluate|extends|for|function|get|global|implements|import|instance|if|library|local|method|null|of|out|peopleCode|private|program|property|protected|readonly|ref|repeat|returns?|set|step|then|throw|to|try|until|value|when(?:-other)?|while)\b/i,"operator-keyword":{pattern:/\b(?:and|not|or)\b/i,alias:"operator"},function:/[_a-z]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/i,number:/\b\d+(?:\.\d+)?\b/,operator:/<>|[<>]=?|!=|\*\*|[-+*/|=@]/,punctuation:/[:.;,()[\]]/},Prism.languages.pcode=Prism.languages.peoplecode; Prism.languages.perl={comment:[{pattern:/(^\s*)=\w[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+(?![\w$]))+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],fileHandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},function:{pattern:/sub \w+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|return|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; !function(a){var e="(?:\\b[a-zA-Z]\\w*|[|\\\\[\\]])+";a.languages.phpdoc=a.languages.extend("javadoclike",{parameter:{pattern:RegExp("(@(?:global|param|property(?:-read|-write)?|var)\\s+(?:"+e+"\\s+)?)\\$\\w+"),lookbehind:!0}}),a.languages.insertBefore("phpdoc","keyword",{"class-name":[{pattern:RegExp("(@(?:global|package|param|property(?:-read|-write)?|return|subpackage|throws|var)\\s+)"+e),lookbehind:!0,inside:{keyword:/\b(?:callback|resource|boolean|integer|double|object|string|array|false|float|mixed|bool|null|self|true|void|int)\b/,punctuation:/[|\\[\]()]/}}]}),a.languages.javadoclike.addSupport("php",a.languages.phpdoc)}(Prism); Prism.languages.insertBefore("php","variable",{this:/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/static|self|parent/,punctuation:/::|\\/}}}); !function(E){var A=E.languages.plsql=E.languages.extend("sql",{comment:[/\/\*[\s\S]*?\*\//,/--.*/]}),T=A.keyword;Array.isArray(T)||(T=A.keyword=[T]),T.unshift(/\b(?:ACCESS|AGENT|AGGREGATE|ARRAY|ARROW|AT|ATTRIBUTE|AUDIT|AUTHID|BFILE_BASE|BLOB_BASE|BLOCK|BODY|BOTH|BOUND|BYTE|CALLING|CHAR_BASE|CHARSET(?:FORM|ID)|CLOB_BASE|COLAUTH|COLLECT|CLUSTERS?|COMPILED|COMPRESS|CONSTANT|CONSTRUCTOR|CONTEXT|CRASH|CUSTOMDATUM|DANGLING|DATE_BASE|DEFINE|DETERMINISTIC|DURATION|ELEMENT|EMPTY|EXCEPTIONS?|EXCLUSIVE|EXTERNAL|FINAL|FORALL|FORM|FOUND|GENERAL|HEAP|HIDDEN|IDENTIFIED|IMMEDIATE|INCLUDING|INCREMENT|INDICATOR|INDEXES|INDICES|INFINITE|INITIAL|ISOPEN|INSTANTIABLE|INTERFACE|INVALIDATE|JAVA|LARGE|LEADING|LENGTH|LIBRARY|LIKE[24C]|LIMITED|LONG|LOOP|MAP|MAXEXTENTS|MAXLEN|MEMBER|MINUS|MLSLABEL|MULTISET|NAME|NAN|NATIVE|NEW|NOAUDIT|NOCOMPRESS|NOCOPY|NOTFOUND|NOWAIT|NUMBER(?:_BASE)?|OBJECT|OCI(?:COLL|DATE|DATETIME|DURATION|INTERVAL|LOBLOCATOR|NUMBER|RAW|REF|REFCURSOR|ROWID|STRING|TYPE)|OFFLINE|ONLINE|ONLY|OPAQUE|OPERATOR|ORACLE|ORADATA|ORGANIZATION|ORL(?:ANY|VARY)|OTHERS|OVERLAPS|OVERRIDING|PACKAGE|PARALLEL_ENABLE|PARAMETERS?|PASCAL|PCTFREE|PIPE(?:LINED)?|PRAGMA|PRIOR|PRIVATE|RAISE|RANGE|RAW|RECORD|REF|REFERENCE|REM|REMAINDER|RESULT|RESOURCE|RETURNING|REVERSE|ROW(?:ID|NUM|TYPE)|SAMPLE|SB[124]|SEGMENT|SELF|SEPARATE|SEQUENCE|SHORT|SIZE(?:_T)?|SPARSE|SQL(?:CODE|DATA|NAME|STATE)|STANDARD|STATIC|STDDEV|STORED|STRING|STRUCT|STYLE|SUBMULTISET|SUBPARTITION|SUBSTITUTABLE|SUBTYPE|SUCCESSFUL|SYNONYM|SYSDATE|TABAUTH|TDO|THE|TIMEZONE_(?:ABBR|HOUR|MINUTE|REGION)|TRAILING|TRANSAC(?:TIONAL)?|TRUSTED|UB[124]|UID|UNDER|UNTRUSTED|VALIDATE|VALIST|VARCHAR2|VARIABLE|VARIANCE|VARRAY|VIEWS|VOID|WHENEVER|WRAPPED|ZONE)\b/i);var R=A.operator;Array.isArray(R)||(R=A.operator=[R]),R.unshift(/:=/)}(Prism); Prism.languages.powerquery={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:\/\/).*)/,lookbehind:!0},"quoted-identifier":{pattern:/#"(?:[^"\r\n]|"")*"(?!")/,greedy:!0,alias:"variable"},string:{pattern:/"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},constant:[/\bDay\.(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)\b/,/\bTraceLevel\.(?:Critical|Error|Information|Verbose|Warning)\b/,/\bOccurrence\.(?:First|Last|All)\b/,/\bOrder\.(?:Ascending|Descending)\b/,/\bRoundingMode\.(?:AwayFromZero|Down|ToEven|TowardZero|Up)\b/,/\bMissingField\.(?:Error|Ignore|UseNull)\b/,/\bQuoteStyle\.(?:Csv|None)\b/,/\bJoinKind\.(?:Inner|LeftOuter|RightOuter|FullOuter|LeftAnti|RightAnti)\b/,/\bGroupKind\.(?:Global|Local)\b/,/\bExtraValues\.(?:List|Ignore|Error)\b/,/\bJoinAlgorithm\.(?:Dynamic|PairwiseHash|SortMerge|LeftHash|RightHash|LeftIndex|RightIndex)\b/,/\bJoinSide\.(?:Left|Right)\b/,/\bPrecision\.(?:Double|Decimal)\b/,/\bRelativePosition\.From(?:End|Start)\b/,/\bTextEncoding\.(?:Ascii|BigEndianUnicode|Unicode|Utf8|Utf16|Windows)\b/,/\b(?:Any|Binary|Date|DateTime|DateTimeZone|Duration|Int8|Int16|Int32|Int64|Function|List|Logical|None|Number|Record|Table|Text|Time)\.Type\b/,/\bnull\b/],boolean:/\b(?:true|false)\b/,keyword:/\b(?:and|as|each|else|error|if|in|is|let|meta|not|nullable|optional|or|otherwise|section|shared|then|try|type)\b|#(?:binary|date|datetime|datetimezone|duration|infinity|nan|sections|shared|table|time)\b/,function:{pattern:/(^|[^#\w.])(?!\d)[\w.]+(?=\s*\()/,lookbehind:!0},"data-type":{pattern:/\b(?:any|anynonnull|binary|date|datetime|datetimezone|duration|function|list|logical|none|number|record|table|text|time|type)\b/,alias:"variable"},number:{pattern:/\b0x[\da-f]+\b|(?:[+-]?(?:\b\d+\.)?\b\d+|[+-]\.\d+|(^|[^.])\B\.\d+)(?:e[+-]?\d+)?\b/i,lookbehind:!0},operator:/[-+*\/&?@^]|<(?:=>?|>)?|>=?|=>?|\.\.\.?/,punctuation:/[,;\[\](){}]/},Prism.languages.pq=Prism.languages.powerquery,Prism.languages.mscript=Prism.languages.powerquery; !function(e){var i=Prism.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:{function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:{}}}},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:true|false)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(\W?)(?:!|-(?:eq|ne|gt|ge|lt|le|sh[lr]|not|b?(?:and|x?or)|(?:Not)?(?:Like|Match|Contains|In)|Replace|Join|is(?:Not)?|as)\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/},r=i.string[0].inside;r.boolean=i.boolean,r.variable=i.variable,r.function.inside=i}(); Prism.languages.processing=Prism.languages.extend("clike",{keyword:/\b(?:break|catch|case|class|continue|default|else|extends|final|for|if|implements|import|new|null|private|public|return|static|super|switch|this|try|void|while)\b/,operator:/<[<=]?|>[>=]?|&&?|\|\|?|[%?]|[!=+\-*\/]=?/}),Prism.languages.insertBefore("processing","number",{constant:/\b(?!XML\b)[A-Z][A-Z\d_]+\b/,type:{pattern:/\b(?:boolean|byte|char|color|double|float|int|[A-Z]\w*)\b/,alias:"variable"}}),Prism.languages.processing.function=/\b\w+(?=\s*\()/,Prism.languages.processing["class-name"].alias="variable"; Prism.languages.prolog={comment:[/%.+/,/\/\*[\s\S]*?\*\//],string:{pattern:/(["'])(?:\1\1|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\b(?:fx|fy|xf[xy]?|yfx?)\b/,variable:/\b[A-Z_]\w*/,function:/\b[a-z]\w*(?:(?=\()|\/\d+)/,number:/\b\d+(?:\.\d*)?/,operator:/[:\\=><\-?*@\/;+^|!$.]+|\b(?:is|mod|not|xor)\b/,punctuation:/[(){}\[\],]/}; !function(t){var n=["on","ignoring","group_right","group_left","by","without"],a=["sum","min","max","avg","group","stddev","stdvar","count","count_values","bottomk","topk","quantile"].concat(n,["offset"]);t.languages.promql={comment:{pattern:/(^[ \t]*)#.*/m,lookbehind:!0},"vector-match":{pattern:new RegExp("((?:"+n.join("|")+")\\s*)\\([^)]*\\)"),lookbehind:!0,inside:{"label-key":{pattern:/\b[^,]*\b/,alias:"attr-name"},punctuation:/[(),]/}},"context-labels":{pattern:/\{[^{}]*\}/,inside:{"label-key":{pattern:/\b[a-z_]\w*(?=\s*(?:=|![=~]))/,alias:"attr-name"},"label-value":{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0,alias:"attr-value"},punctuation:/\{|\}|=~?|![=~]|,/}},"context-range":[{pattern:/\[[\w\s:]+\]/,inside:{punctuation:/\[|\]|:/,"range-duration":{pattern:/\b(?:\d+(?:[smhdwy]|ms))+\b/i,alias:"number"}}},{pattern:/(\boffset\s+)\w+/,lookbehind:!0,inside:{"range-duration":{pattern:/\b(?:\d+(?:[smhdwy]|ms))+\b/i,alias:"number"}}}],keyword:new RegExp("\\b(?:"+a.join("|")+")\\b","i"),function:/\b[a-z_]\w*(?=\s*\()/i,number:/[-+]?(?:(?:\b\d+(?:\.\d+)?|\B\.\d+)(?:e[-+]?\d+)?\b|\b(?:0x[0-9a-f]+|nan|inf)\b)/i,operator:/[\^*/%+-]|==|!=|<=|<|>=|>|\b(?:and|unless|or)\b/i,punctuation:/[{};()`,.[\]]/}}(Prism); Prism.languages.properties={comment:/^[ \t]*[#!].*$/m,"attr-value":{pattern:/(^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?: *[=:] *(?! )| ))(?:\\(?:\r\n|[\s\S])|[^\\\r\n])+/m,lookbehind:!0},"attr-name":/^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?= *[=:]| )/m,punctuation:/[=:]/}; !function(e){var s=/\b(?:double|float|[su]?int(?:32|64)|s?fixed(?:32|64)|bool|string|bytes)\b/;e.languages.protobuf=e.languages.extend("clike",{"class-name":[{pattern:/(\b(?:enum|extend|message|service)\s+)[A-Za-z_]\w*(?=\s*\{)/,lookbehind:!0},{pattern:/(\b(?:rpc\s+\w+|returns)\s*\(\s*(?:stream\s+)?)\.?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?=\s*\))/,lookbehind:!0}],keyword:/\b(?:enum|extend|extensions|import|message|oneof|option|optional|package|public|repeated|required|reserved|returns|rpc(?=\s+\w)|service|stream|syntax|to)\b(?!\s*=\s*\d)/,function:/\b[a-z_]\w*(?=\s*\()/i}),e.languages.insertBefore("protobuf","operator",{map:{pattern:/\bmap<\s*[\w.]+\s*,\s*[\w.]+\s*>(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/[<>.,]/,builtin:s}},builtin:s,"positional-class-name":{pattern:/(?:\b|\B\.)[a-z_]\w*(?:\.[a-z_]\w*)*(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/\./}},annotation:{pattern:/(\[\s*)[a-z_]\w*(?=\s*=)/i,lookbehind:!0}})}(Prism); !function(e){e.languages.pug={comment:{pattern:/(^([\t ]*))\/\/.*(?:(?:\r?\n|\r)\2[\t ].+)*/m,lookbehind:!0},"multiline-script":{pattern:/(^([\t ]*)script\b.*\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:e.languages.javascript},filter:{pattern:/(^([\t ]*)):.+(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"}}},"multiline-plain-text":{pattern:/(^([\t ]*)[\w\-#.]+\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0},markup:{pattern:/(^[\t ]*)<.+/m,lookbehind:!0,inside:e.languages.markup},doctype:{pattern:/((?:^|\n)[\t ]*)doctype(?: .+)?/,lookbehind:!0},"flow-control":{pattern:/(^[\t ]*)(?:if|unless|else|case|when|default|each|while)\b(?: .+)?/m,lookbehind:!0,inside:{each:{pattern:/^each .+? in\b/,inside:{keyword:/\b(?:each|in)\b/,punctuation:/,/}},branch:{pattern:/^(?:if|unless|else|case|when|default|while)\b/,alias:"keyword"},rest:e.languages.javascript}},keyword:{pattern:/(^[\t ]*)(?:block|extends|include|append|prepend)\b.+/m,lookbehind:!0},mixin:[{pattern:/(^[\t ]*)mixin .+/m,lookbehind:!0,inside:{keyword:/^mixin/,function:/\w+(?=\s*\(|\s*$)/,punctuation:/[(),.]/}},{pattern:/(^[\t ]*)\+.+/m,lookbehind:!0,inside:{name:{pattern:/^\+\w+/,alias:"function"},rest:e.languages.javascript}}],script:{pattern:/(^[\t ]*script(?:(?:&[^(]+)?\([^)]+\))*[\t ]).+/m,lookbehind:!0,inside:e.languages.javascript},"plain-text":{pattern:/(^[\t ]*(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?[\t ]).+/m,lookbehind:!0},tag:{pattern:/(^[\t ]*)(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?:?/m,lookbehind:!0,inside:{attributes:[{pattern:/&[^(]+\([^)]+\)/,inside:e.languages.javascript},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*(?!\s))(?:\{[^}]*\}|[^,)\r\n]+)/,lookbehind:!0,inside:e.languages.javascript},"attr-name":/[\w-]+(?=\s*!?=|\s*[,)])/,punctuation:/[!=(),]+/}}],punctuation:/:/,"attr-id":/#[\w\-]+/,"attr-class":/\.[\w\-]+/}},code:[{pattern:/(^[\t ]*(?:-|!?=)).+/m,lookbehind:!0,inside:e.languages.javascript}],punctuation:/[.\-!=|]+/};for(var t=[{filter:"atpl",language:"twig"},{filter:"coffee",language:"coffeescript"},"ejs","handlebars","less","livescript","markdown",{filter:"sass",language:"scss"},"stylus"],n={},a=0,i=t.length;a(?:(?:\r?\n|\r(?!\n))(?:\\2[\t ].+|\\s*?(?=\r?\n|\r)))+".replace("",function(){return r.filter}),"m"),lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"},rest:e.languages[r.language]}})}e.languages.insertBefore("pug","filter",n)}(Prism); !function(e){e.languages.puppet={heredoc:[{pattern:/(@\("([^"\r\n\/):]+)"(?:\/[nrts$uL]*)?\).*(?:\r?\n|\r))(?:.*(?:\r?\n|\r(?!\n)))*?[ \t]*(?:\|[ \t]*)?(?:-[ \t]*)?\2/,lookbehind:!0,alias:"string",inside:{punctuation:/(?=\S).*\S(?= *$)/}},{pattern:/(@\(([^"\r\n\/):]+)(?:\/[nrts$uL]*)?\).*(?:\r?\n|\r))(?:.*(?:\r?\n|\r(?!\n)))*?[ \t]*(?:\|[ \t]*)?(?:-[ \t]*)?\2/,lookbehind:!0,greedy:!0,alias:"string",inside:{punctuation:/(?=\S).*\S(?= *$)/}},{pattern:/@\("?(?:[^"\r\n\/):]+)"?(?:\/[nrts$uL]*)?\)/,alias:"string",inside:{punctuation:{pattern:/(\().+?(?=\))/,lookbehind:!0}}}],"multiline-comment":{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,greedy:!0,alias:"comment"},regex:{pattern:/((?:\bnode\s+|[~=\(\[\{,]\s*|[=+]>\s*|^\s*))\/(?:[^\/\\]|\\[\s\S])+\/(?:[imx]+\b|\B)/,lookbehind:!0,greedy:!0,inside:{"extended-regex":{pattern:/^\/(?:[^\/\\]|\\[\s\S])+\/[im]*x[im]*$/,inside:{comment:/#.*/}}}},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},string:{pattern:/(["'])(?:\$\{(?:[^'"}]|(["'])(?:(?!\2)[^\\]|\\[\s\S])*\2)+\}|\$(?!\{)|(?!\1)[^\\$]|\\[\s\S])*\1/,greedy:!0,inside:{"double-quoted":{pattern:/^"[\s\S]*"$/,inside:{}}}},variable:{pattern:/\$(?:::)?\w+(?:::\w+)*/,inside:{punctuation:/::/}},"attr-name":/(?:\b\w+|\*)(?=\s*=>)/,function:[{pattern:/(\.)(?!\d)\w+/,lookbehind:!0},/\b(?:contain|debug|err|fail|include|info|notice|realize|require|tag|warning)\b|\b(?!\d)\w+(?=\()/],number:/\b(?:0x[a-f\d]+|\d+(?:\.\d+)?(?:e-?\d+)?)\b/i,boolean:/\b(?:true|false)\b/,keyword:/\b(?:application|attr|case|class|consumes|default|define|else|elsif|function|if|import|inherits|node|private|produces|type|undef|unless)\b/,datatype:{pattern:/\b(?:Any|Array|Boolean|Callable|Catalogentry|Class|Collection|Data|Default|Enum|Float|Hash|Integer|NotUndef|Numeric|Optional|Pattern|Regexp|Resource|Runtime|Scalar|String|Struct|Tuple|Type|Undef|Variant)\b/,alias:"symbol"},operator:/=[=~>]?|![=~]?|<(?:<\|?|[=~|-])?|>[>=]?|->?|~>|\|>?>?|[*\/%+?]|\b(?:and|in|or)\b/,punctuation:/[\[\]{}().,;]|:+/};var n=[{pattern:/(^|[^\\])\$\{(?:[^'"{}]|\{[^}]*\}|(["'])(?:(?!\2)[^\\]|\\[\s\S])*\2)+\}/,lookbehind:!0,inside:{"short-variable":{pattern:/(^\$\{)(?!\w+\()(?:::)?\w+(?:::\w+)*/,lookbehind:!0,alias:"variable",inside:{punctuation:/::/}},delimiter:{pattern:/^\$/,alias:"variable"},rest:e.languages.puppet}},{pattern:/(^|[^\\])\$(?:::)?\w+(?:::\w+)*/,lookbehind:!0,alias:"variable",inside:{punctuation:/::/}}];e.languages.puppet.heredoc[0].inside.interpolation=n,e.languages.puppet.string.inside["double-quoted"].inside.interpolation=n}(Prism); !function(r){r.languages.pure={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0},/#!.+/],"inline-lang":{pattern:/%<[\s\S]+?%>/,greedy:!0,inside:{lang:{pattern:/(^%< *)-\*-.+?-\*-/,lookbehind:!0,alias:"comment"},delimiter:{pattern:/^%<.*|%>$/,alias:"punctuation"}}},string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},number:{pattern:/((?:\.\.)?)(?:\b(?:inf|nan)\b|\b0x[\da-f]+|(?:\b(?:0b)?\d+(?:\.\d+)?|\B\.\d+)(?:e[+-]?\d+)?L?)/i,lookbehind:!0},keyword:/\b(?:ans|break|bt|case|catch|cd|clear|const|def|del|dump|else|end|exit|extern|false|force|help|if|infix[lr]?|interface|let|ls|mem|namespace|nonfix|NULL|of|otherwise|outfix|override|postfix|prefix|private|public|pwd|quit|run|save|show|stats|then|throw|trace|true|type|underride|using|when|with)\b/,function:/\b(?:abs|add_(?:(?:fundef|interface|macdef|typedef)(?:_at)?|addr|constdef|vardef)|all|any|applp?|arity|bigintp?|blob(?:_crc|_size|p)?|boolp?|byte_(?:matrix|pointer)|byte_c?string(?:_pointer)?|calloc|cat|catmap|ceil|char[ps]?|check_ptrtag|chr|clear_sentry|clearsym|closurep?|cmatrixp?|cols?|colcat(?:map)?|colmap|colrev|colvector(?:p|seq)?|complex(?:_float_(?:matrix|pointer)|_matrix(?:_view)?|_pointer|p)?|conj|cookedp?|cst|cstring(?:_(?:dup|list|vector))?|curry3?|cyclen?|del_(?:constdef|fundef|interface|macdef|typedef|vardef)|delete|diag(?:mat)?|dim|dmatrixp?|do|double(?:_matrix(?:_view)?|_pointer|p)?|dowith3?|drop|dropwhile|eval(?:cmd)?|exactp|filter|fix|fixity|flip|float(?:_matrix|_pointer)|floor|fold[lr]1?|frac|free|funp?|functionp?|gcd|get(?:_(?:byte|constdef|double|float|fundef|int(?:64)?|interface(?:_typedef)?|long|macdef|pointer|ptrtag|short|sentry|string|typedef|vardef))?|globsym|hash|head|id|im|imatrixp?|index|inexactp|infp|init|insert|int(?:_matrix(?:_view)?|_pointer|p)?|int64_(?:matrix|pointer)|integerp?|iteraten?|iterwhile|join|keys?|lambdap?|last(?:err(?:pos)?)?|lcd|list[2p]?|listmap|make_ptrtag|malloc|map|matcat|matrixp?|max|member|min|nanp|nargs|nmatrixp?|null|numberp?|ord|pack(?:ed)?|pointer(?:_cast|_tag|_type|p)?|pow|pred|ptrtag|put(?:_(?:byte|double|float|int(?:64)?|long|pointer|short|string))?|rationalp?|re|realp?|realloc|recordp?|redim|reduce(?:_with)?|refp?|repeatn?|reverse|rlistp?|round|rows?|rowcat(?:map)?|rowmap|rowrev|rowvector(?:p|seq)?|same|scan[lr]1?|sentry|sgn|short_(?:matrix|pointer)|slice|smatrixp?|sort|split|str|strcat|stream|stride|string(?:_(?:dup|list|vector)|p)?|subdiag(?:mat)?|submat|subseq2?|substr|succ|supdiag(?:mat)?|symbolp?|tail|take|takewhile|thunkp?|transpose|trunc|tuplep?|typep|ubyte|uint(?:64)?|ulong|uncurry3?|unref|unzip3?|update|ushort|vals?|varp?|vector(?:p|seq)?|void|zip3?|zipwith3?)\b/,special:{pattern:/\b__[a-z]+__\b/i,alias:"builtin"},operator:/(?:[!"#$%&'*+,\-.\/:<=>?@\\^`|~\u00a1-\u00bf\u00d7-\u00f7\u20d0-\u2bff]|\b_+\b)+|\b(?:and|div|mod|not|or)\b/,punctuation:/[(){}\[\];,|]/};["c",{lang:"c++",alias:"cpp"},"fortran"].forEach(function(e){var t=e;if("string"!=typeof e&&(t=e.alias,e=e.lang),r.languages[t]){var a={};a["inline-lang-"+t]={pattern:RegExp("%< *-\\*- *\\d* *-\\*-[^]+?%>".replace("",e.replace(/([.+*?\/\\(){}\[\]])/g,"\\$1")),"i"),inside:r.util.clone(r.languages.pure["inline-lang"].inside)},a["inline-lang-"+t].inside.rest=r.util.clone(r.languages[t]),r.languages.insertBefore("pure","inline-lang",a)}}),r.languages.c&&(r.languages.pure["inline-lang"].inside.rest=r.util.clone(r.languages.c))}(Prism); Prism.languages.purebasic=Prism.languages.extend("clike",{comment:/;.*/,keyword:/\b(?:declarecdll|declaredll|compilerselect|compilercase|compilerdefault|compilerendselect|compilererror|enableexplicit|disableexplicit|not|and|or|xor|calldebugger|debuglevel|enabledebugger|disabledebugger|restore|read|includepath|includebinary|threaded|runtime|with|endwith|structureunion|endstructureunion|align|newlist|newmap|interface|endinterface|extends|enumeration|endenumeration|swap|foreach|continue|fakereturn|goto|gosub|return|break|module|endmodule|declaremodule|enddeclaremodule|declare|declarec|prototype|prototypec|enableasm|disableasm|dim|redim|data|datasection|enddatasection|to|procedurereturn|debug|default|case|select|endselect|as|import|endimport|importc|compilerif|compilerelse|compilerendif|compilerelseif|end|structure|endstructure|while|wend|for|next|step|if|else|elseif|endif|repeat|until|procedure|proceduredll|procedurec|procedurecdll|endprocedure|protected|shared|static|global|define|includefile|xincludefile|macro|endmacro)\b/i,function:/\b\w+(?:\.\w+)?\s*(?=\()/,number:/(?:\$[\da-f]+|\b-?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)\b/i,operator:/(?:@\*?|\?|\*)\w+|-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*/@]/}),Prism.languages.insertBefore("purebasic","keyword",{tag:/#\w+/,asm:{pattern:/(^[\t ]*)!.*/m,lookbehind:!0,alias:"tag",inside:{comment:/;.*/,string:{pattern:/(["'`])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"label-reference-anonymous":{pattern:/(!\s*j[a-z]+\s+)@[fb]/i,lookbehind:!0,alias:"fasm-label"},"label-reference-addressed":{pattern:/(!\s*j[a-z]+\s+)[A-Z._?$@][\w.?$@~#]*/i,lookbehind:!0,alias:"fasm-label"},function:{pattern:/^([\t ]*!\s*)[\da-z]+(?=\s|$)/im,lookbehind:!0},"function-inline":{pattern:/(:\s*)[\da-z]+(?=\s)/i,lookbehind:!0,alias:"function"},label:{pattern:/^([\t ]*!\s*)[A-Za-z._?$@][\w.?$@~#]*(?=:)/m,lookbehind:!0,alias:"fasm-label"},keyword:[/\b(?:extern|global)\b[^;\r\n]*/i,/\b(?:CPU|FLOAT|DEFAULT)\b.*/],register:/\b(?:st\d|[xyz]mm\d\d?|[cdt]r\d|r\d\d?[bwd]?|[er]?[abcd]x|[abcd][hl]|[er]?(?:bp|sp|si|di)|[cdefgs]s|mm\d+)\b/i,number:/(?:\b|-|(?=\$))(?:0[hx](?:[\da-f]*\.)?[\da-f]+(?:p[+-]?\d+)?|\d[\da-f]+[hx]|\$\d[\da-f]*|0[oq][0-7]+|[0-7]+[oq]|0[by][01]+|[01]+[by]|0[dt]\d+|(?:\d+(?:\.\d+)?|\.\d+)(?:\.?e[+-]?\d+)?[dt]?)\b/i,operator:/[\[\]*+\-/%<>=&|$!,.:]/}}}),delete Prism.languages.purebasic["class-name"],delete Prism.languages.purebasic.boolean,Prism.languages.pbfasm=Prism.languages.purebasic; Prism.languages.purescript=Prism.languages.extend("haskell",{keyword:/\b(?:ado|case|class|data|derive|do|else|forall|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b|∀/,"import-statement":{pattern:/(^[\t ]*)import\s+[A-Z][\w']*(?:\.[A-Z][\w']*)*(?:\s+as\s+[A-Z][\w']*(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:import|as|hiding)\b/,punctuation:/\./}},builtin:/\b(?:absurd|add|ap|append|apply|between|bind|bottom|clamp|compare|comparing|compose|conj|const|degree|discard|disj|div|eq|flap|flip|gcd|identity|ifM|join|lcm|liftA1|liftM1|map|max|mempty|min|mod|mul|negate|not|notEq|one|otherwise|recip|show|sub|top|unit|unless|unlessM|void|when|whenM|zero)\b/,operator:[Prism.languages.haskell.operator[0],Prism.languages.haskell.operator[2],/[\xa2-\xa6\xa8\xa9\xac\xae-\xb1\xb4\xb8\xd7\xf7\u02c2-\u02c5\u02d2-\u02df\u02e5-\u02eb\u02ed\u02ef-\u02ff\u0375\u0384\u0385\u03f6\u0482\u058d-\u058f\u0606-\u0608\u060b\u060e\u060f\u06de\u06e9\u06fd\u06fe\u07f6\u07fe\u07ff\u09f2\u09f3\u09fa\u09fb\u0af1\u0b70\u0bf3-\u0bfa\u0c7f\u0d4f\u0d79\u0e3f\u0f01-\u0f03\u0f13\u0f15-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce\u0fcf\u0fd5-\u0fd8\u109e\u109f\u1390-\u1399\u166d\u17db\u1940\u19de-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u1fbd\u1fbf-\u1fc1\u1fcd-\u1fcf\u1fdd-\u1fdf\u1fed-\u1fef\u1ffd\u1ffe\u2044\u2052\u207a-\u207c\u208a-\u208c\u20a0-\u20bf\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211e-\u2123\u2125\u2127\u2129\u212e\u213a\u213b\u2140-\u2144\u214a-\u214d\u214f\u218a\u218b\u2190-\u2307\u230c-\u2328\u232b-\u2426\u2440-\u244a\u249c-\u24e9\u2500-\u2767\u2794-\u27c4\u27c7-\u27e5\u27f0-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2b73\u2b76-\u2b95\u2b97-\u2bff\u2ce5-\u2cea\u2e50\u2e51\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u2ff0-\u2ffb\u3004\u3012\u3013\u3020\u3036\u3037\u303e\u303f\u309b\u309c\u3190\u3191\u3196-\u319f\u31c0-\u31e3\u3200-\u321e\u322a-\u3247\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua700-\ua716\ua720\ua721\ua789\ua78a\ua828-\ua82b\ua836-\ua839\uaa77-\uaa79\uab5b\uab6a\uab6b\ufb29\ufbb2-\ufbc1\ufdfc\ufdfd\ufe62\ufe64-\ufe66\ufe69\uff04\uff0b\uff1c-\uff1e\uff3e\uff40\uff5c\uff5e\uffe0-\uffe6\uffe8-\uffee\ufffc\ufffd]/]}),Prism.languages.purs=Prism.languages.purescript; Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/im,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; !function(e){function a(e,r){return e.replace(/<<(\d+)>>/g,function(e,n){return"(?:"+r[+n]+")"})}function n(e,n,r){return RegExp(a(e,n),r||"")}var r=RegExp("\\b(?:"+("Adj BigInt Bool Ctl Double false Int One Pauli PauliI PauliX PauliY PauliZ Qubit Range Result String true Unit Zero"+" "+"Adjoint adjoint apply as auto body borrow borrowing Controlled controlled distribute elif else fail fixup for function if in internal intrinsic invert is let mutable namespace new newtype open operation repeat return self set until use using while within").trim().replace(/ /g,"|")+")\\b"),t=a("<<0>>(?:\\s*\\.\\s*<<0>>)*",["\\b[A-Za-z_]\\w*\\b"]),i={keyword:r,punctuation:/[<>()?,.:[\]]/},s='"(?:\\\\.|[^\\\\"])*"';e.languages.qsharp=e.languages.extend("clike",{comment:/\/\/.*/,string:[{pattern:n("(^|[^$\\\\])<<0>>",[s]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:n("(\\b(?:as|open)\\s+)<<0>>(?=\\s*(?:;|as\\b))",[t]),lookbehind:!0,inside:i},{pattern:n("(\\bnamespace\\s+)<<0>>(?=\\s*\\{)",[t]),lookbehind:!0,inside:i}],keyword:r,number:/(?:\b0(?:x[\da-f]+|b[01]+|o[0-7]+)|(?:\B\.\d+|\b\d+(?:\.\d*)?)(?:e[-+]?\d+)?)l?\b/i,operator:/\band=|\bor=|\band\b|\bor\b|\bnot\b|<[-=]|[-=]>|>>>=?|<<<=?|\^\^\^=?|\|\|\|=?|&&&=?|w\/=?|~~~|[*\/+\-^=!%]=?/,punctuation:/::|[{}[\];(),.:]/}),e.languages.insertBefore("qsharp","number",{range:{pattern:/\.\./,alias:"operator"}});var o=function(e,n){for(var r=0;r>/g,function(){return"(?:"+e+")"});return e.replace(/<>/g,"[^\\s\\S]")}(a('\\{(?:[^"{}]|<<0>>|<>)*\\}',[s]),2);e.languages.insertBefore("qsharp","string",{"interpolation-string":{pattern:n('\\$"(?:\\\\.|<<0>>|[^\\\\"{])*"',[o]),greedy:!0,inside:{interpolation:{pattern:n("((?:^|[^\\\\])(?:\\\\\\\\)*)<<0>>",[o]),lookbehind:!0,inside:{punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-qsharp",inside:e.languages.qsharp}}},string:/[\s\S]+/}}})}(Prism),Prism.languages.qs=Prism.languages.qsharp; Prism.languages.q={string:/"(?:\\.|[^"\\\r\n])*"/,comment:[{pattern:/([\t )\]}])\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|\r?\n|\r)\/[\t ]*(?:(?:\r?\n|\r)(?:.*(?:\r?\n|\r(?!\n)))*?(?:\\(?=[\t ]*(?:\r?\n|\r))|$)|\S.*)/,lookbehind:!0,greedy:!0},{pattern:/^\\[\t ]*(?:\r?\n|\r)[\s\S]+/m,greedy:!0},{pattern:/^#!.+/m,greedy:!0}],symbol:/`(?::\S+|[\w.]*)/,datetime:{pattern:/0N[mdzuvt]|0W[dtz]|\d{4}\.\d\d(?:m|\.\d\d(?:T(?:\d\d(?::\d\d(?::\d\d(?:[.:]\d\d\d)?)?)?)?)?[dz]?)|\d\d:\d\d(?::\d\d(?:[.:]\d\d\d)?)?[uvt]?/,alias:"number"},number:/\b(?![01]:)(?:0[wn]|0W[hj]?|0N[hje]?|0x[\da-fA-F]+|\d+(?:\.\d*)?(?:e[+-]?\d+)?[hjfeb]?)/,keyword:/\\\w+\b|\b(?:abs|acos|aj0?|all|and|any|asc|asin|asof|atan|attr|avgs?|binr?|by|ceiling|cols|cor|cos|count|cov|cross|csv|cut|delete|deltas|desc|dev|differ|distinct|div|do|dsave|ej|enlist|eval|except|exec|exit|exp|fby|fills|first|fkeys|flip|floor|from|get|getenv|group|gtime|hclose|hcount|hdel|hopen|hsym|iasc|identity|idesc|if|ij|in|insert|inter|inv|keys?|last|like|list|ljf?|load|log|lower|lsq|ltime|ltrim|mavg|maxs?|mcount|md5|mdev|med|meta|mins?|mmax|mmin|mmu|mod|msum|neg|next|not|null|or|over|parse|peach|pj|plist|prds?|prev|prior|rand|rank|ratios|raze|read0|read1|reciprocal|reval|reverse|rload|rotate|rsave|rtrim|save|scan|scov|sdev|select|set|setenv|show|signum|sin|sqrt|ssr?|string|sublist|sums?|sv|svar|system|tables|tan|til|trim|txf|type|uj|ungroup|union|update|upper|upsert|value|var|views?|vs|wavg|where|while|within|wj1?|wsum|ww|xasc|xbar|xcols?|xdesc|xexp|xgroup|xkey|xlog|xprev|xrank)\b/,adverb:{pattern:/['\/\\]:?|\beach\b/,alias:"function"},verb:{pattern:/(?:\B\.\B|\b[01]:|<[=>]?|>=?|[:+\-*%,!?~=|$&#@^]):?|\b_\b:?/,alias:"operator"},punctuation:/[(){}\[\];.]/}; !function(e){for(var r="(?:[^\\\\()[\\]{}\"'/]||/(?![*/])||\\(*\\)|\\[*\\]|\\{*\\}|\\\\[^])".replace(//g,function(){return"\"(?:\\\\.|[^\\\\\"\r\n])*\"|'(?:\\\\.|[^\\\\'\r\n])*'"}).replace(//g,function(){return"//.*(?!.)|/\\*(?:[^*]|\\*(?!/))*\\*/"}),n=0;n<2;n++)r=r.replace(//g,function(){return r});r=r.replace(//g,"[^\\s\\S]"),e.languages.qml={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},"javascript-function":{pattern:RegExp("((?:^|;)[ \t]*)function\\s+(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*\\s*\\(*\\)\\s*\\{*\\}".replace(//g,function(){return r}),"m"),lookbehind:!0,greedy:!0,alias:"language-javascript",inside:e.languages.javascript},"class-name":{pattern:/((?:^|[:;])[ \t]*)(?!\d)\w+(?=[ \t]*\{|[ \t]+on\b)/m,lookbehind:!0},property:[{pattern:/((?:^|[;{])[ \t]*)(?!\d)\w+(?:\.\w+)*(?=[ \t]*:)/m,lookbehind:!0},{pattern:/((?:^|[;{])[ \t]*)property[ \t]+(?!\d)\w+(?:\.\w+)*[ \t]+(?!\d)\w+(?:\.\w+)*(?=[ \t]*:)/m,lookbehind:!0,inside:{keyword:/^property/,property:/\w+(?:\.\w+)*/}}],"javascript-expression":{pattern:RegExp("(:[ \t]*)(?![\\s;}[])(?:(?!$|[;}]))+".replace(//g,function(){return r}),"m"),lookbehind:!0,greedy:!0,alias:"language-javascript",inside:e.languages.javascript},string:/"(?:\\.|[^\\"\r\n])*"/,keyword:/\b(?:as|import|on)\b/,punctuation:/[{}[\]:;,]/}}(Prism); Prism.languages.qore=Prism.languages.extend("clike",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:\/\/|#).*)/,lookbehind:!0},string:{pattern:/("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},keyword:/\b(?:abstract|any|assert|binary|bool|boolean|break|byte|case|catch|char|class|code|const|continue|data|default|do|double|else|enum|extends|final|finally|float|for|goto|hash|if|implements|import|inherits|instanceof|int|interface|long|my|native|new|nothing|null|object|our|own|private|reference|rethrow|return|short|soft(?:int|float|number|bool|string|date|list)|static|strictfp|string|sub|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\b/,boolean:/\b(?:true|false)\b/i,function:/\$?\b(?!\d)\w+(?=\()/,number:/\b(?:0b[01]+|0x(?:[\da-f]*\.)?[\da-fp\-]+|(?:\d+(?:\.\d+)?|\.\d+)(?:e\d+)?[df]|(?:\d+(?:\.\d+)?|\.\d+))\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|[!=](?:==?|~)?|>>?=?|<(?:=>?|<=?)?|&[&=]?|\|[|=]?|[*\/%^]=?|[~?])/,lookbehind:!0},variable:/\$(?!\d)\w+\b/}); Prism.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:TRUE|FALSE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:NaN|Inf)\b/,/(?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?/],keyword:/\b(?:if|else|repeat|while|function|for|in|next|break|NULL|NA|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/,operator:/->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/}; Prism.languages.racket=Prism.languages.extend("scheme",{"lambda-parameter":{pattern:/([(\[]lambda\s+[(\[])[^()\[\]'\s]+/,lookbehind:!0}}),Prism.languages.insertBefore("racket","string",{lang:{pattern:/^#lang.+/m,greedy:!0,alias:"keyword"}}),Prism.languages.rkt=Prism.languages.racket; !function(i){var t=i.util.clone(i.languages.javascript),e="(?:\\{*\\.{3}(?:[^{}]|)*\\})";function n(t,n){return t=t.replace(//g,function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"}).replace(//g,function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"}).replace(//g,function(){return e}),RegExp(t,n)}e=n(e).source,i.languages.jsx=i.languages.extend("markup",t),i.languages.jsx.tag.pattern=n("+(?:[\\w.:$-]+(?:=(?:\"(?:\\\\[^]|[^\\\\\"])*\"|'(?:\\\\[^]|[^\\\\'])*'|[^\\s{'\"/>=]+|))?|))**/?)?>"),i.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/i,i.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/i,i.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,i.languages.jsx.tag.inside.comment=t.comment,i.languages.insertBefore("inside","attr-name",{spread:{pattern:n(""),inside:i.languages.jsx}},i.languages.jsx.tag),i.languages.insertBefore("inside","special-attr",{script:{pattern:n("="),inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:i.languages.jsx},alias:"language-javascript"}},i.languages.jsx.tag);var o=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(o).join(""):""},r=function(t){for(var n=[],e=0;e"===a.content[a.content.length-1].content||n.push({tagName:o(a.content[0].content[1]),openedBraces:0}):0|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:mod|land|lor|lxor|lsl|lsr|asr)\b/}),Prism.languages.insertBefore("reason","class-name",{character:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,alias:"string"},constructor:{pattern:/\b[A-Z]\w*\b(?!\s*\.)/,alias:"variable"},label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete Prism.languages.reason.function; !function(a){var e={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|c[a-zA-Z]|0[0-7]{0,2}|[123][0-7]{2}|.)/,t="(?:[^\\\\-]|"+n.source+")",s=RegExp(t+"-"+t),i={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"};a.languages.regex={charset:{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"charset-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"charset-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:s,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":e,charclass:{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":e,charclass:{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":i}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|:=]=?|!=|\b_\b/,punctuation:/[,;.\[\]{}()]/}; Prism.languages.renpy={comment:{pattern:/(^|[^\\])#.+/,lookbehind:!0},string:{pattern:/("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2|(?:^#?(?:[0-9a-fA-F]{6}|(?:[0-9a-fA-F]){3})$)/m,greedy:!0},function:/\b[a-z_]\w*(?=\()/i,property:/\b(?:insensitive|idle|hover|selected_idle|selected_hover|background|position|alt|xpos|ypos|pos|xanchor|yanchor|anchor|xalign|yalign|align|xcenter|ycenter|xofsset|yoffset|ymaximum|maximum|xmaximum|xminimum|yminimum|minimum|xsize|ysizexysize|xfill|yfill|area|antialias|black_color|bold|caret|color|first_indent|font|size|italic|justify|kerning|language|layout|line_leading|line_overlap_split|line_spacing|min_width|newline_indent|outlines|rest_indent|ruby_style|slow_cps|slow_cps_multiplier|strikethrough|text_align|underline|hyperlink_functions|vertical|hinting|foreground|left_margin|xmargin|top_margin|bottom_margin|ymargin|left_padding|right_padding|xpadding|top_padding|bottom_padding|ypadding|size_group|child|hover_sound|activate_sound|mouse|focus_mask|keyboard_focus|bar_vertical|bar_invert|bar_resizing|left_gutter|right_gutter|top_gutter|bottom_gutter|left_bar|right_bar|top_bar|bottom_bar|thumb|thumb_shadow|thumb_offset|unscrollable|spacing|first_spacing|box_reverse|box_wrap|order_reverse|fit_first|ysize|thumbnail_width|thumbnail_height|help|text_ypos|text_xpos|idle_color|hover_color|selected_idle_color|selected_hover_color|insensitive_color|alpha|insensitive_background|hover_background|zorder|value|width|xadjustment|xanchoraround|xaround|xinitial|xoffset|xzoom|yadjustment|yanchoraround|yaround|yinitial|yzoom|zoom|ground|height|text_style|text_y_fudge|selected_insensitive|has_sound|has_music|has_voice|focus|hovered|image_style|length|minwidth|mousewheel|offset|prefix|radius|range|right_margin|rotate|rotate_pad|developer|screen_width|screen_height|window_title|name|version|windows_icon|default_fullscreen|default_text_cps|default_afm_time|main_menu_music|sample_sound|enter_sound|exit_sound|save_directory|enter_transition|exit_transition|intra_transition|main_game_transition|game_main_transition|end_splash_transition|end_game_transition|after_load_transition|window_show_transition|window_hide_transition|adv_nvl_transition|nvl_adv_transition|enter_yesno_transition|exit_yesno_transition|enter_replay_transition|exit_replay_transition|say_attribute_transition|directory_name|executable_name|include_update|window_icon|modal|google_play_key|google_play_salt|drag_name|drag_handle|draggable|dragged|droppable|dropped|narrator_menu|action|default_afm_enable|version_name|version_tuple|inside|fadeout|fadein|layers|layer_clipping|linear|scrollbars|side_xpos|side_ypos|side_spacing|edgescroll|drag_joined|drag_raise|drop_shadow|drop_shadow_color|subpixel|easein|easeout|time|crop|auto|update|get_installed_packages|can_update|UpdateVersion|Update|overlay_functions|translations|window_left_padding|show_side_image|show_two_window)\b/,tag:/\b(?:label|image|menu|[hv]box|frame|text|imagemap|imagebutton|bar|vbar|screen|textbutton|buttoscreenn|fixed|grid|input|key|mousearea|side|timer|viewport|window|hotspot|hotbar|self|button|drag|draggroup|tag|mm_menu_frame|nvl|block|parallel)\b|\$/,keyword:/\b(?:as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|yield|adjustment|alignaround|allow|angle|around|box_layout|cache|changed|child_size|clicked|clipping|corner1|corner2|default|delay|exclude|scope|slow|slow_abortable|slow_done|sound|style_group|substitute|suffix|transform_anchor|transpose|unhovered|config|theme|mm_root|gm_root|rounded_window|build|disabled_text|disabled|widget_selected|widget_text|widget_hover|widget|updater|behind|call|expression|hide|init|jump|onlayer|python|renpy|scene|set|show|transform|play|queue|stop|pause|define|window|repeat|contains|choice|on|function|event|animation|clockwise|counterclockwise|circles|knot|null|None|random|has|add|use|fade|dissolve|style|store|id|voice|center|left|right|less_rounded|music|movie|clear|persistent|ui)\b/,boolean:/\b(?:[Tt]rue|[Ff]alse)\b/,number:/(?:\b(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?)|\B\.\d+)(?:e[+-]?\d+)?j?/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not|with|at)\b/,punctuation:/[{}[\];(),.:]/},Prism.languages.rpy=Prism.languages.renpy; Prism.languages.rest={table:[{pattern:/(^[\t ]*)(?:\+[=-]+)+\+(?:\r?\n|\r)(?:\1[+|].+[+|](?:\r?\n|\r))+\1(?:\+[=-]+)+\+/m,lookbehind:!0,inside:{punctuation:/\||(?:\+[=-]+)+\+/}},{pattern:/(^[\t ]*)=+ [ =]*=(?:(?:\r?\n|\r)\1.+)+(?:\r?\n|\r)\1=+ [ =]*=(?=(?:\r?\n|\r){2}|\s*$)/m,lookbehind:!0,inside:{punctuation:/[=-]+/}}],"substitution-def":{pattern:/(^[\t ]*\.\. )\|(?:[^|\s](?:[^|]*[^|\s])?)\| [^:]+::/m,lookbehind:!0,inside:{substitution:{pattern:/^\|(?:[^|\s]|[^|\s][^|]*[^|\s])\|/,alias:"attr-value",inside:{punctuation:/^\||\|$/}},directive:{pattern:/( )(?! )[^:]+::/,lookbehind:!0,alias:"function",inside:{punctuation:/::$/}}}},"link-target":[{pattern:/(^[\t ]*\.\. )\[[^\]]+\]/m,lookbehind:!0,alias:"string",inside:{punctuation:/^\[|\]$/}},{pattern:/(^[\t ]*\.\. )_(?:`[^`]+`|(?:[^:\\]|\\.)+):/m,lookbehind:!0,alias:"string",inside:{punctuation:/^_|:$/}}],directive:{pattern:/(^[\t ]*\.\. )[^:]+::/m,lookbehind:!0,alias:"function",inside:{punctuation:/::$/}},comment:{pattern:/(^[\t ]*\.\.)(?:(?: .+)?(?:(?:\r?\n|\r).+)+| .+)(?=(?:\r?\n|\r){2}|$)/m,lookbehind:!0},title:[{pattern:/^(([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2+)(?:\r?\n|\r).+(?:\r?\n|\r)\1$/m,inside:{punctuation:/^[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+|[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+$/,important:/.+/}},{pattern:/(^|(?:\r?\n|\r){2}).+(?:\r?\n|\r)([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2+(?=\r?\n|\r|$)/,lookbehind:!0,inside:{punctuation:/[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+$/,important:/.+/}}],hr:{pattern:/((?:\r?\n|\r){2})([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2{3,}(?=(?:\r?\n|\r){2})/,lookbehind:!0,alias:"punctuation"},field:{pattern:/(^[\t ]*):[^:\r\n]+:(?= )/m,lookbehind:!0,alias:"attr-name"},"command-line-option":{pattern:/(^[\t ]*)(?:[+-][a-z\d]|(?:--|\/)[a-z\d-]+)(?:[ =](?:[a-z][\w-]*|<[^<>]+>))?(?:, (?:[+-][a-z\d]|(?:--|\/)[a-z\d-]+)(?:[ =](?:[a-z][\w-]*|<[^<>]+>))?)*(?=(?:\r?\n|\r)? {2,}\S)/im,lookbehind:!0,alias:"symbol"},"literal-block":{pattern:/::(?:\r?\n|\r){2}([ \t]+)(?![ \t]).+(?:(?:\r?\n|\r)\1.+)*/,inside:{"literal-block-punctuation":{pattern:/^::/,alias:"punctuation"}}},"quoted-literal-block":{pattern:/::(?:\r?\n|\r){2}([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]).*(?:(?:\r?\n|\r)\1.*)*/,inside:{"literal-block-punctuation":{pattern:/^(?:::|([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\1*)/m,alias:"punctuation"}}},"list-bullet":{pattern:/(^[\t ]*)(?:[*+\-•‣⁃]|\(?(?:\d+|[a-z]|[ivxdclm]+)\)|(?:\d+|[a-z]|[ivxdclm]+)\.)(?= )/im,lookbehind:!0,alias:"punctuation"},"doctest-block":{pattern:/(^[\t ]*)>>> .+(?:(?:\r?\n|\r).+)*/m,lookbehind:!0,inside:{punctuation:/^>>>/}},inline:[{pattern:/(^|[\s\-:\/'"<(\[{])(?::[^:]+:`.*?`|`.*?`:[^:]+:|(\*\*?|``?|\|)(?!\s)(?:(?!\2).)*\S\2(?=[\s\-.,:;!?\\\/'")\]}]|$))/m,lookbehind:!0,inside:{bold:{pattern:/(^\*\*).+(?=\*\*$)/,lookbehind:!0},italic:{pattern:/(^\*).+(?=\*$)/,lookbehind:!0},"inline-literal":{pattern:/(^``).+(?=``$)/,lookbehind:!0,alias:"symbol"},role:{pattern:/^:[^:]+:|:[^:]+:$/,alias:"function",inside:{punctuation:/^:|:$/}},"interpreted-text":{pattern:/(^`).+(?=`$)/,lookbehind:!0,alias:"attr-value"},substitution:{pattern:/(^\|).+(?=\|$)/,lookbehind:!0,alias:"attr-value"},punctuation:/\*\*?|``?|\|/}}],link:[{pattern:/\[[^\[\]]+\]_(?=[\s\-.,:;!?\\\/'")\]}]|$)/,alias:"string",inside:{punctuation:/^\[|\]_$/}},{pattern:/(?:\b[a-z\d]+(?:[_.:+][a-z\d]+)*_?_|`[^`]+`_?_|_`[^`]+`)(?=[\s\-.,:;!?\\\/'")\]}]|$)/i,alias:"string",inside:{punctuation:/^_?`|`$|`?_?_$/}}],punctuation:{pattern:/(^[\t ]*)(?:\|(?= |$)|(?:---?|—|\.\.|__)(?= )|\.\.$)/m,lookbehind:!0}}; Prism.languages.rip={comment:/#.*/,keyword:/(?:=>|->)|\b(?:class|if|else|switch|case|return|exit|try|catch|finally|raise)\b/,builtin:/@|\bSystem\b/,boolean:/\b(?:true|false)\b/,date:/\b\d{4}-\d{2}-\d{2}\b/,time:/\b\d{2}:\d{2}:\d{2}\b/,datetime:/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\b/,character:/\B`[^\s`'",.:;#\/\\()<>\[\]{}]\b/,regex:{pattern:/(^|[^/])\/(?!\/)(?:\[[^\n\r\]]*\]|\\.|[^/\\\r\n\[])+\/(?=\s*(?:$|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},symbol:/:[^\d\s`'",.:;#\/\\()<>\[\]{}][^\s`'",.:;#\/\\()<>\[\]{}]*/,string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},number:/[+-]?\b(?:\d+\.\d+|\d+)\b/,punctuation:/(?:\.{2,3})|[`,.:;=\/\\()<>\[\]{}]/,reference:/[^\d\s`'",.:;#\/\\()<>\[\]{}][^\s`'",.:;#\/\\()<>\[\]{}]*/}; Prism.languages.roboconf={comment:/#.*/,keyword:{pattern:/(^|\s)(?:(?:facet|instance of)(?=[ \t]+[\w-]+[ \t]*\{)|(?:external|import)\b)/,lookbehind:!0},component:{pattern:/[\w-]+(?=[ \t]*\{)/,alias:"variable"},property:/[\w.-]+(?=[ \t]*:)/,value:{pattern:/(=[ \t]*(?![ \t]))[^,;]+/,lookbehind:!0,alias:"attr-value"},optional:{pattern:/\(optional\)/,alias:"builtin"},wildcard:{pattern:/(\.)\*/,lookbehind:!0,alias:"operator"},punctuation:/[{},.;:=]/}; !function(t){var r={pattern:/(^[ \t]*| {2}|\t)#.*/m,lookbehind:!0,greedy:!0},o={pattern:/((?:^|[^\\])(?:\\{2})*)[$@&%]\{(?:[^{}\r\n]|\{[^{}\r\n]*\})*\}/,lookbehind:!0,inside:{punctuation:/^[$@&%]\{|\}$/}};function n(t,n){var e={"section-header":{pattern:/^ ?\*{3}.+?\*{3}/,alias:"keyword"}};for(var a in n)e[a]=n[a];return e.tag={pattern:/([\r\n](?: {2}|\t)[ \t]*)\[[-\w]+\]/,lookbehind:!0,inside:{punctuation:/\[|\]/}},e.variable=o,e.comment=r,{pattern:RegExp("^ ?\\*{3}[ \t]*[ \t]*\\*{3}(?:.|[\r\n](?!\\*{3}))*".replace(//g,function(){return t}),"im"),alias:"section",inside:e}}var e={pattern:/(\[Documentation\](?: {2}|\t)[ \t]*)(?![ \t]|#)(?:.|(?:\r\n?|\n)[ \t]*\.{3})+/,lookbehind:!0,alias:"string"},a={pattern:/([\r\n] ?)(?!#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0,alias:"function",inside:{variable:o}},i={pattern:/([\r\n](?: {2}|\t)[ \t]*)(?!\[|\.{3}|#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0,inside:{variable:o}};t.languages.robotframework={settings:n("Settings",{documentation:{pattern:/([\r\n] ?Documentation(?: {2}|\t)[ \t]*)(?![ \t]|#)(?:.|(?:\r\n?|\n)[ \t]*\.{3})+/,lookbehind:!0,alias:"string"},property:{pattern:/([\r\n] ?)(?!\.{3}|#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0}}),variables:n("Variables"),"test-cases":n("Test Cases",{"test-name":a,documentation:e,property:i}),keywords:n("Keywords",{"keyword-name":a,documentation:e,property:i}),tasks:n("Tasks",{"task-name":a,documentation:e,property:i}),comment:r},t.languages.robot=t.languages.robotframework}(Prism); !function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,function(){return a});a=a.replace(//g,function(){return"[^\\s\\S]"}),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0,alias:"string"},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|Self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:[ui](?:8|16|32|64|128|size)|f(?:32|64)|bool|char|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64|size)?|f32|f64))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); !function(e){var t="(?:\"(?:\"\"|[^\"])*\"(?!\")|'(?:''|[^'])*'(?!'))",a=/\b(?:\d[\da-f]*x|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,n={pattern:RegExp(t+"[bx]"),alias:"number"},i={pattern:/&[a-z_]\w*/i},r={pattern:/((?:^|\s|=|\())%(?:ABORT|BY|CMS|COPY|DISPLAY|DO|ELSE|END|EVAL|GLOBAL|GO|GOTO|IF|INC|INCLUDE|INDEX|INPUT|KTRIM|LENGTH|LET|LIST|LOCAL|PUT|QKTRIM|QSCAN|QSUBSTR|QSYSFUNC|QUPCASE|RETURN|RUN|SCAN|SUBSTR|SUPERQ|SYMDEL|SYMGLOBL|SYMLOCAL|SYMEXIST|SYSCALL|SYSEVALF|SYSEXEC|SYSFUNC|SYSGET|SYSRPUT|THEN|TO|TSO|UNQUOTE|UNTIL|UPCASE|WHILE|WINDOW)\b/i,lookbehind:!0,alias:"keyword"},s={pattern:/(^|\s)(?:proc\s+\w+|quit|run|data(?!=))\b/i,alias:"keyword",lookbehind:!0},o=[/\/\*[\s\S]*?\*\//,{pattern:/(^[ \t]*|;\s*)\*[^;]*;/m,lookbehind:!0}],l={pattern:RegExp(t),greedy:!0},c=/[$%@.(){}\[\];,\\]/,d={pattern:/%?\b\w+(?=\()/,alias:"keyword"},p={function:d,"arg-value":{pattern:/(=\s*)[A-Z\.]+/i,lookbehind:!0},operator:/=/,"macro-variable":i,arg:{pattern:/[A-Z]+/i,alias:"keyword"},number:a,"numeric-constant":n,punctuation:c,string:l},u={pattern:/\b(?:format|put)\b=?[\w'$.]+/im,inside:{keyword:/^(?:format|put)(?==)/i,equals:/=/,format:{pattern:/(?:\w|\$\d)+\.\d?/i,alias:"number"}}},m={pattern:/\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i,inside:{keyword:/^(?:format|put)/i,format:{pattern:/[\w$]+\.\d?/,alias:"number"}}},b={pattern:/((?:^|\s)=?)(?:catname|checkpoint execute_always|dm|endsas|filename|footnote|%include|libname|%list|lock|missing|options|page|resetline|%run|sasfile|skip|sysecho|title\d?)\b/i,lookbehind:!0,alias:"keyword"},g={pattern:/(^|\s)(?:submit(?:\s+(?:load|parseonly|norun))?|endsubmit)\b/i,lookbehind:!0,alias:"keyword"},k="accessControl|cdm|aggregation|aStore|ruleMining|audio|autotune|bayesianNetClassifier|bioMedImage|boolRule|builtins|cardinality|sccasl|clustering|copula|countreg|dataDiscovery|dataPreprocess|dataSciencePilot|dataStep|decisionTree|deepLearn|deepNeural|varReduce|simSystem|ds2|deduplication|ecm|entityRes|espCluster|explainModel|factmac|fastKnn|fcmpact|fedSql|freqTab|gam|gleam|graphSemiSupLearn|gVarCluster|hiddenMarkovModel|hyperGroup|image|iml|ica|kernalPca|langModel|ldaTopic|sparseML|mlTools|mixed|modelPublishing|mbc|network|optNetwork|neuralNet|nonlinear|nmf|nonParametricBayes|optimization|panel|pls|percentile|pca|phreg|qkb|qlim|quantreg|recommend|tsReconcile|deepRnn|regression|reinforcementLearn|robustPca|sampling|sparkEmbeddedProcess|search(?:Analytics)?|sentimentAnalysis|sequence|configuration|session(?:Prop)?|severity|simple|smartData|sandwich|spatialreg|stabilityMonitoring|spc|loadStreams|svDataDescription|svm|table|conditionalRandomFields|text(?:Rule(?:Develop|Score)|Mining|Parse|Topic|Util|Filters|Frequency)|tsInfo|timeData|transpose|uniTimeSeries",y={pattern:RegExp("(^|\\s)(?:action\\s+)?(?:)\\.[a-z]+\\b[^;]+".replace(//g,function(){return k}),"i"),lookbehind:!0,inside:{keyword:RegExp("(?:)\\.[a-z]+\\b".replace(//g,function(){return k}),"i"),action:{pattern:/(?:action)/i,alias:"keyword"},comment:o,function:d,"arg-value":p["arg-value"],operator:p.operator,argument:p.arg,number:a,"numeric-constant":n,punctuation:c,string:l}},S={pattern:/((?:^|\s)=?)(?:after|analysis|and|array|barchart|barwidth|begingraph|by|call|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|continue|data(?==)|define|delete|describe|document|do\s+over|do|dol|drop|dul|end(?:source|comp)?|entryTitle|else|eval(?:uate)?|exec(?:ute)?|exit|fill(?:attrs)?|file(?:name)?|flist|fnc|function(?:list)?|goto|global|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|leave|legendlabel|length|libname|loadactionset|merge|midpoints|name|noobs|nowd|_?null_|ods|options|or|otherwise|out(?:put)?|over(?:lay)?|plot|put|print|raise|ranexp|rannor|rbreak|retain|return|select|set|session|sessref|source|statgraph|sum|summarize|table|temp|terminate|then\s+do|then|title\d?|to|var|when|where|xaxisopts|yaxisopts|y2axisopts)\b/i,lookbehind:!0};e.languages.sas={datalines:{pattern:/^([ \t]*)(?:(?:data)?lines|cards);[\s\S]+?^[ \t]*;/im,lookbehind:!0,alias:"string",inside:{keyword:{pattern:/^(?:(?:data)?lines|cards)/i},punctuation:/;/}},"proc-sql":{pattern:/(^proc\s+(?:fed)?sql(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{sql:{pattern:RegExp("^[ \t]*(?:select|alter\\s+table|(?:create|describe|drop)\\s+(?:index|table(?:\\s+constraints)?|view)|create\\s+unique\\s+index|insert\\s+into|update)(?:|[^;\"'])+;".replace(//g,function(){return t}),"im"),alias:"language-sql",inside:e.languages.sql},"global-statements":b,"sql-statements":{pattern:/(^|\s)(?:disconnect\s+from|exec(?:ute)?|begin|commit|rollback|reset|validate)\b/i,lookbehind:!0,alias:"keyword"},number:a,"numeric-constant":n,punctuation:c,string:l}},"proc-groovy":{pattern:/(^proc\s+groovy(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:o,groovy:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,function(){return t}),"im"),lookbehind:!0,alias:"language-groovy",inside:e.languages.groovy},keyword:S,"submit-statement":g,"global-statements":b,number:a,"numeric-constant":n,punctuation:c,string:l}},"proc-lua":{pattern:/(^proc\s+lua(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:o,lua:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,function(){return t}),"im"),lookbehind:!0,alias:"language-lua",inside:e.languages.lua},keyword:S,"submit-statement":g,"global-statements":b,number:a,"numeric-constant":n,punctuation:c,string:l}},"proc-cas":{pattern:/(^proc\s+cas(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|data);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:o,"statement-var":{pattern:/((?:^|\s)=?)saveresult\s[^;]+/im,lookbehind:!0,inside:{statement:{pattern:/^saveresult\s+\S+/i,inside:{keyword:/^(?:saveresult)/i}},rest:p}},"cas-actions":y,statement:{pattern:/((?:^|\s)=?)(?:default|(?:un)?set|on|output|upload)[^;]+/im,lookbehind:!0,inside:p},step:s,keyword:S,function:d,format:u,altformat:m,"global-statements":b,number:a,"numeric-constant":n,punctuation:c,string:l}},"proc-args":{pattern:RegExp("(^proc\\s+\\w+\\s+)(?!\\s)(?:[^;\"']|)+;".replace(//g,function(){return t}),"im"),lookbehind:!0,inside:p},"macro-keyword":r,"macro-variable":i,"macro-string-functions":{pattern:/((?:^|\s|=))%(?:NRBQUOTE|NRQUOTE|NRSTR|BQUOTE|QUOTE|STR)\(.*?(?:[^%]\))/i,lookbehind:!0,inside:{function:{pattern:/%(?:NRBQUOTE|NRQUOTE|NRSTR|BQUOTE|QUOTE|STR)/i,alias:"keyword"},"macro-keyword":r,"macro-variable":i,"escaped-char":{pattern:/%['"()<>=¬^~;,#]/i},punctuation:c}},"macro-declaration":{pattern:/^%macro[^;]+(?=;)/im,inside:{keyword:/%macro/i}},"macro-end":{pattern:/^%mend[^;]+(?=;)/im,inside:{keyword:/%mend/i}},macro:{pattern:/%_\w+(?=\()/,alias:"keyword"},input:{pattern:/\binput\s[-\w\s/*.$&]+;/i,inside:{input:{alias:"keyword",pattern:/^input/i},comment:o,number:a,"numeric-constant":n}},"options-args":{pattern:/(^options)[-'"|/\\<>*+=:()\w\s]*(?=;)/im,lookbehind:!0,inside:p},"cas-actions":y,comment:o,function:d,format:u,altformat:m,"numeric-constant":n,datetime:{pattern:RegExp(t+"(?:dt?|t)"),alias:"number"},string:l,step:s,keyword:S,"operator-keyword":{pattern:/\b(?:eq|ne|gt|lt|ge|le|in|not)\b/i,alias:"operator"},number:a,operator:/\*\*?|\|\|?|!!?|¦¦?|<[>=]?|>[<=]?|[-+\/=&]|[~¬^]=?/i,punctuation:c}}(Prism); !function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var r=/\$[-\w]+|#\{\$[-\w]+\}/,t=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:r,operator:t}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:r,operator:t,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(Prism); Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|forward|for|each|while|import|use|extend|debug|warn|mixin|include|function|return|content)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),Prism.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|with|show|hide)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss; Prism.languages.scala=Prism.languages.extend("java",{"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/<-|=>|\b(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|null|object|override|package|private|protected|return|sealed|self|super|this|throw|trait|try|type|val|var|while|with|yield)\b/,number:/\b0x(?:[\da-f]*\.)?[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e\d+)?[dfl]?/i,builtin:/\b(?:String|Int|Long|Short|Byte|Boolean|Double|Float|Char|Any|AnyRef|AnyVal|Unit|Nothing)\b/,symbol:/'[^\d\s\\]\w*/}),delete Prism.languages.scala["class-name"],delete Prism.languages.scala.function; !function(s){var n=['"(?:\\\\[^]|\\$\\([^)]+\\)|\\$(?!\\()|`[^`]+`|[^"\\\\`$])*"',"'[^']*'","\\$'(?:[^'\\\\]|\\\\[^])*'","<<-?\\s*([\"']?)(\\w+)\\1\\s[^]*?[\r\n]\\2"].join("|");s.languages["shell-session"]={command:{pattern:RegExp('^(?:[^\\s@:$#%*!/\\\\]+@[^\r\n@:$#%*!/\\\\]+(?::[^\0-\\x1F$#%*?"<>:;|]+)?|[^\0-\\x1F$#%*?"<>@:;|]+)?[$#%]'+"(?:[^\\\\\r\n'\"<$]|\\\\(?:[^\r]|\r\n?)|\\$(?!')|<>)+".replace(/<>/g,function(){return n}),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:s.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},s.languages["sh-session"]=s.languages.shellsession=s.languages["shell-session"]}(Prism); Prism.languages.smali={comment:/#.*/,string:{pattern:/"(?:[^\r\n\\"]|\\.)*"|'(?:[^\r\n\\']|\\(?:.|u[\da-fA-F]{4}))'/,greedy:!0},"class-name":{pattern:/(^|[^L])L(?:(?:\w+|`[^`\r\n]*`)\/)*(?:[\w$]+|`[^`\r\n]*`)(?=\s*;)/,lookbehind:!0,inside:{"class-name":{pattern:/(^L|\/)(?:[\w$]+|`[^`\r\n]*`)$/,lookbehind:!0},namespace:{pattern:/^(L)(?:(?:\w+|`[^`\r\n]*`)\/)+/,lookbehind:!0,inside:{punctuation:/\//}},builtin:/^L/}},builtin:[{pattern:/([();\[])[BCDFIJSVZ]+/,lookbehind:!0},{pattern:/([\w$>]:)[BCDFIJSVZ]/,lookbehind:!0}],keyword:[{pattern:/(\.end\s+)[\w-]+/,lookbehind:!0},{pattern:/(^|[^\w.-])\.(?!\d)[\w-]+/,lookbehind:!0},{pattern:/(^|[^\w.-])(?:abstract|annotation|bridge|constructor|enum|final|interface|private|protected|public|runtime|static|synthetic|system|transient)(?![\w.-])/,lookbehind:!0}],function:{pattern:/(^|[^\w.-])(?:\w+|<[\w$-]+>)(?=\()/,lookbehind:!0},field:{pattern:/[\w$]+(?=:)/,alias:"variable"},register:{pattern:/(^|[^\w.-])[vp]\d(?![\w.-])/,lookbehind:!0,alias:"variable"},boolean:{pattern:/(^|[^\w.-])(?:true|false)(?![\w.-])/,lookbehind:!0},number:{pattern:/(^|[^/\w.-])-?(?:NAN|INFINITY|0x(?:[\dA-F]+(?:\.[\dA-F]*)?|\.[\dA-F]+)(?:p[+-]?[\dA-F]+)?|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)[dflst]?(?![\w.-])/i,lookbehind:!0},label:{pattern:/(:)\w+/,lookbehind:!0,alias:"property"},operator:/->|\.\.|[\[=]/,punctuation:/[{}(),;:]/}; Prism.languages.smalltalk={comment:/"(?:""|[^"])*"/,character:{pattern:/\$./,alias:"string"},string:/'(?:''|[^'])*'/,symbol:/#[\da-z]+|#(?:-|([+\/\\*~<>=@%|&?!])\1?)|#(?=\()/i,"block-arguments":{pattern:/(\[\s*):[^\[|]*\|/,lookbehind:!0,inside:{variable:/:[\da-z]+/i,punctuation:/\|/}},"temporary-variables":{pattern:/\|[^|]+\|/,inside:{variable:/[\da-z]+/i,punctuation:/\|/}},keyword:/\b(?:nil|true|false|self|super|new)\b/,number:[/\d+r-?[\dA-Z]+(?:\.[\dA-Z]+)?(?:e-?\d+)?/,/\b\d+(?:\.\d+)?(?:e-?\d+)?/],operator:/[<=]=?|:=|~[~=]|\/\/?|\\\\|>[>=]?|[!^+\-*&|,@]/,punctuation:/[.;:?\[\](){}]/}; !function(n){n.languages.smarty={comment:/\{\*[\s\S]*?\*\}/,delimiter:{pattern:/^\{|\}$/i,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,variable:[/\$(?!\d)\w+/,/#(?!\d)\w+#/,{pattern:/(\.|->)(?!\d)\w+/,lookbehind:!0},{pattern:/(\[)(?!\d)\w+(?=\])/,lookbehind:!0}],function:[{pattern:/(\|\s*)@?(?!\d)\w+/,lookbehind:!0},/^\/?(?!\d)\w+/,/(?!\d)\w+(?=\()/],"attr-name":{pattern:/\w+\s*=\s*(?:(?!\d)\w+)?/,inside:{variable:{pattern:/(=\s*)(?!\d)\w+/,lookbehind:!0},operator:/=/}},punctuation:[/[\[\]().,:`]|->/],operator:[/[+\-*\/%]|==?=?|[!<>]=?|&&|\|\|?/,/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,/\b(?:eq|neq?|gt|lt|gt?e|lt?e|not|mod|or|and)\b/],keyword:/\b(?:false|off|on|no|true|yes)\b/},n.hooks.add("before-tokenize",function(e){var t=!1;n.languages["markup-templating"].buildPlaceholders(e,"smarty",/\{\*[\s\S]*?\*\}|\{[\s\S]+?\}/g,function(e){return"{/literal}"===e&&(t=!1),!t&&("{literal}"===e&&(t=!0),!0)})}),n.hooks.add("after-tokenize",function(e){n.languages["markup-templating"].tokenizePlaceholders(e,"smarty")})}(Prism); !function(e){var n=/\b(?:abstype|and|andalso|as|case|datatype|do|else|end|eqtype|exception|fn|fun|functor|handle|if|in|include|infix|infixr|let|local|nonfix|of|op|open|orelse|raise|rec|sharing|sig|signature|struct|structure|then|type|val|where|while|with|withtype)\b/i;e.languages.sml={comment:/\(\*(?:[^*(]|\*(?!\))|\((?!\*)|\(\*(?:[^*(]|\*(?!\))|\((?!\*))*\*\))*\*\)/,string:{pattern:/#?"(?:[^"\\]|\\.)*"/,greedy:!0},"class-name":[{pattern:RegExp("((?:^|[^:]):\\s*)(?:\\s*(?:(?:\\*|->)\\s*|,\\s*(?:(?=)|(?!)\\s+)))*".replace(//g,function(){return"\\s*(?:[*,]|->)"}).replace(//g,function(){return"(?:'[\\w']*||\\((?:[^()]|\\([^()]*\\))*\\)|\\{(?:[^{}]|\\{[^{}]*\\})*\\})(?:\\s+)*"}).replace(//g,function(){return"(?!)[a-z\\d_][\\w'.]*"}).replace(//g,function(){return n.source}),"i"),lookbehind:!0,greedy:!0,inside:null},{pattern:/((?:^|[^\w'])(?:datatype|exception|functor|signature|structure|type)\s+)[a-z_][\w'.]*/i,lookbehind:!0}],function:{pattern:/((?:^|[^\w'])fun\s+)[a-z_][\w'.]*/i,lookbehind:!0},keyword:n,variable:{pattern:/(^|[^\w'])'[\w']*/,lookbehind:!0},number:/~?\b(?:\d+(?:\.\d+)?(?:e~?\d+)?|0x[\da-f]+)\b/i,word:{pattern:/\b0w(?:\d+|x[\da-f]+)\b/i,alias:"constant"},boolean:/\b(?:false|true)\b/i,operator:/\.\.\.|:[>=:]|=>?|->|[<>]=?|[!+\-*/^#|@~]/,punctuation:/[(){}\[\].:,;]/},e.languages.sml["class-name"][0].inside=e.languages.sml,e.languages.smlnj=e.languages.sml}(Prism); Prism.languages.solidity=Prism.languages.extend("clike",{"class-name":{pattern:/(\b(?:contract|enum|interface|library|new|struct|using)\s+)(?!\d)[\w$]+/,lookbehind:!0},keyword:/\b(?:_|anonymous|as|assembly|assert|break|calldata|case|constant|constructor|continue|contract|default|delete|do|else|emit|enum|event|external|for|from|function|if|import|indexed|inherited|interface|internal|is|let|library|mapping|memory|modifier|new|payable|pragma|private|public|pure|require|returns?|revert|selfdestruct|solidity|storage|struct|suicide|switch|this|throw|using|var|view|while)\b/,operator:/=>|->|:=|=:|\*\*|\+\+|--|\|\||&&|<<=?|>>=?|[-+*/%^&|<>!=]=?|[~?]/}),Prism.languages.insertBefore("solidity","keyword",{builtin:/\b(?:address|bool|string|u?int(?:8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?|byte|bytes(?:[1-9]|[12]\d|3[0-2])?)\b/}),Prism.languages.insertBefore("solidity","number",{version:{pattern:/([<>]=?|\^)\d+\.\d+\.\d+\b/,lookbehind:!0,alias:"number"}}),Prism.languages.sol=Prism.languages.solidity; !function(n){var t={pattern:/\{[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\}/i,alias:"constant",inside:{punctuation:/[{}]/}};n.languages["solution-file"]={comment:{pattern:/#.*/,greedy:!0},string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,greedy:!0,inside:{guid:t}},object:{pattern:/^([ \t]*)(?:([A-Z]\w*)\b(?=.*(?:\r\n?|\n)(?:\1[ \t].*(?:\r\n?|\n))*\1End\2(?=[ \t]*$))|End[A-Z]\w*(?=[ \t]*$))/m,lookbehind:!0,greedy:!0,alias:"keyword"},property:{pattern:/^([ \t]*)(?!\s)[^\r\n"#=()]*[^\s"#=()](?=\s*=)/m,lookbehind:!0,inside:{guid:t}},guid:t,number:/\b\d+(?:\.\d+)*\b/,boolean:/\b(?:FALSE|TRUE)\b/,operator:/=/,punctuation:/[(),]/},n.languages.sln=n.languages["solution-file"]}(Prism); !function(t){var e=/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,a=/\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b|\b0x[\dA-F]+\b/;t.languages.soy={comment:[/\/\*[\s\S]*?\*\//,{pattern:/(\s)\/\/.*/,lookbehind:!0,greedy:!0}],"command-arg":{pattern:/(\{+\/?\s*(?:alias|call|delcall|delpackage|deltemplate|namespace|template)\s+)\.?[\w.]+/,lookbehind:!0,alias:"string",inside:{punctuation:/\./}},parameter:{pattern:/(\{+\/?\s*@?param\??\s+)\.?[\w.]+/,lookbehind:!0,alias:"variable"},keyword:[{pattern:/(\{+\/?[^\S\r\n]*)(?:\\[nrt]|alias|call|case|css|default|delcall|delpackage|deltemplate|else(?:if)?|fallbackmsg|for(?:each)?|if(?:empty)?|lb|let|literal|msg|namespace|nil|@?param\??|rb|sp|switch|template|xid)/,lookbehind:!0},/\b(?:any|as|attributes|bool|css|float|in|int|js|html|list|map|null|number|string|uri)\b/],delimiter:{pattern:/^\{+\/?|\/?\}+$/,alias:"punctuation"},property:/\w+(?==)/,variable:{pattern:/\$[^\W\d]\w*(?:\??(?:\.\w+|\[[^\]]+\]))*/,inside:{string:{pattern:e,greedy:!0},number:a,punctuation:/[\[\].?]/}},string:{pattern:e,greedy:!0},function:[/\w+(?=\()/,{pattern:/(\|[^\S\r\n]*)\w+/,lookbehind:!0}],boolean:/\b(?:true|false)\b/,number:a,operator:/\?:?|<=?|>=?|==?|!=|[+*/%-]|\b(?:and|not|or)\b/,punctuation:/[{}()\[\]|.,:]/},t.hooks.add("before-tokenize",function(e){var a=!1;t.languages["markup-templating"].buildPlaceholders(e,"soy",/\{\{.+?\}\}|\{.+?\}|\s\/\/.*|\/\*[\s\S]*?\*\//g,function(e){return"{/literal}"===e&&(a=!1),!a&&("{literal}"===e&&(a=!0),!0)})}),t.hooks.add("after-tokenize",function(e){t.languages["markup-templating"].tokenizePlaceholders(e,"soy")})}(Prism); Prism.languages.turtle={comment:{pattern:/#.*/,greedy:!0},"multiline-string":{pattern:/"""(?:(?:""?)?(?:[^"\\]|\\.))*"""|'''(?:(?:''?)?(?:[^'\\]|\\.))*'''/,greedy:!0,alias:"string",inside:{comment:/#.*/}},string:{pattern:/"(?:[^\\"\r\n]|\\.)*"|'(?:[^\\'\r\n]|\\.)*'/,greedy:!0},url:{pattern:/<(?:[^\x00-\x20<>"{}|^`\\]|\\(?:u[\da-fA-F]{4}|U[\da-fA-F]{8}))*>/,greedy:!0,inside:{punctuation:/[<>]/}},function:{pattern:/(?:(?![-.\d\xB7])[-.\w\xB7\xC0-\uFFFD]+)?:(?:(?![-.])(?:[-.:\w\xC0-\uFFFD]|%[\da-f]{2}|\\.)+)?/i,inside:{"local-name":{pattern:/([^:]*:)[\s\S]+/,lookbehind:!0},prefix:{pattern:/[\s\S]+/,inside:{punctuation:/:/}}}},number:/[+-]?\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,punctuation:/[{}.,;()[\]]|\^\^/,boolean:/\b(?:true|false)\b/,keyword:[/(?:\ba|@prefix|@base)\b|=/,/\b(?:graph|base|prefix)\b/i],tag:{pattern:/@[a-z]+(?:-[a-z\d]+)*/i,inside:{punctuation:/@/}}},Prism.languages.trig=Prism.languages.turtle; Prism.languages.sparql=Prism.languages.extend("turtle",{boolean:/\b(?:true|false)\b/i,variable:{pattern:/[?$]\w+/,greedy:!0}}),Prism.languages.insertBefore("sparql","punctuation",{keyword:[/\b(?:A|ADD|ALL|AS|ASC|ASK|BNODE|BY|CLEAR|CONSTRUCT|COPY|CREATE|DATA|DEFAULT|DELETE|DESC|DESCRIBE|DISTINCT|DROP|EXISTS|FILTER|FROM|GROUP|HAVING|INSERT|INTO|LIMIT|LOAD|MINUS|MOVE|NAMED|NOT|NOW|OFFSET|OPTIONAL|ORDER|RAND|REDUCED|SELECT|SEPARATOR|SERVICE|SILENT|STRUUID|UNION|USING|UUID|VALUES|WHERE)\b/i,/\b(?:ABS|AVG|BIND|BOUND|CEIL|COALESCE|CONCAT|CONTAINS|COUNT|DATATYPE|DAY|ENCODE_FOR_URI|FLOOR|GROUP_CONCAT|HOURS|IF|IRI|isBLANK|isIRI|isLITERAL|isNUMERIC|isURI|LANG|LANGMATCHES|LCASE|MAX|MD5|MIN|MINUTES|MONTH|ROUND|REGEX|REPLACE|sameTerm|SAMPLE|SECONDS|SHA1|SHA256|SHA384|SHA512|STR|STRAFTER|STRBEFORE|STRDT|STRENDS|STRLANG|STRLEN|STRSTARTS|SUBSTR|SUM|TIMEZONE|TZ|UCASE|URI|YEAR)\b(?=\s*\()/i,/\b(?:GRAPH|BASE|PREFIX)\b/i]}),Prism.languages.rq=Prism.languages.sparql; Prism.languages["splunk-spl"]={comment:/`comment\("(?:\\.|[^\\"])*"\)`/,string:{pattern:/"(?:\\.|[^\\"])*"/,greedy:!0},keyword:/\b(?:abstract|accum|addcoltotals|addinfo|addtotals|analyzefields|anomalies|anomalousvalue|anomalydetection|append|appendcols|appendcsv|appendlookup|appendpipe|arules|associate|audit|autoregress|bin|bucket|bucketdir|chart|cluster|cofilter|collect|concurrency|contingency|convert|correlate|datamodel|dbinspect|dedup|delete|delta|diff|erex|eval|eventcount|eventstats|extract|fieldformat|fields|fieldsummary|filldown|fillnull|findtypes|folderize|foreach|format|from|gauge|gentimes|geom|geomfilter|geostats|head|highlight|history|iconify|input|inputcsv|inputlookup|iplocation|join|kmeans|kv|kvform|loadjob|localize|localop|lookup|makecontinuous|makemv|makeresults|map|mcollect|metadata|metasearch|meventcollect|mstats|multikv|multisearch|mvcombine|mvexpand|nomv|outlier|outputcsv|outputlookup|outputtext|overlap|pivot|predict|rangemap|rare|regex|relevancy|reltime|rename|replace|rest|return|reverse|rex|rtorder|run|savedsearch|script|scrub|search|searchtxn|selfjoin|sendemail|set|setfields|sichart|sirare|sistats|sitimechart|sitop|sort|spath|stats|strcat|streamstats|table|tags|tail|timechart|timewrap|top|transaction|transpose|trendline|tscollect|tstats|typeahead|typelearner|typer|union|uniq|untable|where|x11|xmlkv|xmlunescape|xpath|xyseries)\b/i,"operator-word":{pattern:/\b(?:and|as|by|not|or|xor)\b/i,alias:"operator"},function:/\b\w+(?=\s*\()/,property:/\b\w+(?=\s*=(?!=))/,date:{pattern:/\b\d{1,2}\/\d{1,2}\/\d{1,4}(?:(?::\d{1,2}){3})?\b/,alias:"number"},number:/\b\d+(?:\.\d+)?\b/,boolean:/\b(?:f|false|t|true)\b/i,operator:/[<>=]=?|[-+*/%|]/,punctuation:/[()[\],]/}; Prism.languages.sqf=Prism.languages.extend("clike",{string:{pattern:/"(?:(?:"")?[^"])*"(?!")|'(?:[^'])*'/,greedy:!0},keyword:/\b(?:breakOut|breakTo|call|case|catch|default|do|echo|else|execVM|execFSM|exitWith|for|forEach|forEachMember|forEachMemberAgent|forEachMemberTeam|from|goto|if|nil|preprocessFile|preprocessFileLineNumbers|private|scopeName|spawn|step|switch|then|throw|to|try|while|with)\b/i,boolean:/\b(?:true|false)\b/i,function:/\b(?:abs|accTime|acos|action|actionIDs|actionKeys|actionKeysImages|actionKeysNames|actionKeysNamesArray|actionName|actionParams|activateAddons|activatedAddons|activateKey|add3DENConnection|add3DENEventHandler|add3DENLayer|addAction|addBackpack|addBackpackCargo|addBackpackCargoGlobal|addBackpackGlobal|addCamShake|addCuratorAddons|addCuratorCameraArea|addCuratorEditableObjects|addCuratorEditingArea|addCuratorPoints|addEditorObject|addEventHandler|addForce|addForceGeneratorRTD|addGoggles|addGroupIcon|addHandgunItem|addHeadgear|addItem|addItemCargo|addItemCargoGlobal|addItemPool|addItemToBackpack|addItemToUniform|addItemToVest|addLiveStats|addMagazine|addMagazineAmmoCargo|addMagazineCargo|addMagazineCargoGlobal|addMagazineGlobal|addMagazinePool|addMagazines|addMagazineTurret|addMenu|addMenuItem|addMissionEventHandler|addMPEventHandler|addMusicEventHandler|addOwnedMine|addPlayerScores|addPrimaryWeaponItem|addPublicVariableEventHandler|addRating|addResources|addScore|addScoreSide|addSecondaryWeaponItem|addSwitchableUnit|addTeamMember|addToRemainsCollector|addTorque|addUniform|addVehicle|addVest|addWaypoint|addWeapon|addWeaponCargo|addWeaponCargoGlobal|addWeaponGlobal|addWeaponItem|addWeaponPool|addWeaponTurret|admin|agent|agents|AGLToASL|aimedAtTarget|aimPos|airDensityCurveRTD|airDensityRTD|airplaneThrottle|airportSide|AISFinishHeal|alive|all3DENEntities|allAirports|allControls|allCurators|allCutLayers|allDead|allDeadMen|allDisplays|allGroups|allMapMarkers|allMines|allMissionObjects|allow3DMode|allowCrewInImmobile|allowCuratorLogicIgnoreAreas|allowDamage|allowDammage|allowFileOperations|allowFleeing|allowGetIn|allowSprint|allPlayers|allSimpleObjects|allSites|allTurrets|allUnits|allUnitsUAV|allVariables|ammo|ammoOnPylon|animate|animateBay|animateDoor|animatePylon|animateSource|animationNames|animationPhase|animationSourcePhase|animationState|append|apply|armoryPoints|arrayIntersect|asin|ASLToAGL|ASLToATL|assert|assignAsCargo|assignAsCargoIndex|assignAsCommander|assignAsDriver|assignAsGunner|assignAsTurret|assignCurator|assignedCargo|assignedCommander|assignedDriver|assignedGunner|assignedItems|assignedTarget|assignedTeam|assignedVehicle|assignedVehicleRole|assignItem|assignTeam|assignToAirport|atan|atan2|atg|ATLToASL|attachedObject|attachedObjects|attachedTo|attachObject|attachTo|attackEnabled|backpack|backpackCargo|backpackContainer|backpackItems|backpackMagazines|backpackSpaceFor|behaviour|benchmark|binocular|blufor|boundingBox|boundingBoxReal|boundingCenter|briefingName|buildingExit|buildingPos|buldozer_EnableRoadDiag|buldozer_IsEnabledRoadDiag|buldozer_LoadNewRoads|buldozer_reloadOperMap|buttonAction|buttonSetAction|cadetMode|callExtension|camCommand|camCommit|camCommitPrepared|camCommitted|camConstuctionSetParams|camCreate|camDestroy|cameraEffect|cameraEffectEnableHUD|cameraInterest|cameraOn|cameraView|campaignConfigFile|camPreload|camPreloaded|camPrepareBank|camPrepareDir|camPrepareDive|camPrepareFocus|camPrepareFov|camPrepareFovRange|camPreparePos|camPrepareRelPos|camPrepareTarget|camSetBank|camSetDir|camSetDive|camSetFocus|camSetFov|camSetFovRange|camSetPos|camSetRelPos|camSetTarget|camTarget|camUseNVG|canAdd|canAddItemToBackpack|canAddItemToUniform|canAddItemToVest|cancelSimpleTaskDestination|canFire|canMove|canSlingLoad|canStand|canSuspend|canTriggerDynamicSimulation|canUnloadInCombat|canVehicleCargo|captive|captiveNum|cbChecked|cbSetChecked|ceil|channelEnabled|cheatsEnabled|checkAIFeature|checkVisibility|civilian|className|clear3DENAttribute|clear3DENInventory|clearAllItemsFromBackpack|clearBackpackCargo|clearBackpackCargoGlobal|clearForcesRTD|clearGroupIcons|clearItemCargo|clearItemCargoGlobal|clearItemPool|clearMagazineCargo|clearMagazineCargoGlobal|clearMagazinePool|clearOverlay|clearRadio|clearVehicleInit|clearWeaponCargo|clearWeaponCargoGlobal|clearWeaponPool|clientOwner|closeDialog|closeDisplay|closeOverlay|collapseObjectTree|collect3DENHistory|collectiveRTD|combatMode|commandArtilleryFire|commandChat|commander|commandFire|commandFollow|commandFSM|commandGetOut|commandingMenu|commandMove|commandRadio|commandStop|commandSuppressiveFire|commandTarget|commandWatch|comment|commitOverlay|compile|compileFinal|completedFSM|composeText|configClasses|configFile|configHierarchy|configName|configNull|configProperties|configSourceAddonList|configSourceMod|configSourceModList|confirmSensorTarget|connectTerminalToUAV|controlNull|controlsGroupCtrl|copyFromClipboard|copyToClipboard|copyWaypoints|cos|count|countEnemy|countFriendly|countSide|countType|countUnknown|create3DENComposition|create3DENEntity|createAgent|createCenter|createDialog|createDiaryLink|createDiaryRecord|createDiarySubject|createDisplay|createGearDialog|createGroup|createGuardedPoint|createLocation|createMarker|createMarkerLocal|createMenu|createMine|createMissionDisplay|createMPCampaignDisplay|createSimpleObject|createSimpleTask|createSite|createSoundSource|createTask|createTeam|createTrigger|createUnit|createVehicle|createVehicleCrew|createVehicleLocal|crew|ctAddHeader|ctAddRow|ctClear|ctCurSel|ctData|ctFindHeaderRows|ctFindRowHeader|ctHeaderControls|ctHeaderCount|ctRemoveHeaders|ctRemoveRows|ctrlActivate|ctrlAddEventHandler|ctrlAngle|ctrlAutoScrollDelay|ctrlAutoScrollRewind|ctrlAutoScrollSpeed|ctrlChecked|ctrlClassName|ctrlCommit|ctrlCommitted|ctrlCreate|ctrlDelete|ctrlEnable|ctrlEnabled|ctrlFade|ctrlHTMLLoaded|ctrlIDC|ctrlIDD|ctrlMapAnimAdd|ctrlMapAnimClear|ctrlMapAnimCommit|ctrlMapAnimDone|ctrlMapCursor|ctrlMapMouseOver|ctrlMapScale|ctrlMapScreenToWorld|ctrlMapWorldToScreen|ctrlModel|ctrlModelDirAndUp|ctrlModelScale|ctrlParent|ctrlParentControlsGroup|ctrlPosition|ctrlRemoveAllEventHandlers|ctrlRemoveEventHandler|ctrlScale|ctrlSetActiveColor|ctrlSetAngle|ctrlSetAutoScrollDelay|ctrlSetAutoScrollRewind|ctrlSetAutoScrollSpeed|ctrlSetBackgroundColor|ctrlSetChecked|ctrlSetDisabledColor|ctrlSetEventHandler|ctrlSetFade|ctrlSetFocus|ctrlSetFont|ctrlSetFontH1|ctrlSetFontH1B|ctrlSetFontH2|ctrlSetFontH2B|ctrlSetFontH3|ctrlSetFontH3B|ctrlSetFontH4|ctrlSetFontH4B|ctrlSetFontH5|ctrlSetFontH5B|ctrlSetFontH6|ctrlSetFontH6B|ctrlSetFontHeight|ctrlSetFontHeightH1|ctrlSetFontHeightH2|ctrlSetFontHeightH3|ctrlSetFontHeightH4|ctrlSetFontHeightH5|ctrlSetFontHeightH6|ctrlSetFontHeightSecondary|ctrlSetFontP|ctrlSetFontPB|ctrlSetFontSecondary|ctrlSetForegroundColor|ctrlSetModel|ctrlSetModelDirAndUp|ctrlSetModelScale|ctrlSetPixelPrecision|ctrlSetPosition|ctrlSetScale|ctrlSetStructuredText|ctrlSetText|ctrlSetTextColor|ctrlSetTextColorSecondary|ctrlSetTextSecondary|ctrlSetTooltip|ctrlSetTooltipColorBox|ctrlSetTooltipColorShade|ctrlSetTooltipColorText|ctrlShow|ctrlShown|ctrlText|ctrlTextHeight|ctrlTextSecondary|ctrlTextWidth|ctrlType|ctrlVisible|ctRowControls|ctRowCount|ctSetCurSel|ctSetData|ctSetHeaderTemplate|ctSetRowTemplate|ctSetValue|ctValue|curatorAddons|curatorCamera|curatorCameraArea|curatorCameraAreaCeiling|curatorCoef|curatorEditableObjects|curatorEditingArea|curatorEditingAreaType|curatorMouseOver|curatorPoints|curatorRegisteredObjects|curatorSelected|curatorWaypointCost|current3DENOperation|currentChannel|currentCommand|currentMagazine|currentMagazineDetail|currentMagazineDetailTurret|currentMagazineTurret|currentMuzzle|currentNamespace|currentTask|currentTasks|currentThrowable|currentVisionMode|currentWaypoint|currentWeapon|currentWeaponMode|currentWeaponTurret|currentZeroing|cursorObject|cursorTarget|customChat|customRadio|cutFadeOut|cutObj|cutRsc|cutText|damage|date|dateToNumber|daytime|deActivateKey|debriefingText|debugFSM|debugLog|deg|delete3DENEntities|deleteAt|deleteCenter|deleteCollection|deleteEditorObject|deleteGroup|deleteGroupWhenEmpty|deleteIdentity|deleteLocation|deleteMarker|deleteMarkerLocal|deleteRange|deleteResources|deleteSite|deleteStatus|deleteTeam|deleteVehicle|deleteVehicleCrew|deleteWaypoint|detach|detectedMines|diag_activeMissionFSMs|diag_activeScripts|diag_activeSQFScripts|diag_activeSQSScripts|diag_captureFrame|diag_captureFrameToFile|diag_captureSlowFrame|diag_codePerformance|diag_drawMode|diag_dynamicSimulationEnd|diag_enable|diag_enabled|diag_fps|diag_fpsMin|diag_frameNo|diag_lightNewLoad|diag_list|diag_log|diag_logSlowFrame|diag_mergeConfigFile|diag_recordTurretLimits|diag_setLightNew|diag_tickTime|diag_toggle|dialog|diarySubjectExists|didJIP|didJIPOwner|difficulty|difficultyEnabled|difficultyEnabledRTD|difficultyOption|direction|directSay|disableAI|disableCollisionWith|disableConversation|disableDebriefingStats|disableMapIndicators|disableNVGEquipment|disableRemoteSensors|disableSerialization|disableTIEquipment|disableUAVConnectability|disableUserInput|displayAddEventHandler|displayCtrl|displayNull|displayParent|displayRemoveAllEventHandlers|displayRemoveEventHandler|displaySetEventHandler|dissolveTeam|distance|distance2D|distanceSqr|distributionRegion|do3DENAction|doArtilleryFire|doFire|doFollow|doFSM|doGetOut|doMove|doorPhase|doStop|doSuppressiveFire|doTarget|doWatch|drawArrow|drawEllipse|drawIcon|drawIcon3D|drawLine|drawLine3D|drawLink|drawLocation|drawPolygon|drawRectangle|drawTriangle|driver|drop|dynamicSimulationDistance|dynamicSimulationDistanceCoef|dynamicSimulationEnabled|dynamicSimulationSystemEnabled|east|edit3DENMissionAttributes|editObject|editorSetEventHandler|effectiveCommander|emptyPositions|enableAI|enableAIFeature|enableAimPrecision|enableAttack|enableAudioFeature|enableAutoStartUpRTD|enableAutoTrimRTD|enableCamShake|enableCaustics|enableChannel|enableCollisionWith|enableCopilot|enableDebriefingStats|enableDiagLegend|enableDynamicSimulation|enableDynamicSimulationSystem|enableEndDialog|enableEngineArtillery|enableEnvironment|enableFatigue|enableGunLights|enableInfoPanelComponent|enableIRLasers|enableMimics|enablePersonTurret|enableRadio|enableReload|enableRopeAttach|enableSatNormalOnDetail|enableSaving|enableSentences|enableSimulation|enableSimulationGlobal|enableStamina|enableStressDamage|enableTeamSwitch|enableTraffic|enableUAVConnectability|enableUAVWaypoints|enableVehicleCargo|enableVehicleSensor|enableWeaponDisassembly|endl|endLoadingScreen|endMission|engineOn|enginesIsOnRTD|enginesPowerRTD|enginesRpmRTD|enginesTorqueRTD|entities|environmentEnabled|estimatedEndServerTime|estimatedTimeLeft|evalObjectArgument|everyBackpack|everyContainer|exec|execEditorScript|exp|expectedDestination|exportJIPMessages|eyeDirection|eyePos|face|faction|fadeMusic|fadeRadio|fadeSound|fadeSpeech|failMission|fillWeaponsFromPool|find|findCover|findDisplay|findEditorObject|findEmptyPosition|findEmptyPositionReady|findIf|findNearestEnemy|finishMissionInit|finite|fire|fireAtTarget|firstBackpack|flag|flagAnimationPhase|flagOwner|flagSide|flagTexture|fleeing|floor|flyInHeight|flyInHeightASL|fog|fogForecast|fogParams|forceAddUniform|forceAtPositionRTD|forcedMap|forceEnd|forceFlagTexture|forceFollowRoad|forceGeneratorRTD|forceMap|forceRespawn|forceSpeed|forceWalk|forceWeaponFire|forceWeatherChange|forgetTarget|format|formation|formationDirection|formationLeader|formationMembers|formationPosition|formationTask|formatText|formLeader|freeLook|fromEditor|fuel|fullCrew|gearIDCAmmoCount|gearSlotAmmoCount|gearSlotData|get3DENActionState|get3DENAttribute|get3DENCamera|get3DENConnections|get3DENEntity|get3DENEntityID|get3DENGrid|get3DENIconsVisible|get3DENLayerEntities|get3DENLinesVisible|get3DENMissionAttribute|get3DENMouseOver|get3DENSelected|getAimingCoef|getAllEnvSoundControllers|getAllHitPointsDamage|getAllOwnedMines|getAllSoundControllers|getAmmoCargo|getAnimAimPrecision|getAnimSpeedCoef|getArray|getArtilleryAmmo|getArtilleryComputerSettings|getArtilleryETA|getAssignedCuratorLogic|getAssignedCuratorUnit|getBackpackCargo|getBleedingRemaining|getBurningValue|getCameraViewDirection|getCargoIndex|getCenterOfMass|getClientState|getClientStateNumber|getCompatiblePylonMagazines|getConnectedUAV|getContainerMaxLoad|getCursorObjectParams|getCustomAimCoef|getDammage|getDescription|getDir|getDirVisual|getDLCAssetsUsage|getDLCAssetsUsageByName|getDLCs|getDLCUsageTime|getEditorCamera|getEditorMode|getEditorObjectScope|getElevationOffset|getEngineTargetRpmRTD|getEnvSoundController|getFatigue|getFieldManualStartPage|getForcedFlagTexture|getFriend|getFSMVariable|getFuelCargo|getGroupIcon|getGroupIconParams|getGroupIcons|getHideFrom|getHit|getHitIndex|getHitPointDamage|getItemCargo|getMagazineCargo|getMarkerColor|getMarkerPos|getMarkerSize|getMarkerType|getMass|getMissionConfig|getMissionConfigValue|getMissionDLCs|getMissionLayerEntities|getMissionLayers|getModelInfo|getMousePosition|getMusicPlayedTime|getNumber|getObjectArgument|getObjectChildren|getObjectDLC|getObjectMaterials|getObjectProxy|getObjectTextures|getObjectType|getObjectViewDistance|getOxygenRemaining|getPersonUsedDLCs|getPilotCameraDirection|getPilotCameraPosition|getPilotCameraRotation|getPilotCameraTarget|getPlateNumber|getPlayerChannel|getPlayerScores|getPlayerUID|getPlayerUIDOld|getPos|getPosASL|getPosASLVisual|getPosASLW|getPosATL|getPosATLVisual|getPosVisual|getPosWorld|getPylonMagazines|getRelDir|getRelPos|getRemoteSensorsDisabled|getRepairCargo|getResolution|getRotorBrakeRTD|getShadowDistance|getShotParents|getSlingLoad|getSoundController|getSoundControllerResult|getSpeed|getStamina|getStatValue|getSuppression|getTerrainGrid|getTerrainHeightASL|getText|getTotalDLCUsageTime|getTrimOffsetRTD|getUnitLoadout|getUnitTrait|getUserMFDText|getUserMFDValue|getVariable|getVehicleCargo|getWeaponCargo|getWeaponSway|getWingsOrientationRTD|getWingsPositionRTD|getWPPos|glanceAt|globalChat|globalRadio|goggles|group|groupChat|groupFromNetId|groupIconSelectable|groupIconsVisible|groupId|groupOwner|groupRadio|groupSelectedUnits|groupSelectUnit|grpNull|gunner|gusts|halt|handgunItems|handgunMagazine|handgunWeapon|handsHit|hasInterface|hasPilotCamera|hasWeapon|hcAllGroups|hcGroupParams|hcLeader|hcRemoveAllGroups|hcRemoveGroup|hcSelected|hcSelectGroup|hcSetGroup|hcShowBar|hcShownBar|headgear|hideBody|hideObject|hideObjectGlobal|hideSelection|hint|hintC|hintCadet|hintSilent|hmd|hostMission|htmlLoad|HUDMovementLevels|humidity|image|importAllGroups|importance|in|inArea|inAreaArray|incapacitatedState|independent|inflame|inflamed|infoPanel|infoPanelComponentEnabled|infoPanelComponents|infoPanels|inGameUISetEventHandler|inheritsFrom|initAmbientLife|inPolygon|inputAction|inRangeOfArtillery|insertEditorObject|intersect|is3DEN|is3DENMultiplayer|isAbleToBreathe|isAgent|isAimPrecisionEnabled|isArray|isAutoHoverOn|isAutonomous|isAutoStartUpEnabledRTD|isAutotest|isAutoTrimOnRTD|isBleeding|isBurning|isClass|isCollisionLightOn|isCopilotEnabled|isDamageAllowed|isDedicated|isDLCAvailable|isEngineOn|isEqualTo|isEqualType|isEqualTypeAll|isEqualTypeAny|isEqualTypeArray|isEqualTypeParams|isFilePatchingEnabled|isFlashlightOn|isFlatEmpty|isForcedWalk|isFormationLeader|isGroupDeletedWhenEmpty|isHidden|isInRemainsCollector|isInstructorFigureEnabled|isIRLaserOn|isKeyActive|isKindOf|isLaserOn|isLightOn|isLocalized|isManualFire|isMarkedForCollection|isMultiplayer|isMultiplayerSolo|isNil|isNull|isNumber|isObjectHidden|isObjectRTD|isOnRoad|isPipEnabled|isPlayer|isRealTime|isRemoteExecuted|isRemoteExecutedJIP|isServer|isShowing3DIcons|isSimpleObject|isSprintAllowed|isStaminaEnabled|isSteamMission|isStreamFriendlyUIEnabled|isStressDamageEnabled|isText|isTouchingGround|isTurnedOut|isTutHintsEnabled|isUAVConnectable|isUAVConnected|isUIContext|isUniformAllowed|isVehicleCargo|isVehicleRadarOn|isVehicleSensorEnabled|isWalking|isWeaponDeployed|isWeaponRested|itemCargo|items|itemsWithMagazines|join|joinAs|joinAsSilent|joinSilent|joinString|kbAddDatabase|kbAddDatabaseTargets|kbAddTopic|kbHasTopic|kbReact|kbRemoveTopic|kbTell|kbWasSaid|keyImage|keyName|knowsAbout|land|landAt|landResult|language|laserTarget|lbAdd|lbClear|lbColor|lbColorRight|lbCurSel|lbData|lbDelete|lbIsSelected|lbPicture|lbPictureRight|lbSelection|lbSetColor|lbSetColorRight|lbSetCurSel|lbSetData|lbSetPicture|lbSetPictureColor|lbSetPictureColorDisabled|lbSetPictureColorSelected|lbSetPictureRight|lbSetPictureRightColor|lbSetPictureRightColorDisabled|lbSetPictureRightColorSelected|lbSetSelectColor|lbSetSelectColorRight|lbSetSelected|lbSetText|lbSetTextRight|lbSetTooltip|lbSetValue|lbSize|lbSort|lbSortByValue|lbText|lbTextRight|lbValue|leader|leaderboardDeInit|leaderboardGetRows|leaderboardInit|leaderboardRequestRowsFriends|leaderboardRequestRowsGlobal|leaderboardRequestRowsGlobalAroundUser|leaderboardsRequestUploadScore|leaderboardsRequestUploadScoreKeepBest|leaderboardState|leaveVehicle|libraryCredits|libraryDisclaimers|lifeState|lightAttachObject|lightDetachObject|lightIsOn|lightnings|limitSpeed|linearConversion|lineBreak|lineIntersects|lineIntersectsObjs|lineIntersectsSurfaces|lineIntersectsWith|linkItem|list|listObjects|listRemoteTargets|listVehicleSensors|ln|lnbAddArray|lnbAddColumn|lnbAddRow|lnbClear|lnbColor|lnbColorRight|lnbCurSelRow|lnbData|lnbDeleteColumn|lnbDeleteRow|lnbGetColumnsPosition|lnbPicture|lnbPictureRight|lnbSetColor|lnbSetColorRight|lnbSetColumnsPos|lnbSetCurSelRow|lnbSetData|lnbSetPicture|lnbSetPictureColor|lnbSetPictureColorRight|lnbSetPictureColorSelected|lnbSetPictureColorSelectedRight|lnbSetPictureRight|lnbSetText|lnbSetTextRight|lnbSetValue|lnbSize|lnbSort|lnbSortByValue|lnbText|lnbTextRight|lnbValue|load|loadAbs|loadBackpack|loadFile|loadGame|loadIdentity|loadMagazine|loadOverlay|loadStatus|loadUniform|loadVest|local|localize|locationNull|locationPosition|lock|lockCameraTo|lockCargo|lockDriver|locked|lockedCargo|lockedDriver|lockedTurret|lockIdentity|lockTurret|lockWP|log|logEntities|logNetwork|logNetworkTerminate|lookAt|lookAtPos|magazineCargo|magazines|magazinesAllTurrets|magazinesAmmo|magazinesAmmoCargo|magazinesAmmoFull|magazinesDetail|magazinesDetailBackpack|magazinesDetailUniform|magazinesDetailVest|magazinesTurret|magazineTurretAmmo|mapAnimAdd|mapAnimClear|mapAnimCommit|mapAnimDone|mapCenterOnCamera|mapGridPosition|markAsFinishedOnSteam|markerAlpha|markerBrush|markerColor|markerDir|markerPos|markerShape|markerSize|markerText|markerType|max|members|menuAction|menuAdd|menuChecked|menuClear|menuCollapse|menuData|menuDelete|menuEnable|menuEnabled|menuExpand|menuHover|menuPicture|menuSetAction|menuSetCheck|menuSetData|menuSetPicture|menuSetValue|menuShortcut|menuShortcutText|menuSize|menuSort|menuText|menuURL|menuValue|min|mineActive|mineDetectedBy|missionConfigFile|missionDifficulty|missionName|missionNamespace|missionStart|missionVersion|modelToWorld|modelToWorldVisual|modelToWorldVisualWorld|modelToWorldWorld|modParams|moonIntensity|moonPhase|morale|move|move3DENCamera|moveInAny|moveInCargo|moveInCommander|moveInDriver|moveInGunner|moveInTurret|moveObjectToEnd|moveOut|moveTime|moveTo|moveToCompleted|moveToFailed|musicVolume|name|nameSound|nearEntities|nearestBuilding|nearestLocation|nearestLocations|nearestLocationWithDubbing|nearestObject|nearestObjects|nearestTerrainObjects|nearObjects|nearObjectsReady|nearRoads|nearSupplies|nearTargets|needReload|netId|netObjNull|newOverlay|nextMenuItemIndex|nextWeatherChange|nMenuItems|numberOfEnginesRTD|numberToDate|objectCurators|objectFromNetId|objectParent|objNull|objStatus|onBriefingGear|onBriefingGroup|onBriefingNotes|onBriefingPlan|onBriefingTeamSwitch|onCommandModeChanged|onDoubleClick|onEachFrame|onGroupIconClick|onGroupIconOverEnter|onGroupIconOverLeave|onHCGroupSelectionChanged|onMapSingleClick|onPlayerConnected|onPlayerDisconnected|onPreloadFinished|onPreloadStarted|onShowNewObject|onTeamSwitch|openCuratorInterface|openDLCPage|openDSInterface|openMap|openSteamApp|openYoutubeVideo|opfor|orderGetIn|overcast|overcastForecast|owner|param|params|parseNumber|parseSimpleArray|parseText|parsingNamespace|particlesQuality|pi|pickWeaponPool|pitch|pixelGrid|pixelGridBase|pixelGridNoUIScale|pixelH|pixelW|playableSlotsNumber|playableUnits|playAction|playActionNow|player|playerRespawnTime|playerSide|playersNumber|playGesture|playMission|playMove|playMoveNow|playMusic|playScriptedMission|playSound|playSound3D|position|positionCameraToWorld|posScreenToWorld|posWorldToScreen|ppEffectAdjust|ppEffectCommit|ppEffectCommitted|ppEffectCreate|ppEffectDestroy|ppEffectEnable|ppEffectEnabled|ppEffectForceInNVG|precision|preloadCamera|preloadObject|preloadSound|preloadTitleObj|preloadTitleRsc|primaryWeapon|primaryWeaponItems|primaryWeaponMagazine|priority|processDiaryLink|processInitCommands|productVersion|profileName|profileNamespace|profileNameSteam|progressLoadingScreen|progressPosition|progressSetPosition|publicVariable|publicVariableClient|publicVariableServer|pushBack|pushBackUnique|putWeaponPool|queryItemsPool|queryMagazinePool|queryWeaponPool|rad|radioChannelAdd|radioChannelCreate|radioChannelRemove|radioChannelSetCallSign|radioChannelSetLabel|radioVolume|rain|rainbow|random|rank|rankId|rating|rectangular|registeredTasks|registerTask|reload|reloadEnabled|remoteControl|remoteExec|remoteExecCall|remoteExecutedOwner|remove3DENConnection|remove3DENEventHandler|remove3DENLayer|removeAction|removeAll3DENEventHandlers|removeAllActions|removeAllAssignedItems|removeAllContainers|removeAllCuratorAddons|removeAllCuratorCameraAreas|removeAllCuratorEditingAreas|removeAllEventHandlers|removeAllHandgunItems|removeAllItems|removeAllItemsWithMagazines|removeAllMissionEventHandlers|removeAllMPEventHandlers|removeAllMusicEventHandlers|removeAllOwnedMines|removeAllPrimaryWeaponItems|removeAllWeapons|removeBackpack|removeBackpackGlobal|removeCuratorAddons|removeCuratorCameraArea|removeCuratorEditableObjects|removeCuratorEditingArea|removeDrawIcon|removeDrawLinks|removeEventHandler|removeFromRemainsCollector|removeGoggles|removeGroupIcon|removeHandgunItem|removeHeadgear|removeItem|removeItemFromBackpack|removeItemFromUniform|removeItemFromVest|removeItems|removeMagazine|removeMagazineGlobal|removeMagazines|removeMagazinesTurret|removeMagazineTurret|removeMenuItem|removeMissionEventHandler|removeMPEventHandler|removeMusicEventHandler|removeOwnedMine|removePrimaryWeaponItem|removeSecondaryWeaponItem|removeSimpleTask|removeSwitchableUnit|removeTeamMember|removeUniform|removeVest|removeWeapon|removeWeaponAttachmentCargo|removeWeaponCargo|removeWeaponGlobal|removeWeaponTurret|reportRemoteTarget|requiredVersion|resetCamShake|resetSubgroupDirection|resistance|resize|resources|respawnVehicle|restartEditorCamera|reveal|revealMine|reverse|reversedMouseY|roadAt|roadsConnectedTo|roleDescription|ropeAttachedObjects|ropeAttachedTo|ropeAttachEnabled|ropeAttachTo|ropeCreate|ropeCut|ropeDestroy|ropeDetach|ropeEndPosition|ropeLength|ropes|ropeUnwind|ropeUnwound|rotorsForcesRTD|rotorsRpmRTD|round|runInitScript|safeZoneH|safeZoneW|safeZoneWAbs|safeZoneX|safeZoneXAbs|safeZoneY|save3DENInventory|saveGame|saveIdentity|saveJoysticks|saveOverlay|saveProfileNamespace|saveStatus|saveVar|savingEnabled|say|say2D|say3D|score|scoreSide|screenshot|screenToWorld|scriptDone|scriptName|scriptNull|scudState|secondaryWeapon|secondaryWeaponItems|secondaryWeaponMagazine|select|selectBestPlaces|selectDiarySubject|selectedEditorObjects|selectEditorObject|selectionNames|selectionPosition|selectLeader|selectMax|selectMin|selectNoPlayer|selectPlayer|selectRandom|selectRandomWeighted|selectWeapon|selectWeaponTurret|sendAUMessage|sendSimpleCommand|sendTask|sendTaskResult|sendUDPMessage|serverCommand|serverCommandAvailable|serverCommandExecutable|serverName|serverTime|set|set3DENAttribute|set3DENAttributes|set3DENGrid|set3DENIconsVisible|set3DENLayer|set3DENLinesVisible|set3DENLogicType|set3DENMissionAttribute|set3DENMissionAttributes|set3DENModelsVisible|set3DENObjectType|set3DENSelected|setAccTime|setActualCollectiveRTD|setAirplaneThrottle|setAirportSide|setAmmo|setAmmoCargo|setAmmoOnPylon|setAnimSpeedCoef|setAperture|setApertureNew|setArmoryPoints|setAttributes|setAutonomous|setBehaviour|setBleedingRemaining|setBrakesRTD|setCameraInterest|setCamShakeDefParams|setCamShakeParams|setCamUseTI|setCaptive|setCenterOfMass|setCollisionLight|setCombatMode|setCompassOscillation|setConvoySeparation|setCuratorCameraAreaCeiling|setCuratorCoef|setCuratorEditingAreaType|setCuratorWaypointCost|setCurrentChannel|setCurrentTask|setCurrentWaypoint|setCustomAimCoef|setCustomWeightRTD|setDamage|setDammage|setDate|setDebriefingText|setDefaultCamera|setDestination|setDetailMapBlendPars|setDir|setDirection|setDrawIcon|setDriveOnPath|setDropInterval|setDynamicSimulationDistance|setDynamicSimulationDistanceCoef|setEditorMode|setEditorObjectScope|setEffectCondition|setEngineRpmRTD|setFace|setFaceAnimation|setFatigue|setFeatureType|setFlagAnimationPhase|setFlagOwner|setFlagSide|setFlagTexture|setFog|setForceGeneratorRTD|setFormation|setFormationTask|setFormDir|setFriend|setFromEditor|setFSMVariable|setFuel|setFuelCargo|setGroupIcon|setGroupIconParams|setGroupIconsSelectable|setGroupIconsVisible|setGroupId|setGroupIdGlobal|setGroupOwner|setGusts|setHideBehind|setHit|setHitIndex|setHitPointDamage|setHorizonParallaxCoef|setHUDMovementLevels|setIdentity|setImportance|setInfoPanel|setLeader|setLightAmbient|setLightAttenuation|setLightBrightness|setLightColor|setLightDayLight|setLightFlareMaxDistance|setLightFlareSize|setLightIntensity|setLightnings|setLightUseFlare|setLocalWindParams|setMagazineTurretAmmo|setMarkerAlpha|setMarkerAlphaLocal|setMarkerBrush|setMarkerBrushLocal|setMarkerColor|setMarkerColorLocal|setMarkerDir|setMarkerDirLocal|setMarkerPos|setMarkerPosLocal|setMarkerShape|setMarkerShapeLocal|setMarkerSize|setMarkerSizeLocal|setMarkerText|setMarkerTextLocal|setMarkerType|setMarkerTypeLocal|setMass|setMimic|setMousePosition|setMusicEffect|setMusicEventHandler|setName|setNameSound|setObjectArguments|setObjectMaterial|setObjectMaterialGlobal|setObjectProxy|setObjectTexture|setObjectTextureGlobal|setObjectViewDistance|setOvercast|setOwner|setOxygenRemaining|setParticleCircle|setParticleClass|setParticleFire|setParticleParams|setParticleRandom|setPilotCameraDirection|setPilotCameraRotation|setPilotCameraTarget|setPilotLight|setPiPEffect|setPitch|setPlateNumber|setPlayable|setPlayerRespawnTime|setPos|setPosASL|setPosASL2|setPosASLW|setPosATL|setPosition|setPosWorld|setPylonLoadOut|setPylonsPriority|setRadioMsg|setRain|setRainbow|setRandomLip|setRank|setRectangular|setRepairCargo|setRotorBrakeRTD|setShadowDistance|setShotParents|setSide|setSimpleTaskAlwaysVisible|setSimpleTaskCustomData|setSimpleTaskDescription|setSimpleTaskDestination|setSimpleTaskTarget|setSimpleTaskType|setSimulWeatherLayers|setSize|setSkill|setSlingLoad|setSoundEffect|setSpeaker|setSpeech|setSpeedMode|setStamina|setStaminaScheme|setStatValue|setSuppression|setSystemOfUnits|setTargetAge|setTaskMarkerOffset|setTaskResult|setTaskState|setTerrainGrid|setText|setTimeMultiplier|setTitleEffect|setToneMapping|setToneMappingParams|setTrafficDensity|setTrafficDistance|setTrafficGap|setTrafficSpeed|setTriggerActivation|setTriggerArea|setTriggerStatements|setTriggerText|setTriggerTimeout|setTriggerType|setType|setUnconscious|setUnitAbility|setUnitLoadout|setUnitPos|setUnitPosWeak|setUnitRank|setUnitRecoilCoefficient|setUnitTrait|setUnloadInCombat|setUserActionText|setUserMFDText|setUserMFDValue|setVariable|setVectorDir|setVectorDirAndUp|setVectorUp|setVehicleAmmo|setVehicleAmmoDef|setVehicleArmor|setVehicleCargo|setVehicleId|setVehicleInit|setVehicleLock|setVehiclePosition|setVehicleRadar|setVehicleReceiveRemoteTargets|setVehicleReportOwnPosition|setVehicleReportRemoteTargets|setVehicleTIPars|setVehicleVarName|setVelocity|setVelocityModelSpace|setVelocityTransformation|setViewDistance|setVisibleIfTreeCollapsed|setWantedRpmRTD|setWaves|setWaypointBehaviour|setWaypointCombatMode|setWaypointCompletionRadius|setWaypointDescription|setWaypointForceBehaviour|setWaypointFormation|setWaypointHousePosition|setWaypointLoiterRadius|setWaypointLoiterType|setWaypointName|setWaypointPosition|setWaypointScript|setWaypointSpeed|setWaypointStatements|setWaypointTimeout|setWaypointType|setWaypointVisible|setWeaponReloadingTime|setWind|setWindDir|setWindForce|setWindStr|setWingForceScaleRTD|setWPPos|show3DIcons|showChat|showCinemaBorder|showCommandingMenu|showCompass|showCuratorCompass|showGPS|showHUD|showLegend|showMap|shownArtilleryComputer|shownChat|shownCompass|shownCuratorCompass|showNewEditorObject|shownGPS|shownHUD|shownMap|shownPad|shownRadio|shownScoretable|shownUAVFeed|shownWarrant|shownWatch|showPad|showRadio|showScoretable|showSubtitles|showUAVFeed|showWarrant|showWatch|showWaypoint|showWaypoints|side|sideAmbientLife|sideChat|sideEmpty|sideEnemy|sideFriendly|sideLogic|sideRadio|sideUnknown|simpleTasks|simulationEnabled|simulCloudDensity|simulCloudOcclusion|simulInClouds|simulWeatherSync|sin|size|sizeOf|skill|skillFinal|skipTime|sleep|sliderPosition|sliderRange|sliderSetPosition|sliderSetRange|sliderSetSpeed|sliderSpeed|slingLoadAssistantShown|soldierMagazines|someAmmo|sort|soundVolume|speaker|speed|speedMode|splitString|sqrt|squadParams|stance|startLoadingScreen|stop|stopEngineRTD|stopped|str|sunOrMoon|supportInfo|suppressFor|surfaceIsWater|surfaceNormal|surfaceType|swimInDepth|switchableUnits|switchAction|switchCamera|switchGesture|switchLight|switchMove|synchronizedObjects|synchronizedTriggers|synchronizedWaypoints|synchronizeObjectsAdd|synchronizeObjectsRemove|synchronizeTrigger|synchronizeWaypoint|systemChat|systemOfUnits|tan|targetKnowledge|targets|targetsAggregate|targetsQuery|taskAlwaysVisible|taskChildren|taskCompleted|taskCustomData|taskDescription|taskDestination|taskHint|taskMarkerOffset|taskNull|taskParent|taskResult|taskState|taskType|teamMember|teamMemberNull|teamName|teams|teamSwitch|teamSwitchEnabled|teamType|terminate|terrainIntersect|terrainIntersectASL|terrainIntersectAtASL|text|textLog|textLogFormat|tg|time|timeMultiplier|titleCut|titleFadeOut|titleObj|titleRsc|titleText|toArray|toFixed|toLower|toString|toUpper|triggerActivated|triggerActivation|triggerArea|triggerAttachedVehicle|triggerAttachObject|triggerAttachVehicle|triggerDynamicSimulation|triggerStatements|triggerText|triggerTimeout|triggerTimeoutCurrent|triggerType|turretLocal|turretOwner|turretUnit|tvAdd|tvClear|tvCollapse|tvCollapseAll|tvCount|tvCurSel|tvData|tvDelete|tvExpand|tvExpandAll|tvPicture|tvPictureRight|tvSetColor|tvSetCurSel|tvSetData|tvSetPicture|tvSetPictureColor|tvSetPictureColorDisabled|tvSetPictureColorSelected|tvSetPictureRight|tvSetPictureRightColor|tvSetPictureRightColorDisabled|tvSetPictureRightColorSelected|tvSetSelectColor|tvSetText|tvSetTooltip|tvSetValue|tvSort|tvSortByValue|tvText|tvTooltip|tvValue|type|typeName|typeOf|UAVControl|uiNamespace|uiSleep|unassignCurator|unassignItem|unassignTeam|unassignVehicle|underwater|uniform|uniformContainer|uniformItems|uniformMagazines|unitAddons|unitAimPosition|unitAimPositionVisual|unitBackpack|unitIsUAV|unitPos|unitReady|unitRecoilCoefficient|units|unitsBelowHeight|unlinkItem|unlockAchievement|unregisterTask|updateDrawIcon|updateMenuItem|updateObjectTree|useAIOperMapObstructionTest|useAISteeringComponent|useAudioTimeForMoves|userInputDisabled|vectorAdd|vectorCos|vectorCrossProduct|vectorDiff|vectorDir|vectorDirVisual|vectorDistance|vectorDistanceSqr|vectorDotProduct|vectorFromTo|vectorMagnitude|vectorMagnitudeSqr|vectorModelToWorld|vectorModelToWorldVisual|vectorMultiply|vectorNormalized|vectorUp|vectorUpVisual|vectorWorldToModel|vectorWorldToModelVisual|vehicle|vehicleCargoEnabled|vehicleChat|vehicleRadio|vehicleReceiveRemoteTargets|vehicleReportOwnPosition|vehicleReportRemoteTargets|vehicles|vehicleVarName|velocity|velocityModelSpace|verifySignature|vest|vestContainer|vestItems|vestMagazines|viewDistance|visibleCompass|visibleGPS|visibleMap|visiblePosition|visiblePositionASL|visibleScoretable|visibleWatch|waitUntil|waves|waypointAttachedObject|waypointAttachedVehicle|waypointAttachObject|waypointAttachVehicle|waypointBehaviour|waypointCombatMode|waypointCompletionRadius|waypointDescription|waypointForceBehaviour|waypointFormation|waypointHousePosition|waypointLoiterRadius|waypointLoiterType|waypointName|waypointPosition|waypoints|waypointScript|waypointsEnabledUAV|waypointShow|waypointSpeed|waypointStatements|waypointTimeout|waypointTimeoutCurrent|waypointType|waypointVisible|weaponAccessories|weaponAccessoriesCargo|weaponCargo|weaponDirection|weaponInertia|weaponLowered|weapons|weaponsItems|weaponsItemsCargo|weaponState|weaponsTurret|weightRTD|west|WFSideText|wind|windDir|windRTD|windStr|wingsForcesRTD|worldName|worldSize|worldToModel|worldToModelVisual|worldToScreen)\b/i,number:/(?:\$|\b0x)[\da-f]+\b|(?:\B\.\d+|\b\d+(?:\.\d+)?)(?:e[+-]?\d+)?\b/i,operator:/##|>>|&&|\|\||[!=<>]=?|[-+*/%#^]|\b(?:and|mod|not|or)\b/i,"magic-variable":{pattern:/\b(?:_exception|_fnc_scriptName|_fnc_scriptNameParent|_forEachIndex|_this|_thisEventHandler|_thisFSM|_thisScript|_x|this|thisList|thisTrigger)\b/i,alias:"keyword"},constant:/\bDIK(?:_[a-z\d]+)+\b/i}),Prism.languages.insertBefore("sqf","string",{macro:{pattern:/(^[ \t]*)#[a-z](?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{directive:{pattern:/#[a-z]+\b/i,alias:"keyword"},comment:Prism.languages.sqf.comment}}}),delete Prism.languages.sqf["class-name"]; Prism.languages.squirrel=Prism.languages.extend("clike",{comment:[Prism.languages.clike.comment[0],{pattern:/(^|[^\\:])(?:\/\/|#).*/,lookbehind:!0,greedy:!0}],string:[{pattern:/(^|[^\\"'@])(?:@"(?:[^"]|"")*"(?!")|"(?:[^\\\r\n"]|\\.)*")/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\"'])'(?:[^\\']|\\(?:[xuU][0-9a-fA-F]{0,8}|[\s\S]))'/,lookbehind:!0,greedy:!0}],"class-name":{pattern:/(\b(?:class|enum|extends|instanceof)\s+)\w+(?:\.\w+)*/,lookbehind:!0,inside:{punctuation:/\./}},keyword:/\b(?:base|break|case|catch|class|clone|const|constructor|continue|default|delete|else|enum|extends|for|foreach|function|if|in|instanceof|local|null|resume|return|static|switch|this|throw|try|typeof|while|yield|__LINE__|__FILE__)\b/,number:/\b(?:0x[0-9a-fA-F]+|\d+(?:\.(?:\d+|[eE][+-]?\d+))?)\b/,operator:/\+\+|--|<=>|<[-<]|>>>?|&&?|\|\|?|[-+*/%!=<>]=?|[~^]|::?/,punctuation:/[(){}\[\],;.]/}),Prism.languages.insertBefore("squirrel","operator",{"attribute-punctuation":{pattern:/<\/|\/>/,alias:"important"},lambda:{pattern:/@(?=\()/,alias:"operator"}}); Prism.languages.stan={comment:/\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,string:{pattern:/"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,greedy:!0},directive:{pattern:/^([ \t]*)#include\b.*/m,lookbehind:!0,alias:"property"},"function-arg":{pattern:/(\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\s*\(\s*)[a-zA-Z]\w*/,lookbehind:!0,alias:"function"},constraint:{pattern:/(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,lookbehind:!0,inside:{expression:{pattern:/(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,lookbehind:!0,inside:null},property:/\b[a-z]\w*(?=\s*=)/i,operator:/=/,punctuation:/^<|>$|,/}},keyword:[/\b(?:break|cholesky_factor_corr|cholesky_factor_cov|continue|corr_matrix|cov_matrix|data|else|for|functions|generated|if|in|increment_log_prob|int|matrix|model|ordered|parameters|positive_ordered|print|quantities|real|reject|return|row_vector|simplex|target|transformed|unit_vector|vector|void|while)\b/,/\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\b/],function:/\b[a-z]\w*(?=\s*\()/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,operator:/<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,punctuation:/[()\[\]{},;]/},Prism.languages.stan.constraint.inside.expression.inside=Prism.languages.stan; Prism.languages.iecst={comment:[{pattern:/(^|[^\\])(?:\/\*[\s\S]*?(?:\*\/|$)|\(\*[\s\S]*?(?:\*\)|$)|\{[\s\S]*?(?:\}|$))/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":/\b(?:END_)?(?:PROGRAM|CONFIGURATION|INTERFACE|FUNCTION_BLOCK|FUNCTION|ACTION|TRANSITION|TYPE|STRUCT|(?:INITIAL_)?STEP|NAMESPACE|LIBRARY|CHANNEL|FOLDER|RESOURCE|VAR_(?:GLOBAL|INPUT|PUTPUT|IN_OUT|ACCESS|TEMP|EXTERNAL|CONFIG)|VAR|METHOD|PROPERTY)\b/i,keyword:/\b(?:(?:END_)?(?:IF|WHILE|REPEAT|CASE|FOR)|ELSE|FROM|THEN|ELSIF|DO|TO|BY|PRIVATE|PUBLIC|PROTECTED|CONSTANT|RETURN|EXIT|CONTINUE|GOTO|JMP|AT|RETAIN|NON_RETAIN|TASK|WITH|UNTIL|USING|EXTENDS|IMPLEMENTS|GET|SET|__TRY|__CATCH|__FINALLY|__ENDTRY)\b/,variable:/\b(?:AT|BOOL|BYTE|(?:D|L)?WORD|U?(?:S|D|L)?INT|L?REAL|TIME(?:_OF_DAY)?|TOD|DT|DATE(?:_AND_TIME)?|STRING|ARRAY|ANY|POINTER)\b/,symbol:/%[IQM][XBWDL][\d.]*|%[IQ][\d.]*/,number:/\b(?:16#[\da-f]+|2#[01_]+|0x[\da-f]+)\b|\b(?:T|D|DT|TOD)#[\d_shmd:]*|\b[A-Z]*#[\d.,_]*|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/,function:/\w+(?=\()/,operator:/(?:S?R?:?=>?|&&?|\*\*?|<=?|>=?|[-:^/+])|\b(?:OR|AND|MOD|NOT|XOR|LE|GE|EQ|NE|GT|LT)\b/,punctuation:/[();]/,type:{pattern:/#/,alias:"selector"}}; !function(e){var n={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},r={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},t={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:if|else|for|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:n,number:r,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:n,boolean:/\b(?:true|false)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:r,punctuation:/[{}()\[\];:,]/};t.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:t}},t.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:t}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:t}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:t}},statement:{pattern:/(^[ \t]*)(?:if|else|for|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:t}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:t.interpolation}},rest:t}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:t.interpolation,comment:t.comment,punctuation:/[{},]/}},func:t.func,string:t.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:t.interpolation,punctuation:/[{}()\[\];:.]/}}(Prism); Prism.languages.swift=Prism.languages.extend("clike",{string:{pattern:/("|')(?:\\(?:\((?:[^()]|\([^)]+\))+\)|\r\n|[^(])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/\\\((?:[^()]|\([^)]+\))+\)/,inside:{delimiter:{pattern:/^\\\(|\)$/,alias:"variable"}}}}},keyword:/\b(?:actor|as|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic(?:Type)?|else|enum|extension|fallthrough|final|for|func|get|guard|if|import|in|infix|init|inout|internal|is|lazy|left|let|mutating|new|none|nonisolated|nonmutating|operator|optional|override|postfix|precedence|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|Self|set|some|static|struct|subscript|super|switch|throws?|try|Type|typealias|unowned|unsafe|var|weak|where|while|willSet|__(?:COLUMN__|FILE__|FUNCTION__|LINE__))\b/,number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,constant:/\b(?:nil|[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,atrule:/@\b(?:IB(?:Outlet|Designable|Action|Inspectable)|class_protocol|exported|globalActor|MainActor|noreturn|NS(?:Copying|Managed)|objc|propertyWrapper|UIApplicationMain|auto_closure)\b/,builtin:/\b(?:[A-Z]\S+|abs|advance|alignof(?:Value)?|assert|contains|count(?:Elements)?|debugPrint(?:ln)?|distance|drop(?:First|Last)|dump|enumerate|equal|filter|find|first|getVaList|indices|isEmpty|join|last|lexicographicalCompare|map|max(?:Element)?|min(?:Element)?|numericCast|overlaps|partition|print(?:ln)?|reduce|reflect|reverse|sizeof(?:Value)?|sort(?:ed)?|split|startsWith|stride(?:of(?:Value)?)?|suffix|swap|toDebugString|toString|transcode|underestimateCount|unsafeBitCast|with(?:ExtendedLifetime|Unsafe(?:MutablePointers?|Pointers?)|VaList))\b/}),Prism.languages.swift.string.inside.interpolation.inside.rest=Prism.languages.swift; !function(n){function i(e,t,a){return{pattern:RegExp("<#"+e+"[\\s\\S]*?#>"),alias:"block",inside:{delimiter:{pattern:RegExp("^<#"+e+"|#>$"),alias:"important"},content:{pattern:/[\s\S]+/,inside:t,alias:a}}}}n.languages["t4-templating"]=Object.defineProperty({},"createT4",{value:function(e){var t=n.languages[e],a="language-"+e;return{block:{pattern:/<#[\s\S]+?#>/,inside:{directive:i("@",{"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/,inside:{punctuation:/^=|^["']|["']$/}},keyword:/\b\w+(?=\s)/,"attr-name":/\b\w+/}),expression:i("=",t,a),"class-feature":i("\\+",t,a),standard:i("",t,a)}}}}})}(Prism); Prism.languages.t4=Prism.languages["t4-cs"]=Prism.languages["t4-templating"].createT4("csharp"); Prism.languages.vbnet=Prism.languages.extend("basic",{comment:[{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},{pattern:/(^|[^\\:])'.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(^|[^"])"(?:""|[^"])*"(?!")/i,lookbehind:!0,greedy:!0},keyword:/(?:\b(?:ADDHANDLER|ADDRESSOF|ALIAS|AND|ANDALSO|AS|BEEP|BLOAD|BOOLEAN|BSAVE|BYREF|BYTE|BYVAL|CALL(?: ABSOLUTE)?|CASE|CATCH|CBOOL|CBYTE|CCHAR|CDATE|CDEC|CDBL|CHAIN|CHAR|CHDIR|CINT|CLASS|CLEAR|CLNG|CLOSE|CLS|COBJ|COM|COMMON|CONST|CONTINUE|CSBYTE|CSHORT|CSNG|CSTR|CTYPE|CUINT|CULNG|CUSHORT|DATA|DATE|DECIMAL|DECLARE|DEFAULT|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DELEGATE|DIM|DIRECTCAST|DO|DOUBLE|ELSE|ELSEIF|END|ENUM|ENVIRON|ERASE|ERROR|EVENT|EXIT|FALSE|FIELD|FILES|FINALLY|FOR(?: EACH)?|FRIEND|FUNCTION|GET|GETTYPE|GETXMLNAMESPACE|GLOBAL|GOSUB|GOTO|HANDLES|IF|IMPLEMENTS|IMPORTS|IN|INHERITS|INPUT|INTEGER|INTERFACE|IOCTL|IS|ISNOT|KEY|KILL|LINE INPUT|LET|LIB|LIKE|LOCATE|LOCK|LONG|LOOP|LSET|ME|MKDIR|MOD|MODULE|MUSTINHERIT|MUSTOVERRIDE|MYBASE|MYCLASS|NAME|NAMESPACE|NARROWING|NEW|NEXT|NOT|NOTHING|NOTINHERITABLE|NOTOVERRIDABLE|OBJECT|OF|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPERATOR|OPEN|OPTION(?: BASE)?|OPTIONAL|OR|ORELSE|OUT|OVERLOADS|OVERRIDABLE|OVERRIDES|PARAMARRAY|PARTIAL|POKE|PRIVATE|PROPERTY|PROTECTED|PUBLIC|PUT|RAISEEVENT|READ|READONLY|REDIM|REM|REMOVEHANDLER|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SBYTE|SELECT(?: CASE)?|SET|SHADOWS|SHARED|SHORT|SINGLE|SHELL|SLEEP|STATIC|STEP|STOP|STRING|STRUCTURE|SUB|SYNCLOCK|SWAP|SYSTEM|THEN|THROW|TIMER|TO|TROFF|TRON|TRUE|TRY|TRYCAST|TYPE|TYPEOF|UINTEGER|ULONG|UNLOCK|UNTIL|USHORT|USING|VIEW PRINT|WAIT|WEND|WHEN|WHILE|WIDENING|WITH|WITHEVENTS|WRITE|WRITEONLY|XOR)|\B(?:#CONST|#ELSE|#ELSEIF|#END|#IF))(?:\$|\b)/i,punctuation:/[,;:(){}]/}); Prism.languages["t4-vb"]=Prism.languages["t4-templating"].createT4("vbnet"); !function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"}),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,function(){return t}).replace(/<>/g,function(){return e});return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,function(){return t})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,function(){return t}).replace(/<>/g,function(){return"(?:"+a+"|"+d+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("true|false","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); Prism.languages.tap={fail:/not ok[^#{\n\r]*/,pass:/ok[^#{\n\r]*/,pragma:/pragma [+-][a-z]+/,bailout:/bail out!.*/i,version:/TAP version \d+/i,plan:/\b\d+\.\.\d+(?: +#.*)?/,subtest:{pattern:/# Subtest(?:: .*)?/,greedy:!0},punctuation:/[{}]/,directive:/#.*/,yamlish:{pattern:/(^[ \t]*)---[\s\S]*?[\r\n][ \t]*\.\.\.$/m,lookbehind:!0,inside:Prism.languages.yaml,alias:"language-yaml"}}; Prism.languages.tcl={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"/,greedy:!0},variable:[{pattern:/(\$)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/,lookbehind:!0},{pattern:/(\$)\{[^}]+\}/,lookbehind:!0},{pattern:/(^[\t ]*set[ \t]+)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/m,lookbehind:!0}],function:{pattern:/(^[\t ]*proc[ \t]+)\S+/m,lookbehind:!0},builtin:[{pattern:/(^[\t ]*)(?:proc|return|class|error|eval|exit|for|foreach|if|switch|while|break|continue)\b/m,lookbehind:!0},/\b(?:elseif|else)\b/],scope:{pattern:/(^[\t ]*)(?:global|upvar|variable)\b/m,lookbehind:!0,alias:"constant"},keyword:{pattern:/(^[\t ]*|\[)(?:after|append|apply|array|auto_(?:execok|import|load|mkindex|qualify|reset)|automkindex_old|bgerror|binary|catch|cd|chan|clock|close|concat|dde|dict|encoding|eof|exec|expr|fblocked|fconfigure|fcopy|file(?:event|name)?|flush|gets|glob|history|http|incr|info|interp|join|lappend|lassign|lindex|linsert|list|llength|load|lrange|lrepeat|lreplace|lreverse|lsearch|lset|lsort|math(?:func|op)|memory|msgcat|namespace|open|package|parray|pid|pkg_mkIndex|platform|puts|pwd|re_syntax|read|refchan|regexp|registry|regsub|rename|Safe_Base|scan|seek|set|socket|source|split|string|subst|Tcl|tcl(?:_endOfWord|_findLibrary|startOf(?:Next|Previous)Word|wordBreak(?:After|Before)|test|vars)|tell|time|tm|trace|unknown|unload|unset|update|uplevel|vwait)\b/m,lookbehind:!0},operator:/!=?|\*\*?|==|&&?|\|\|?|<[=<]?|>[=>]?|[-+~\/%?^]|\b(?:eq|ne|in|ni)\b/,punctuation:/[{}()\[\]]/}; !function(t){t.languages.tt2=t.languages.extend("clike",{comment:/#.*|\[%#[\s\S]*?%\]/,keyword:/\b(?:BLOCK|CALL|CASE|CATCH|CLEAR|DEBUG|DEFAULT|ELSE|ELSIF|END|FILTER|FINAL|FOREACH|GET|IF|IN|INCLUDE|INSERT|LAST|MACRO|META|NEXT|PERL|PROCESS|RAWPERL|RETURN|SET|STOP|TAGS|THROW|TRY|SWITCH|UNLESS|USE|WHILE|WRAPPER)\b/,punctuation:/[[\]{},()]/}),t.languages.insertBefore("tt2","number",{operator:/=[>=]?|!=?|<=?|>=?|&&|\|\|?|\b(?:and|or|not)\b/,variable:{pattern:/\b[a-z]\w*(?:\s*\.\s*(?:\d+|\$?[a-z]\w*))*\b/i}}),t.languages.insertBefore("tt2","keyword",{delimiter:{pattern:/^(?:\[%|%%)-?|-?%\]$/,alias:"punctuation"}}),t.languages.insertBefore("tt2","string",{"single-quoted-string":{pattern:/'[^\\']*(?:\\[\s\S][^\\']*)*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"[^\\"]*(?:\\[\s\S][^\\"]*)*"/,greedy:!0,alias:"string",inside:{variable:{pattern:/\$(?:[a-z]\w*(?:\.(?:\d+|\$?[a-z]\w*))*)/i}}}}),delete t.languages.tt2.string,t.hooks.add("before-tokenize",function(e){t.languages["markup-templating"].buildPlaceholders(e,"tt2",/\[%[\s\S]+?%\]/g)}),t.hooks.add("after-tokenize",function(e){t.languages["markup-templating"].tokenizePlaceholders(e,"tt2")})}(Prism); !function(n){function e(n,e){return RegExp(n.replace(//g,function(){return"(?:\\([^|()\n]+\\)|\\[[^\\]\n]+\\]|\\{[^}\n]+\\})"}).replace(//g,function(){return"(?:\\)|\\((?![^|()\n]+\\)))"}),e||"")}var i={css:{pattern:/\{[^{}]+\}/,inside:{rest:n.languages.css}},"class-id":{pattern:/(\()[^()]+(?=\))/,lookbehind:!0,alias:"attr-value"},lang:{pattern:/(\[)[^\[\]]+(?=\])/,lookbehind:!0,alias:"attr-value"},punctuation:/[\\\/]\d+|\S/},t=n.languages.textile=n.languages.extend("markup",{phrase:{pattern:/(^|\r|\n)\S[\s\S]*?(?=$|\r?\n\r?\n|\r\r)/,lookbehind:!0,inside:{"block-tag":{pattern:e("^[a-z]\\w*(?:||[<>=])*\\."),inside:{modifier:{pattern:e("(^[a-z]\\w*)(?:||[<>=])+(?=\\.)"),lookbehind:!0,inside:i},tag:/^[a-z]\w*/,punctuation:/\.$/}},list:{pattern:e("^[*#]+*\\s+\\S.*","m"),inside:{modifier:{pattern:e("(^[*#]+)+"),lookbehind:!0,inside:i},punctuation:/^[*#]+/}},table:{pattern:e("^(?:(?:||[<>=^~])+\\.\\s*)?(?:\\|(?:(?:||[<>=^~_]|[\\\\/]\\d+)+\\.|(?!(?:||[<>=^~_]|[\\\\/]\\d+)+\\.))[^|]*)+\\|","m"),inside:{modifier:{pattern:e("(^|\\|(?:\r?\n|\r)?)(?:||[<>=^~_]|[\\\\/]\\d+)+(?=\\.)"),lookbehind:!0,inside:i},punctuation:/\||^\./}},inline:{pattern:e("(^|[^a-zA-Z\\d])(\\*\\*|__|\\?\\?|[*_%@+\\-^~])*.+?\\2(?![a-zA-Z\\d])"),lookbehind:!0,inside:{bold:{pattern:e("(^(\\*\\*?)*).+?(?=\\2)"),lookbehind:!0},italic:{pattern:e("(^(__?)*).+?(?=\\2)"),lookbehind:!0},cite:{pattern:e("(^\\?\\?*).+?(?=\\?\\?)"),lookbehind:!0,alias:"string"},code:{pattern:e("(^@*).+?(?=@)"),lookbehind:!0,alias:"keyword"},inserted:{pattern:e("(^\\+*).+?(?=\\+)"),lookbehind:!0},deleted:{pattern:e("(^-*).+?(?=-)"),lookbehind:!0},span:{pattern:e("(^%*).+?(?=%)"),lookbehind:!0},modifier:{pattern:e("(^\\*\\*|__|\\?\\?|[*_%@+\\-^~])+"),lookbehind:!0,inside:i},punctuation:/[*_%?@+\-^~]+/}},"link-ref":{pattern:/^\[[^\]]+\]\S+$/m,inside:{string:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0},url:{pattern:/(^\])\S+$/,lookbehind:!0},punctuation:/[\[\]]/}},link:{pattern:e('"*[^"]+":.+?(?=[^\\w/]?(?:\\s|$))'),inside:{text:{pattern:e('(^"*)[^"]+(?=")'),lookbehind:!0},modifier:{pattern:e('(^")+'),lookbehind:!0,inside:i},url:{pattern:/(:).+/,lookbehind:!0},punctuation:/[":]/}},image:{pattern:e("!(?:||[<>=])*(?![<>=])[^!\\s()]+(?:\\([^)]+\\))?!(?::.+?(?=[^\\w/]?(?:\\s|$)))?"),inside:{source:{pattern:e("(^!(?:||[<>=])*)(?![<>=])[^!\\s()]+(?:\\([^)]+\\))?(?=!)"),lookbehind:!0,alias:"url"},modifier:{pattern:e("(^!)(?:||[<>=])+"),lookbehind:!0,inside:i},url:{pattern:/(:).+/,lookbehind:!0},punctuation:/[!:]/}},footnote:{pattern:/\b\[\d+\]/,alias:"comment",inside:{punctuation:/\[|\]/}},acronym:{pattern:/\b[A-Z\d]+\([^)]+\)/,inside:{comment:{pattern:/(\()[^()]+(?=\))/,lookbehind:!0},punctuation:/[()]/}},mark:{pattern:/\b\((?:TM|R|C)\)/,alias:"comment",inside:{punctuation:/[()]/}}}}}),a=t.phrase.inside,o={inline:a.inline,link:a.link,image:a.image,footnote:a.footnote,acronym:a.acronym,mark:a.mark};t.tag.pattern=/<\/?(?!\d)[a-z0-9]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i;var r=a.inline.inside;r.bold.inside=o,r.italic.inside=o,r.inserted.inside=o,r.deleted.inside=o,r.span.inside=o;var d=a.table.inside;d.inline=o.inline,d.link=o.link,d.image=o.image,d.footnote=o.footnote,d.acronym=o.acronym,d.mark=o.mark}(Prism); !function(e){function n(e){return e.replace(/__/g,function(){return"(?:[\\w-]+|'[^'\n\r]*'|\"(?:\\\\.|[^\\\\\"\r\n])*\")"})}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n("(^[\t ]*\\[\\s*(?:\\[\\s*)?)__(?:\\s*\\.\\s*__)*(?=\\s*\\])"),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n("(^[\t ]*|[{,]\\s*)__(?:\\s*\\.\\s*__)*(?=\\s*=)"),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:true|false)\b/,punctuation:/[.,=[\]{}]/}}(Prism); Prism.languages.twig={comment:/\{#[\s\S]*?#\}/,tag:{pattern:/\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}/,inside:{ld:{pattern:/^(?:\{\{-?|\{%-?\s*\w+)/,inside:{punctuation:/^(?:\{\{|\{%)-?/,keyword:/\w+/}},rd:{pattern:/-?(?:%\}|\}\})$/,inside:{punctuation:/.+/}},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,inside:{punctuation:/^['"]|['"]$/}},keyword:/\b(?:even|if|odd)\b/,boolean:/\b(?:true|false|null)\b/,number:/\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,operator:[{pattern:/(\s)(?:and|b-and|b-xor|b-or|ends with|in|is|matches|not|or|same as|starts with)(?=\s)/,lookbehind:!0},/[=<>]=?|!=|\*\*?|\/\/?|\?:?|[-+~%|]/],property:/\b[a-zA-Z_]\w*\b/,punctuation:/[()\[\]{}:.,]/}},other:{pattern:/\S(?:[\s\S]*\S)?/,inside:Prism.languages.markup}}; !function(E){var n=/\b(?:ACT|ACTIFSUB|CARRAY|CASE|CLEARGIF|COA|COA_INT|CONSTANTS|CONTENT|CUR|EDITPANEL|EFFECT|EXT|FILE|FLUIDTEMPLATE|FORM|FRAME|FRAMESET|GIFBUILDER|GMENU|GMENU_FOLDOUT|GMENU_LAYERS|GP|HMENU|HRULER|HTML|IENV|IFSUB|IMAGE|IMGMENU|IMGMENUITEM|IMGTEXT|IMG_RESOURCE|INCLUDE_TYPOSCRIPT|JSMENU|JSMENUITEM|LLL|LOAD_REGISTER|NO|PAGE|RECORDS|RESTORE_REGISTER|TEMPLATE|TEXT|TMENU|TMENUITEM|TMENU_LAYERS|USER|USER_INT|_GIFBUILDER|global|globalString|globalVar)\b/;E.languages.typoscript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:= \t]|(?:^|[^= \t])[ \t]+)\/\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^"'])#.*/,lookbehind:!0,greedy:!0}],function:[{pattern://,inside:{string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,inside:{keyword:n}},keyword:{pattern:/INCLUDE_TYPOSCRIPT/}}},{pattern:/@import\s*(?:"[^"\r\n]*"|'[^'\r\n]*')/,inside:{string:/"[^"\r\n]*"|'[^'\r\n]*'/}}],string:{pattern:/^([^=]*=[< ]?)(?:(?!\]\n).)*/,lookbehind:!0,inside:{function:/\{\$.*\}/,keyword:n,number:/^[0-9]+$/,punctuation:/[,|:]/}},keyword:n,number:{pattern:/\b[0-9]+\s*[.{=]/,inside:{operator:/[.{=]/}},tag:{pattern:/\.?[-\w\\]+\.?/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:|]/,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/},E.languages.tsconfig=E.languages.typoscript}(Prism); Prism.languages.unrealscript={comment:/\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},category:{pattern:/(\b(?:(?:autoexpand|hide|show)categories|var)\s*\()[^()]+(?=\))/,lookbehind:!0,greedy:!0,alias:"property"},metadata:{pattern:/(\w\s*)<\s*\w+\s*=[^<>|=\r\n]+(?:\|\s*\w+\s*=[^<>|=\r\n]+)*>/,lookbehind:!0,greedy:!0,inside:{property:/\b\w+(?=\s*=)/,operator:/=/,punctuation:/[<>|]/}},macro:{pattern:/`\w+/,alias:"property"},"class-name":{pattern:/(\b(?:class|enum|extends|interface|state(?:\(\))?|struct|within)\s+)\w+/,lookbehind:!0},keyword:/\b(?:abstract|actor|array|auto|autoexpandcategories|bool|break|byte|case|class|classgroup|client|coerce|collapsecategories|config|const|continue|default|defaultproperties|delegate|dependson|deprecated|do|dontcollapsecategories|editconst|editinlinenew|else|enum|event|exec|export|extends|final|float|for|forcescriptorder|foreach|function|goto|guid|hidecategories|hidedropdown|if|ignores|implements|inherits|input|int|interface|iterator|latent|local|material|name|native|nativereplication|noexport|nontransient|noteditinlinenew|notplaceable|operator|optional|out|pawn|perobjectconfig|perobjectlocalized|placeable|postoperator|preoperator|private|protected|reliable|replication|return|server|showcategories|simulated|singular|state|static|string|struct|structdefault|structdefaultproperties|switch|texture|transient|travel|unreliable|until|var|vector|while|within)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/>>|<<|--|\+\+|\*\*|[-+*/~!=<>$@]=?|&&?|\|\|?|\^\^?|[?:%]|\b(?:Cross|Dot|ClockwiseFrom)\b/,punctuation:/[()[\]{};,.]/},Prism.languages.uc=Prism.languages.uscript=Prism.languages.unrealscript; Prism.languages.uri={scheme:{pattern:/^[a-z][a-z0-9+.-]*:/im,greedy:!0,inside:{"scheme-delimiter":/:$/}},fragment:{pattern:/#[\w\-.~!$&'()*+,;=%:@/?]*/,inside:{"fragment-delimiter":/^#/}},query:{pattern:/\?[\w\-.~!$&'()*+,;=%:@/?]*/,inside:{"query-delimiter":{pattern:/^\?/,greedy:!0},"pair-delimiter":/[&;]/,pair:{pattern:/^[^=][\s\S]*/,inside:{key:/^[^=]+/,value:{pattern:/(^=)[\s\S]+/,lookbehind:!0}}}}},authority:{pattern:RegExp("^//(?:[\\w\\-.~!$&'()*+,;=%:]*@)?(?:\\[(?:[0-9a-fA-F:.]{2,48}|v[0-9a-fA-F]+\\.[\\w\\-.~!$&'()*+,;=]+)\\]|[\\w\\-.~!$&'()*+,;=%]*)(?::\\d*)?","m"),inside:{"authority-delimiter":/^\/\//,"user-info-segment":{pattern:/^[\w\-.~!$&'()*+,;=%:]*@/,inside:{"user-info-delimiter":/@$/,"user-info":/^[\w\-.~!$&'()*+,;=%:]+/}},"port-segment":{pattern:/:\d*$/,inside:{"port-delimiter":/^:/,port:/^\d+/}},host:{pattern:/[\s\S]+/,inside:{"ip-literal":{pattern:/^\[[\s\S]+\]$/,inside:{"ip-literal-delimiter":/^\[|\]$/,"ipv-future":/^v[\s\S]+/,"ipv6-address":/^[\s\S]+/}},"ipv4-address":/^(?:(?:[03-9]\d?|[12]\d{0,2})\.){3}(?:[03-9]\d?|[12]{0,2})$/}}}},path:{pattern:/^[\w\-.~!$&'()*+,;=%:@/]+/m,inside:{"path-separator":/\//}}},Prism.languages.url=Prism.languages.uri; !function(e){var n={pattern:/[\s\S]+/,inside:null};e.languages.v=e.languages.extend("clike",{string:[{pattern:/`(?:\\`|\\?[^`]{1,2})`/,alias:"rune"},{pattern:/r?(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,alias:"quoted-string",greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\{[^{}]*\}|\w+(?:\.\w+(?:\([^\(\)]*\))?|\[[^\[\]]+\])*)/,lookbehind:!0,inside:{"interpolation-variable":{pattern:/^\$\w[\s\S]*$/,alias:"variable"},"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},"interpolation-expression":n}}}}],"class-name":{pattern:/(\b(?:enum|interface|struct|type)\s+)(?:C\.)?\w+/,lookbehind:!0},keyword:/(?:\b(?:as|asm|assert|atomic|break|chan|const|continue|defer|else|embed|enum|fn|for|__global|go(?:to)?|if|import|in|interface|is|lock|match|module|mut|none|or|pub|return|rlock|select|shared|sizeof|static|struct|type(?:of)?|union|unsafe)|\$(?:if|else|for)|#(?:include|flag))\b/,number:/\b(?:0x[a-f\d]+(?:_[a-f\d]+)*|0b[01]+(?:_[01]+)*|0o[0-7]+(?:_[0-7]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?)\b/i,operator:/~|\?|[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\.?/,builtin:/\b(?:any(?:_int|_float)?|bool|byte(?:ptr)?|charptr|f(?:32|64)|i(?:8|16|nt|64|128)|rune|size_t|string|u(?:16|32|64|128)|voidptr)\b/}),n.inside=e.languages.v,e.languages.insertBefore("v","operator",{attribute:{pattern:/(^[\t ]*)\[(?:deprecated|unsafe_fn|typedef|live|inline|flag|ref_only|windows_stdcall|direct_array_access)\]/m,lookbehind:!0,alias:"annotation",inside:{punctuation:/[\[\]]/,keyword:/\w+/}},generic:{pattern:/<\w+>(?=\s*[\)\{])/,inside:{punctuation:/[<>]/,"class-name":/\w+/}}}),e.languages.insertBefore("v","function",{"generic-function":{pattern:/\b\w+\s*<\w+>(?=\()/,inside:{function:/^\w+/,generic:{pattern:/<\w+>/,inside:e.languages.v.generic.inside}}}})}(Prism); Prism.languages.vala=Prism.languages.extend("clike",{"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=(?:\?\s+|\*?\s+\*?)\w)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new|struct|enum)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],keyword:/\b(?:bool|char|double|float|null|size_t|ssize_t|string|unichar|void|int|int8|int16|int32|int64|long|short|uchar|uint|uint8|uint16|uint32|uint64|ulong|ushort|class|delegate|enum|errordomain|interface|namespace|struct|break|continue|do|for|foreach|return|while|else|if|switch|assert|case|default|abstract|const|dynamic|ensures|extern|inline|internal|override|private|protected|public|requires|signal|static|virtual|volatile|weak|async|owned|unowned|try|catch|finally|throw|as|base|construct|delete|get|in|is|lock|new|out|params|ref|sizeof|set|this|throws|typeof|using|value|var|yield)\b/i,function:/\b\w+(?=\s*\()/,number:/(?:\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)(?:f|u?l?)?/i,operator:/\+\+|--|&&|\|\||<<=?|>>=?|=>|->|~|[+\-*\/%&^|=!<>]=?|\?\??|\.\.\./,punctuation:/[{}[\];(),.:]/,constant:/\b[A-Z0-9_]+\b/}),Prism.languages.insertBefore("vala","string",{"raw-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},"template-string":{pattern:/@"[\s\S]*?"/,greedy:!0,inside:{interpolation:{pattern:/\$(?:\([^)]*\)|[a-zA-Z]\w*)/,inside:{delimiter:{pattern:/^\$\(?|\)$/,alias:"punctuation"},rest:Prism.languages.vala}},string:/[\s\S]+/}}}),Prism.languages.insertBefore("vala","keyword",{regex:{pattern:/\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[imsx]{0,4}(?=\s*(?:$|[\r\n,.;})\]]))/,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\//,"regex-flags":/^[a-z]+$/}}}); !function(e){e.languages.velocity=e.languages.extend("markup",{});var n={variable:{pattern:/(^|[^\\](?:\\\\)*)\$!?(?:[a-z][\w-]*(?:\([^)]*\))?(?:\.[a-z][\w-]*(?:\([^)]*\))?|\[[^\]]+\])*|\{[^}]+\})/i,lookbehind:!0,inside:{}},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},number:/\b\d+\b/,boolean:/\b(?:true|false)\b/,operator:/[=!<>]=?|[+*/%-]|&&|\|\||\.\.|\b(?:eq|g[et]|l[et]|n(?:e|ot))\b/,punctuation:/[(){}[\]:,.]/};n.variable.inside={string:n.string,function:{pattern:/([^\w-])[a-z][\w-]*(?=\()/,lookbehind:!0},number:n.number,boolean:n.boolean,punctuation:n.punctuation},e.languages.insertBefore("velocity","comment",{unparsed:{pattern:/(^|[^\\])#\[\[[\s\S]*?\]\]#/,lookbehind:!0,greedy:!0,inside:{punctuation:/^#\[\[|\]\]#$/}},"velocity-comment":[{pattern:/(^|[^\\])#\*[\s\S]*?\*#/,lookbehind:!0,greedy:!0,alias:"comment"},{pattern:/(^|[^\\])##.*/,lookbehind:!0,greedy:!0,alias:"comment"}],directive:{pattern:/(^|[^\\](?:\\\\)*)#@?(?:[a-z][\w-]*|\{[a-z][\w-]*\})(?:\s*\((?:[^()]|\([^()]*\))*\))?/i,lookbehind:!0,inside:{keyword:{pattern:/^#@?(?:[a-z][\w-]*|\{[a-z][\w-]*\})|\bin\b/,inside:{punctuation:/[{}]/}},rest:n}},variable:n.variable}),e.languages.velocity.tag.inside["attr-value"].inside.rest=e.languages.velocity}(Prism); Prism.languages.verilog={comment:/\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},property:/\B\$\w+\b/,constant:/\B`\w+\b/,function:/\b\w+(?=\()/,keyword:/\b(?:alias|and|assert|assign|assume|automatic|before|begin|bind|bins|binsof|bit|break|buf|bufif0|bufif1|byte|class|case|casex|casez|cell|chandle|clocking|cmos|config|const|constraint|context|continue|cover|covergroup|coverpoint|cross|deassign|default|defparam|design|disable|dist|do|edge|else|end|endcase|endclass|endclocking|endconfig|endfunction|endgenerate|endgroup|endinterface|endmodule|endpackage|endprimitive|endprogram|endproperty|endspecify|endsequence|endtable|endtask|enum|event|expect|export|extends|extern|final|first_match|for|force|foreach|forever|fork|forkjoin|function|generate|genvar|highz0|highz1|if|iff|ifnone|ignore_bins|illegal_bins|import|incdir|include|initial|inout|input|inside|instance|int|integer|interface|intersect|join|join_any|join_none|large|liblist|library|local|localparam|logic|longint|macromodule|matches|medium|modport|module|nand|negedge|new|nmos|nor|noshowcancelled|not|notif0|notif1|null|or|output|package|packed|parameter|pmos|posedge|primitive|priority|program|property|protected|pull0|pull1|pulldown|pullup|pulsestyle_onevent|pulsestyle_ondetect|pure|rand|randc|randcase|randsequence|rcmos|real|realtime|ref|reg|release|repeat|return|rnmos|rpmos|rtran|rtranif0|rtranif1|scalared|sequence|shortint|shortreal|showcancelled|signed|small|solve|specify|specparam|static|string|strong0|strong1|struct|super|supply0|supply1|table|tagged|task|this|throughout|time|timeprecision|timeunit|tran|tranif0|tranif1|tri|tri0|tri1|triand|trior|trireg|type|typedef|union|unique|unsigned|use|uwire|var|vectored|virtual|void|wait|wait_order|wand|weak0|weak1|while|wildcard|wire|with|within|wor|xnor|xor)\b/,important:/\b(?:always_latch|always_comb|always_ff|always)\b ?@?/,number:/\B##?\d+|(?:\b\d+)?'[odbh] ?[\da-fzx_?]+|\b(?:\d*[._])?\d+(?:e[-+]?\d+)?/i,operator:/[-+{}^~%*\/?=!<>&|]+/,punctuation:/[[\];(),.:]/}; Prism.languages.vhdl={comment:/--.+/,"vhdl-vectors":{pattern:/\b[oxb]"[\da-f_]+"|"[01uxzwlh-]+"/i,alias:"number"},"quoted-function":{pattern:/"\S+?"(?=\()/,alias:"function"},string:/"(?:[^\\"\r\n]|\\(?:\r\n|[\s\S]))*"/,constant:/\b(?:use|library)\b/i,keyword:/\b(?:'active|'ascending|'base|'delayed|'driving|'driving_value|'event|'high|'image|'instance_name|'last_active|'last_event|'last_value|'left|'leftof|'length|'low|'path_name|'pos|'pred|'quiet|'range|'reverse_range|'right|'rightof|'simple_name|'stable|'succ|'transaction|'val|'value|access|after|alias|all|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|new|next|null|of|on|open|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|report|return|select|severity|shared|signal|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with)\b/i,boolean:/\b(?:true|false)\b/i,function:/\w+(?=\()/,number:/'[01uxzwlh-]'|\b(?:\d+#[\da-f_.]+#|\d[\d_.]*)(?:e[-+]?\d+)?/i,operator:/[<>]=?|:=|[-+*/&=]|\b(?:abs|not|mod|rem|sll|srl|sla|sra|rol|ror|and|or|nand|xnor|xor|nor)\b/i,punctuation:/[{}[\];(),.:]/}; Prism.languages.vim={string:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\r\n]|'')*'/,comment:/".*/,function:/\b\w+(?=\()/,keyword:/\b(?:ab|abbreviate|abc|abclear|abo|aboveleft|al|all|arga|argadd|argd|argdelete|argdo|arge|argedit|argg|argglobal|argl|arglocal|ar|args|argu|argument|as|ascii|bad|badd|ba|ball|bd|bdelete|be|bel|belowright|bf|bfirst|bl|blast|bm|bmodified|bn|bnext|bN|bNext|bo|botright|bp|bprevious|brea|break|breaka|breakadd|breakd|breakdel|breakl|breaklist|br|brewind|bro|browse|bufdo|b|buffer|buffers|bun|bunload|bw|bwipeout|ca|cabbrev|cabc|cabclear|caddb|caddbuffer|cad|caddexpr|caddf|caddfile|cal|call|cat|catch|cb|cbuffer|cc|ccl|cclose|cd|ce|center|cex|cexpr|cf|cfile|cfir|cfirst|cgetb|cgetbuffer|cgete|cgetexpr|cg|cgetfile|c|change|changes|chd|chdir|che|checkpath|checkt|checktime|cla|clast|cl|clist|clo|close|cmapc|cmapclear|cnew|cnewer|cn|cnext|cN|cNext|cnf|cnfile|cNfcNfile|cnorea|cnoreabbrev|col|colder|colo|colorscheme|comc|comclear|comp|compiler|conf|confirm|con|continue|cope|copen|co|copy|cpf|cpfile|cp|cprevious|cq|cquit|cr|crewind|cuna|cunabbrev|cu|cunmap|cw|cwindow|debugg|debuggreedy|delc|delcommand|d|delete|delf|delfunction|delm|delmarks|diffg|diffget|diffoff|diffpatch|diffpu|diffput|diffsplit|diffthis|diffu|diffupdate|dig|digraphs|di|display|dj|djump|dl|dlist|dr|drop|ds|dsearch|dsp|dsplit|earlier|echoe|echoerr|echom|echomsg|echon|e|edit|el|else|elsei|elseif|em|emenu|endfo|endfor|endf|endfunction|endfun|en|endif|endt|endtry|endw|endwhile|ene|enew|ex|exi|exit|exu|exusage|f|file|files|filetype|fina|finally|fin|find|fini|finish|fir|first|fix|fixdel|fo|fold|foldc|foldclose|folddoc|folddoclosed|foldd|folddoopen|foldo|foldopen|for|fu|fun|function|go|goto|gr|grep|grepa|grepadd|ha|hardcopy|h|help|helpf|helpfind|helpg|helpgrep|helpt|helptags|hid|hide|his|history|ia|iabbrev|iabc|iabclear|if|ij|ijump|il|ilist|imapc|imapclear|in|inorea|inoreabbrev|isearch|isp|isplit|iuna|iunabbrev|iu|iunmap|j|join|ju|jumps|k|keepalt|keepj|keepjumps|kee|keepmarks|laddb|laddbuffer|lad|laddexpr|laddf|laddfile|lan|language|la|last|later|lb|lbuffer|lc|lcd|lch|lchdir|lcl|lclose|let|left|lefta|leftabove|lex|lexpr|lf|lfile|lfir|lfirst|lgetb|lgetbuffer|lgete|lgetexpr|lg|lgetfile|lgr|lgrep|lgrepa|lgrepadd|lh|lhelpgrep|l|list|ll|lla|llast|lli|llist|lmak|lmake|lm|lmap|lmapc|lmapclear|lnew|lnewer|lne|lnext|lN|lNext|lnf|lnfile|lNf|lNfile|ln|lnoremap|lo|loadview|loc|lockmarks|lockv|lockvar|lol|lolder|lop|lopen|lpf|lpfile|lp|lprevious|lr|lrewind|ls|lt|ltag|lu|lunmap|lv|lvimgrep|lvimgrepa|lvimgrepadd|lw|lwindow|mak|make|ma|mark|marks|mat|match|menut|menutranslate|mk|mkexrc|mks|mksession|mksp|mkspell|mkvie|mkview|mkv|mkvimrc|mod|mode|m|move|mzf|mzfile|mz|mzscheme|nbkey|new|n|next|N|Next|nmapc|nmapclear|noh|nohlsearch|norea|noreabbrev|nu|number|nun|nunmap|omapc|omapclear|on|only|o|open|opt|options|ou|ounmap|pc|pclose|ped|pedit|pe|perl|perld|perldo|po|pop|popu|popup|pp|ppop|pre|preserve|prev|previous|p|print|P|Print|profd|profdel|prof|profile|promptf|promptfind|promptr|promptrepl|ps|psearch|pta|ptag|ptf|ptfirst|ptj|ptjump|ptl|ptlast|ptn|ptnext|ptN|ptNext|ptp|ptprevious|ptr|ptrewind|pts|ptselect|pu|put|pw|pwd|pyf|pyfile|py|python|qa|qall|q|quit|quita|quitall|r|read|rec|recover|redi|redir|red|redo|redr|redraw|redraws|redrawstatus|reg|registers|res|resize|ret|retab|retu|return|rew|rewind|ri|right|rightb|rightbelow|rub|ruby|rubyd|rubydo|rubyf|rubyfile|ru|runtime|rv|rviminfo|sal|sall|san|sandbox|sa|sargument|sav|saveas|sba|sball|sbf|sbfirst|sbl|sblast|sbm|sbmodified|sbn|sbnext|sbN|sbNext|sbp|sbprevious|sbr|sbrewind|sb|sbuffer|scripte|scriptencoding|scrip|scriptnames|se|set|setf|setfiletype|setg|setglobal|setl|setlocal|sf|sfind|sfir|sfirst|sh|shell|sign|sil|silent|sim|simalt|sla|slast|sl|sleep|sm|smagic|smap|smapc|smapclear|sme|smenu|sn|snext|sN|sNext|sni|sniff|sno|snomagic|snor|snoremap|snoreme|snoremenu|sor|sort|so|source|spelld|spelldump|spe|spellgood|spelli|spellinfo|spellr|spellrepall|spellu|spellundo|spellw|spellwrong|sp|split|spr|sprevious|sre|srewind|sta|stag|startg|startgreplace|star|startinsert|startr|startreplace|stj|stjump|st|stop|stopi|stopinsert|sts|stselect|sun|sunhide|sunm|sunmap|sus|suspend|sv|sview|syncbind|t|tab|tabc|tabclose|tabd|tabdo|tabe|tabedit|tabf|tabfind|tabfir|tabfirst|tabl|tablast|tabm|tabmove|tabnew|tabn|tabnext|tabN|tabNext|tabo|tabonly|tabp|tabprevious|tabr|tabrewind|tabs|ta|tag|tags|tc|tcl|tcld|tcldo|tclf|tclfile|te|tearoff|tf|tfirst|th|throw|tj|tjump|tl|tlast|tm|tmenu|tn|tnext|tN|tNext|to|topleft|tp|tprevious|tr|trewind|try|ts|tselect|tu|tunmenu|una|unabbreviate|u|undo|undoj|undojoin|undol|undolist|unh|unhide|unlet|unlo|unlockvar|unm|unmap|up|update|verb|verbose|ve|version|vert|vertical|vie|view|vim|vimgrep|vimgrepa|vimgrepadd|vi|visual|viu|viusage|vmapc|vmapclear|vne|vnew|vs|vsplit|vu|vunmap|wa|wall|wh|while|winc|wincmd|windo|winp|winpos|win|winsize|wn|wnext|wN|wNext|wp|wprevious|wq|wqa|wqall|w|write|ws|wsverb|wv|wviminfo|X|xa|xall|x|xit|xm|xmap|xmapc|xmapclear|xme|xmenu|XMLent|XMLns|xn|xnoremap|xnoreme|xnoremenu|xu|xunmap|y|yank)\b/,builtin:/\b(?:autocmd|acd|ai|akm|aleph|allowrevins|altkeymap|ambiwidth|ambw|anti|antialias|arab|arabic|arabicshape|ari|arshape|autochdir|autoindent|autoread|autowrite|autowriteall|aw|awa|background|backspace|backup|backupcopy|backupdir|backupext|backupskip|balloondelay|ballooneval|balloonexpr|bdir|bdlay|beval|bex|bexpr|bg|bh|bin|binary|biosk|bioskey|bk|bkc|bomb|breakat|brk|browsedir|bs|bsdir|bsk|bt|bufhidden|buflisted|buftype|casemap|ccv|cdpath|cedit|cfu|ch|charconvert|ci|cin|cindent|cink|cinkeys|cino|cinoptions|cinw|cinwords|clipboard|cmdheight|cmdwinheight|cmp|cms|columns|com|comments|commentstring|compatible|complete|completefunc|completeopt|consk|conskey|copyindent|cot|cpo|cpoptions|cpt|cscopepathcomp|cscopeprg|cscopequickfix|cscopetag|cscopetagorder|cscopeverbose|cspc|csprg|csqf|cst|csto|csverb|cuc|cul|cursorcolumn|cursorline|cwh|debug|deco|def|define|delcombine|dex|dg|dict|dictionary|diff|diffexpr|diffopt|digraph|dip|dir|directory|dy|ea|ead|eadirection|eb|ed|edcompatible|ef|efm|ei|ek|enc|encoding|endofline|eol|ep|equalalways|equalprg|errorbells|errorfile|errorformat|esckeys|et|eventignore|expandtab|exrc|fcl|fcs|fdc|fde|fdi|fdl|fdls|fdm|fdn|fdo|fdt|fen|fenc|fencs|fex|ff|ffs|fileencoding|fileencodings|fileformat|fileformats|fillchars|fk|fkmap|flp|fml|fmr|foldcolumn|foldenable|foldexpr|foldignore|foldlevel|foldlevelstart|foldmarker|foldmethod|foldminlines|foldnestmax|foldtext|formatexpr|formatlistpat|formatoptions|formatprg|fp|fs|fsync|ft|gcr|gd|gdefault|gfm|gfn|gfs|gfw|ghr|gp|grepformat|grepprg|gtl|gtt|guicursor|guifont|guifontset|guifontwide|guiheadroom|guioptions|guipty|guitablabel|guitabtooltip|helpfile|helpheight|helplang|hf|hh|hi|hidden|highlight|hk|hkmap|hkmapp|hkp|hl|hlg|hls|hlsearch|ic|icon|iconstring|ignorecase|im|imactivatekey|imak|imc|imcmdline|imd|imdisable|imi|iminsert|ims|imsearch|inc|include|includeexpr|incsearch|inde|indentexpr|indentkeys|indk|inex|inf|infercase|insertmode|isf|isfname|isi|isident|isk|iskeyword|isprint|joinspaces|js|key|keymap|keymodel|keywordprg|km|kmp|kp|langmap|langmenu|laststatus|lazyredraw|lbr|lcs|linebreak|lines|linespace|lisp|lispwords|listchars|loadplugins|lpl|lsp|lz|macatsui|magic|makeef|makeprg|matchpairs|matchtime|maxcombine|maxfuncdepth|maxmapdepth|maxmem|maxmempattern|maxmemtot|mco|mef|menuitems|mfd|mh|mis|mkspellmem|ml|mls|mm|mmd|mmp|mmt|modeline|modelines|modifiable|modified|more|mouse|mousef|mousefocus|mousehide|mousem|mousemodel|mouses|mouseshape|mouset|mousetime|mp|mps|msm|mzq|mzquantum|nf|nrformats|numberwidth|nuw|odev|oft|ofu|omnifunc|opendevice|operatorfunc|opfunc|osfiletype|pa|para|paragraphs|paste|pastetoggle|patchexpr|patchmode|path|pdev|penc|pex|pexpr|pfn|ph|pheader|pi|pm|pmbcs|pmbfn|popt|preserveindent|previewheight|previewwindow|printdevice|printencoding|printexpr|printfont|printheader|printmbcharset|printmbfont|printoptions|prompt|pt|pumheight|pvh|pvw|qe|quoteescape|readonly|remap|report|restorescreen|revins|rightleft|rightleftcmd|rl|rlc|ro|rs|rtp|ruf|ruler|rulerformat|runtimepath|sbo|sc|scb|scr|scroll|scrollbind|scrolljump|scrolloff|scrollopt|scs|sect|sections|secure|sel|selection|selectmode|sessionoptions|sft|shcf|shellcmdflag|shellpipe|shellquote|shellredir|shellslash|shelltemp|shelltype|shellxquote|shiftround|shiftwidth|shm|shortmess|shortname|showbreak|showcmd|showfulltag|showmatch|showmode|showtabline|shq|si|sidescroll|sidescrolloff|siso|sj|slm|smartcase|smartindent|smarttab|smc|smd|softtabstop|sol|spc|spell|spellcapcheck|spellfile|spelllang|spellsuggest|spf|spl|splitbelow|splitright|sps|sr|srr|ss|ssl|ssop|stal|startofline|statusline|stl|stmp|su|sua|suffixes|suffixesadd|sw|swapfile|swapsync|swb|swf|switchbuf|sws|sxq|syn|synmaxcol|syntax|tabline|tabpagemax|tabstop|tagbsearch|taglength|tagrelative|tagstack|tal|tb|tbi|tbidi|tbis|tbs|tenc|term|termbidi|termencoding|terse|textauto|textmode|textwidth|tgst|thesaurus|tildeop|timeout|timeoutlen|title|titlelen|titleold|titlestring|toolbar|toolbariconsize|top|tpm|tsl|tsr|ttimeout|ttimeoutlen|ttm|tty|ttybuiltin|ttyfast|ttym|ttymouse|ttyscroll|ttytype|tw|tx|uc|ul|undolevels|updatecount|updatetime|ut|vb|vbs|vdir|verbosefile|vfile|viewdir|viewoptions|viminfo|virtualedit|visualbell|vop|wak|warn|wb|wc|wcm|wd|weirdinvert|wfh|wfw|whichwrap|wi|wig|wildchar|wildcharm|wildignore|wildmenu|wildmode|wildoptions|wim|winaltkeys|window|winfixheight|winfixwidth|winheight|winminheight|winminwidth|winwidth|wiv|wiw|wm|wmh|wmnu|wmw|wop|wrap|wrapmargin|wrapscan|writeany|writebackup|writedelay|ww|noacd|noai|noakm|noallowrevins|noaltkeymap|noanti|noantialias|noar|noarab|noarabic|noarabicshape|noari|noarshape|noautochdir|noautoindent|noautoread|noautowrite|noautowriteall|noaw|noawa|nobackup|noballooneval|nobeval|nobin|nobinary|nobiosk|nobioskey|nobk|nobl|nobomb|nobuflisted|nocf|noci|nocin|nocindent|nocompatible|noconfirm|noconsk|noconskey|nocopyindent|nocp|nocscopetag|nocscopeverbose|nocst|nocsverb|nocuc|nocul|nocursorcolumn|nocursorline|nodeco|nodelcombine|nodg|nodiff|nodigraph|nodisable|noea|noeb|noed|noedcompatible|noek|noendofline|noeol|noequalalways|noerrorbells|noesckeys|noet|noex|noexpandtab|noexrc|nofen|nofk|nofkmap|nofoldenable|nogd|nogdefault|noguipty|nohid|nohidden|nohk|nohkmap|nohkmapp|nohkp|nohls|noic|noicon|noignorecase|noim|noimc|noimcmdline|noimd|noincsearch|noinf|noinfercase|noinsertmode|nois|nojoinspaces|nojs|nolazyredraw|nolbr|nolinebreak|nolisp|nolist|noloadplugins|nolpl|nolz|noma|nomacatsui|nomagic|nomh|noml|nomod|nomodeline|nomodifiable|nomodified|nomore|nomousef|nomousefocus|nomousehide|nonu|nonumber|noodev|noopendevice|nopaste|nopi|nopreserveindent|nopreviewwindow|noprompt|nopvw|noreadonly|noremap|norestorescreen|norevins|nori|norightleft|norightleftcmd|norl|norlc|noro|nors|noru|noruler|nosb|nosc|noscb|noscrollbind|noscs|nosecure|nosft|noshellslash|noshelltemp|noshiftround|noshortname|noshowcmd|noshowfulltag|noshowmatch|noshowmode|nosi|nosm|nosmartcase|nosmartindent|nosmarttab|nosmd|nosn|nosol|nospell|nosplitbelow|nosplitright|nospr|nosr|nossl|nosta|nostartofline|nostmp|noswapfile|noswf|nota|notagbsearch|notagrelative|notagstack|notbi|notbidi|notbs|notermbidi|noterse|notextauto|notextmode|notf|notgst|notildeop|notimeout|notitle|noto|notop|notr|nottimeout|nottybuiltin|nottyfast|notx|novb|novisualbell|nowa|nowarn|nowb|noweirdinvert|nowfh|nowfw|nowildmenu|nowinfixheight|nowinfixwidth|nowiv|nowmnu|nowrap|nowrapscan|nowrite|nowriteany|nowritebackup|nows|invacd|invai|invakm|invallowrevins|invaltkeymap|invanti|invantialias|invar|invarab|invarabic|invarabicshape|invari|invarshape|invautochdir|invautoindent|invautoread|invautowrite|invautowriteall|invaw|invawa|invbackup|invballooneval|invbeval|invbin|invbinary|invbiosk|invbioskey|invbk|invbl|invbomb|invbuflisted|invcf|invci|invcin|invcindent|invcompatible|invconfirm|invconsk|invconskey|invcopyindent|invcp|invcscopetag|invcscopeverbose|invcst|invcsverb|invcuc|invcul|invcursorcolumn|invcursorline|invdeco|invdelcombine|invdg|invdiff|invdigraph|invdisable|invea|inveb|inved|invedcompatible|invek|invendofline|inveol|invequalalways|inverrorbells|invesckeys|invet|invex|invexpandtab|invexrc|invfen|invfk|invfkmap|invfoldenable|invgd|invgdefault|invguipty|invhid|invhidden|invhk|invhkmap|invhkmapp|invhkp|invhls|invhlsearch|invic|invicon|invignorecase|invim|invimc|invimcmdline|invimd|invincsearch|invinf|invinfercase|invinsertmode|invis|invjoinspaces|invjs|invlazyredraw|invlbr|invlinebreak|invlisp|invlist|invloadplugins|invlpl|invlz|invma|invmacatsui|invmagic|invmh|invml|invmod|invmodeline|invmodifiable|invmodified|invmore|invmousef|invmousefocus|invmousehide|invnu|invnumber|invodev|invopendevice|invpaste|invpi|invpreserveindent|invpreviewwindow|invprompt|invpvw|invreadonly|invremap|invrestorescreen|invrevins|invri|invrightleft|invrightleftcmd|invrl|invrlc|invro|invrs|invru|invruler|invsb|invsc|invscb|invscrollbind|invscs|invsecure|invsft|invshellslash|invshelltemp|invshiftround|invshortname|invshowcmd|invshowfulltag|invshowmatch|invshowmode|invsi|invsm|invsmartcase|invsmartindent|invsmarttab|invsmd|invsn|invsol|invspell|invsplitbelow|invsplitright|invspr|invsr|invssl|invsta|invstartofline|invstmp|invswapfile|invswf|invta|invtagbsearch|invtagrelative|invtagstack|invtbi|invtbidi|invtbs|invtermbidi|invterse|invtextauto|invtextmode|invtf|invtgst|invtildeop|invtimeout|invtitle|invto|invtop|invtr|invttimeout|invttybuiltin|invttyfast|invtx|invvb|invvisualbell|invwa|invwarn|invwb|invweirdinvert|invwfh|invwfw|invwildmenu|invwinfixheight|invwinfixwidth|invwiv|invwmnu|invwrap|invwrapscan|invwrite|invwriteany|invwritebackup|invws|t_AB|t_AF|t_al|t_AL|t_bc|t_cd|t_ce|t_Ce|t_cl|t_cm|t_Co|t_cs|t_Cs|t_CS|t_CV|t_da|t_db|t_dl|t_DL|t_EI|t_F1|t_F2|t_F3|t_F4|t_F5|t_F6|t_F7|t_F8|t_F9|t_fs|t_IE|t_IS|t_k1|t_K1|t_k2|t_k3|t_K3|t_k4|t_K4|t_k5|t_K5|t_k6|t_K6|t_k7|t_K7|t_k8|t_K8|t_k9|t_K9|t_KA|t_kb|t_kB|t_KB|t_KC|t_kd|t_kD|t_KD|t_ke|t_KE|t_KF|t_KG|t_kh|t_KH|t_kI|t_KI|t_KJ|t_KK|t_kl|t_KL|t_kN|t_kP|t_kr|t_ks|t_ku|t_le|t_mb|t_md|t_me|t_mr|t_ms|t_nd|t_op|t_RI|t_RV|t_Sb|t_se|t_Sf|t_SI|t_so|t_sr|t_te|t_ti|t_ts|t_ue|t_us|t_ut|t_vb|t_ve|t_vi|t_vs|t_WP|t_WS|t_xs|t_ZH|t_ZR)\b/,number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?)\b/i,operator:/\|\||&&|[-+.]=?|[=!](?:[=~][#?]?)?|[<>]=?[#?]?|[*\/%?]|\b(?:is(?:not)?)\b/,punctuation:/[{}[\](),;:]/}; Prism.languages["visual-basic"]={comment:{pattern:/(?:['‘’]|REM\b)(?:[^\r\n_]|_(?:\r\n?|\n)?)*/i,inside:{keyword:/^REM/i}},directive:{pattern:/#(?:Const|Else|ElseIf|End|ExternalChecksum|ExternalSource|If|Region)(?:[^\S\r\n]_[^\S\r\n]*(?:\r\n?|\n)|.)+/i,alias:"comment",greedy:!0},string:{pattern:/\$?["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,greedy:!0},date:{pattern:/#[^\S\r\n]*(?:\d+([/-])\d+\1\d+(?:[^\S\r\n]+(?:\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?))?|\d+[^\S\r\n]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[^\S\r\n]*(?:AM|PM))?)[^\S\r\n]*#/i,alias:"builtin"},number:/(?:(?:\b\d+(?:\.\d+)?|\.\d+)(?:E[+-]?\d+)?|&[HO][\dA-F]+)(?:U?[ILS]|[FRD])?/i,boolean:/\b(?:True|False|Nothing)\b/i,keyword:/\b(?:AddHandler|AddressOf|Alias|And(?:Also)?|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|C(?:Bool|Byte|Char|Date|Dbl|Dec|Int|Lng|Obj|SByte|Short|Sng|Str|Type|UInt|ULng|UShort)|Char|Class|Const|Continue|Currency|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else(?:If)?|End(?:If)?|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get(?:Type|XMLNamespace)?|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|Must(?:Inherit|Override)|My(?:Base|Class)|Namespace|Narrowing|New|Next|Not(?:Inheritable|Overridable)?|Object|Of|On|Operator|Option(?:al)?|Or(?:Else)?|Out|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TryCast|Type|TypeOf|U(?:Integer|Long|Short)|Using|Variant|Wend|When|While|Widening|With(?:Events)?|WriteOnly|Until|Xor)\b/i,operator:[/[+\-*/\\^<=>&#@$%!]/,{pattern:/([^\S\r\n])_(?=[^\S\r\n]*[\r\n])/,lookbehind:!0}],punctuation:/[{}().,:?]/},Prism.languages.vb=Prism.languages["visual-basic"],Prism.languages.vba=Prism.languages["visual-basic"]; Prism.languages.warpscript={comment:/#.*|\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'|<'(?:[^\\']|'(?!>)|\\.)*'>/,greedy:!0},variable:/\$\S+/,macro:{pattern:/@\S+/,alias:"property"},keyword:/\b(?:BREAK|CHECKMACRO|CONTINUE|CUDF|DEFINED|DEFINEDMACRO|EVAL|FAIL|FOR|FOREACH|FORSTEP|IFT|IFTE|MSGFAIL|NRETURN|RETHROW|RETURN|SWITCH|TRY|UDF|UNTIL|WHILE)\b/,number:/[+-]?\b(?:NaN|Infinity|\d+(?:\.\d*)?(?:[Ee][+-]?\d+)?|0x[\da-fA-F]+|0b[01]+)\b/,boolean:/\b(?:false|true|F|T)\b/,punctuation:/<%|%>|[{}[\]()]/,operator:/==|&&?|\|\|?|\*\*?|>>>?|<<|[<>!~]=?|[-/%^]|\+!?|\b(?:AND|NOT|OR)\b/}; Prism.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|nearest|neg?|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|store(?:8|16|32)?|sqrt|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/i,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/}; Prism.languages.wiki=Prism.languages.extend("markup",{"block-comment":{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,alias:"comment"},heading:{pattern:/^(=+)[^=\r\n].*?\1/m,inside:{punctuation:/^=+|=+$/,important:/.+/}},emphasis:{pattern:/('{2,5}).+?\1/,inside:{"bold-italic":{pattern:/(''''').+?(?=\1)/,lookbehind:!0,alias:["bold","italic"]},bold:{pattern:/(''')[^'](?:.*?[^'])?(?=\1)/,lookbehind:!0},italic:{pattern:/('')[^'](?:.*?[^'])?(?=\1)/,lookbehind:!0},punctuation:/^''+|''+$/}},hr:{pattern:/^-{4,}/m,alias:"punctuation"},url:[/ISBN +(?:97[89][ -]?)?(?:\d[ -]?){9}[\dx]\b|(?:RFC|PMID) +\d+/i,/\[\[.+?\]\]|\[.+?\]/],variable:[/__[A-Z]+__/,/\{{3}.+?\}{3}/,/\{\{.+?\}\}/],symbol:[/^#redirect/im,/~{3,5}/],"table-tag":{pattern:/((?:^|[|!])[|!])[^|\r\n]+\|(?!\|)/m,lookbehind:!0,inside:{"table-bar":{pattern:/\|$/,alias:"punctuation"},rest:Prism.languages.markup.tag.inside}},punctuation:/^(?:\{\||\|\}|\|-|[*#:;!|])|\|\||!!/m}),Prism.languages.insertBefore("wiki","tag",{nowiki:{pattern:/<(nowiki|pre|source)\b[^>]*>[\s\S]*?<\/\1>/i,inside:{tag:{pattern:/<(?:nowiki|pre|source)\b[^>]*>|<\/(?:nowiki|pre|source)>/i,inside:Prism.languages.markup.tag.inside}}}}); Prism.languages.wolfram={comment:/\(\*(?:\(\*(?:[^*]|\*(?!\)))*\*\)|(?!\(\*)[\s\S])*?\*\)/,string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:Abs|AbsArg|Accuracy|Block|Do|For|Function|If|Manipulate|Module|Nest|NestList|None|Return|Switch|Table|Which|While)\b/,context:{pattern:/\w+`+\w*/,alias:"class-name"},blank:{pattern:/\b\w+_\b/,alias:"regex"},"global-variable":{pattern:/\$\w+/,alias:"variable"},boolean:/\b(?:True|False)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/\/\.|;|=\.|\^=|\^:=|:=|<<|>>|<\||\|>|:>|\|->|->|<-|@@@|@@|@|\/@|=!=|===|==|=|\+|-|\^|\[\/-+%=\]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[\|{}[\];(),.:]/},Prism.languages.mathematica=Prism.languages.wolfram,Prism.languages.wl=Prism.languages.wolfram,Prism.languages.nb=Prism.languages.wolfram; !function(n){n.languages.xeora=n.languages.extend("markup",{constant:{pattern:/\$(?:DomainContents|PageRenderDuration)\$/,inside:{punctuation:{pattern:/\$/}}},variable:{pattern:/\$@?(?:#+|[-+*~=^])?[\w.]+\$/,inside:{punctuation:{pattern:/[$.]/},operator:{pattern:/#+|[-+*~=^@]/}}},"function-inline":{pattern:/\$F:[-\w.]+\?[-\w.]+(?:,(?:(?:@[-#]*\w+\.[\w+.]\.*)*\|)*(?:(?:[\w+]|[-#*.~^]+[\w+]|=\S)(?:[^$=]|=+[^=])*=*|(?:@[-#]*\w+\.[\w+.]\.*)+(?:(?:[\w+]|[-#*~^][-#*.~^]*[\w+]|=\S)(?:[^$=]|=+[^=])*=*)?)?)?\$/,inside:{variable:{pattern:/(?:[,|])@?(?:#+|[-+*~=^])?[\w.]+/,inside:{punctuation:{pattern:/[,.|]/},operator:{pattern:/#+|[-+*~=^@]/}}},punctuation:{pattern:/\$\w:|[$:?.,|]/}},alias:"function"},"function-block":{pattern:/\$XF:\{[-\w.]+\?[-\w.]+(?:,(?:(?:@[-#]*\w+\.[\w+.]\.*)*\|)*(?:(?:[\w+]|[-#*.~^]+[\w+]|=\S)(?:[^$=]|=+[^=])*=*|(?:@[-#]*\w+\.[\w+.]\.*)+(?:(?:[\w+]|[-#*~^][-#*.~^]*[\w+]|=\S)(?:[^$=]|=+[^=])*=*)?)?)?\}:XF\$/,inside:{punctuation:{pattern:/[$:{}?.,|]/}},alias:"function"},"directive-inline":{pattern:/\$\w(?:#\d+\+?)?(?:\[[-\w.]+\])?:[-\/\w.]+\$/,inside:{punctuation:{pattern:/\$(?:\w:|C(?:\[|#\d))?|[:{[\]]/,inside:{tag:{pattern:/#\d/}}}},alias:"function"},"directive-block-open":{pattern:/\$\w+:\{|\$\w(?:#\d+\+?)?(?:\[[-\w.]+\])?:[-\w.]+:\{(?:![A-Z]+)?/,inside:{punctuation:{pattern:/\$(?:\w:|C(?:\[|#\d))?|[:{[\]]/,inside:{tag:{pattern:/#\d/}}},attribute:{pattern:/![A-Z]+$/,inside:{punctuation:{pattern:/!/}},alias:"keyword"}},alias:"function"},"directive-block-separator":{pattern:/\}:[-\w.]+:\{/,inside:{punctuation:{pattern:/[:{}]/}},alias:"function"},"directive-block-close":{pattern:/\}:[-\w.]+\$/,inside:{punctuation:{pattern:/[:{}$]/}},alias:"function"}}),n.languages.insertBefore("inside","punctuation",{variable:n.languages.xeora["function-inline"].inside.variable},n.languages.xeora["function-block"]),n.languages.xeoracube=n.languages.xeora}(Prism); !function(n){function a(a,e){n.languages[a]&&n.languages.insertBefore(a,"comment",{"doc-comment":e})}var e=n.languages.markup.tag,t={pattern:/\/\/\/.*/,greedy:!0,alias:"comment",inside:{tag:e}},g={pattern:/'''.*/,greedy:!0,alias:"comment",inside:{tag:e}};a("csharp",t),a("fsharp",t),a("vbnet",g)}(Prism); Prism.languages.xojo={comment:{pattern:/(?:'|\/\/|Rem\b).+/i},string:{pattern:/"(?:""|[^"])*"/,greedy:!0},number:[/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,/&[bchou][a-z\d]+/i],symbol:/#(?:If|Else|ElseIf|Endif|Pragma)\b/i,keyword:/\b(?:AddHandler|App|Array|As(?:signs)?|Auto|By(?:Ref|Val)|Boolean|Break|Byte|Call|Case|Catch|CFStringRef|CGFloat|Class|Color|Const|Continue|CString|Currency|CurrentMethodName|Declare|Delegate|Dim|Do(?:uble|wnTo)?|Each|Else(?:If)?|End|Enumeration|Event|Exception|Exit|Extends|False|Finally|For|Function|Get|GetTypeInfo|Global|GOTO|If|Implements|In|Inherits|Int(?:erface|eger|8|16|32|64)?|Lib|Loop|Me|Module|Next|Nil|Object|Optional|OSType|ParamArray|Private|Property|Protected|PString|Ptr|Raise(?:Event)?|ReDim|RemoveHandler|Return|Select(?:or)?|Self|Set|Single|Shared|Short|Soft|Static|Step|String|Sub|Super|Text|Then|To|True|Try|Ubound|UInt(?:eger|8|16|32|64)?|Until|Using|Var(?:iant)?|Wend|While|WindowPtr|WString)\b/i,operator:/<[=>]?|>=?|[+\-*\/\\^=]|\b(?:AddressOf|And|Ctype|IsA?|Mod|New|Not|Or|Xor|WeakAddressOf)\b/i,punctuation:/[.,;:()]/}; !function(r){r.languages.xquery=r.languages.extend("markup",{"xquery-comment":{pattern:/\(:[\s\S]*?:\)/,greedy:!0,alias:"comment"},string:{pattern:/(["'])(?:\1\1|(?!\1)[\s\S])*\1/,greedy:!0},extension:{pattern:/\(#.+?#\)/,alias:"symbol"},variable:/\$[-\w:]+/,axis:{pattern:/(^|[^-])(?:ancestor(?:-or-self)?|attribute|child|descendant(?:-or-self)?|following(?:-sibling)?|parent|preceding(?:-sibling)?|self)(?=::)/,lookbehind:!0,alias:"operator"},"keyword-operator":{pattern:/(^|[^:-])\b(?:and|castable as|div|eq|except|ge|gt|idiv|instance of|intersect|is|le|lt|mod|ne|or|union)\b(?=$|[^:-])/,lookbehind:!0,alias:"operator"},keyword:{pattern:/(^|[^:-])\b(?:as|ascending|at|base-uri|boundary-space|case|cast as|collation|construction|copy-namespaces|declare|default|descending|else|empty (?:greatest|least)|encoding|every|external|for|function|if|import|in|inherit|lax|let|map|module|namespace|no-inherit|no-preserve|option|order(?: by|ed|ing)?|preserve|return|satisfies|schema|some|stable|strict|strip|then|to|treat as|typeswitch|unordered|validate|variable|version|where|xquery)\b(?=$|[^:-])/,lookbehind:!0},function:/[\w-]+(?::[\w-]+)*(?=\s*\()/,"xquery-element":{pattern:/(element\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"tag"},"xquery-attribute":{pattern:/(attribute\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"attr-name"},builtin:{pattern:/(^|[^:-])\b(?:attribute|comment|document|element|processing-instruction|text|xs:(?:anyAtomicType|anyType|anyURI|base64Binary|boolean|byte|date|dateTime|dayTimeDuration|decimal|double|duration|ENTITIES|ENTITY|float|gDay|gMonth|gMonthDay|gYear|gYearMonth|hexBinary|ID|IDREFS?|int|integer|language|long|Name|NCName|negativeInteger|NMTOKENS?|nonNegativeInteger|nonPositiveInteger|normalizedString|NOTATION|positiveInteger|QName|short|string|time|token|unsigned(?:Byte|Int|Long|Short)|untyped(?:Atomic)?|yearMonthDuration))\b(?=$|[^:-])/,lookbehind:!0},number:/\b\d+(?:\.\d+)?(?:E[+-]?\d+)?/,operator:[/[+*=?|@]|\.\.?|:=|!=|<[=<]?|>[=>]?/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}],punctuation:/[[\](){},;:/]/}),r.languages.xquery.tag.pattern=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,r.languages.xquery.tag.inside["attr-value"].pattern=/=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+)/i,r.languages.xquery.tag.inside["attr-value"].inside.punctuation=/^="|"$/,r.languages.xquery.tag.inside["attr-value"].inside.expression={pattern:/\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}/,inside:r.languages.xquery,alias:"language-xquery"};var s=function(e){return"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(s).join("")},l=function(e){for(var t=[],n=0;n"===a.content[a.content.length-1].content||t.push({tagName:s(a.content[0].content[1]),openedBraces:0}):!(0|(?:\\[[^[\\]]*\\]|\\*(?!\\*)|\\*\\*)(?:\\s*|\\s*const\\b|\\s*volatile\\b|\\s*allowzero\\b)*)".replace(//g,e(o))+"\\s*)*"+"(?:\\bpromise\\b|(?:\\berror\\.)?(?:\\.)*(?!\\s+))".replace(//g,e(a))+")+";n.languages.zig={comment:[{pattern:/\/{3}.*/,alias:"doc-comment"},/\/{2}.*/],string:[{pattern:/(^|[^\\@])c?"(?:[^"\\\r\n]|\\.)*"/,lookbehind:!0,greedy:!0},{pattern:/([\r\n])([ \t]+c?\\{2}).*(?:(?:\r\n?|\n)\2.*)*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\])'(?:[^'\\\r\n]|\\(?:.|x[a-fA-F\d]{2}|u\{[a-fA-F\d]{1,6}\}))'/,lookbehind:!0,greedy:!0}],builtin:/\B@(?!\d)\w+(?=\s*\()/,label:{pattern:/(\b(?:break|continue)\s*:\s*)\w+\b|\b(?!\d)\w+\b(?=\s*:\s*(?:\{|while\b))/,lookbehind:!0},"class-name":[/\b(?!\d)\w+(?=\s*=\s*(?:(?:extern|packed)\s+)?(?:enum|struct|union)\s*[({])/,{pattern:RegExp("(:\\s*)(?=\\s*(?:\\s*)?[=;,)])|(?=\\s*(?:\\s*)?\\{)".replace(//g,e(s)).replace(//g,e(o))),lookbehind:!0,inside:null},{pattern:RegExp("(\\)\\s*)(?=\\s*(?:\\s*)?;)".replace(//g,e(s)).replace(//g,e(o))),lookbehind:!0,inside:null}],"builtin-types":{pattern:/\b(?:anyerror|bool|c_u?(?:short|int|long|longlong)|c_longdouble|c_void|comptime_(?:float|int)|[iu](?:8|16|32|64|128|size)|f(?:16|32|64|128)|noreturn|type|void)\b/,alias:"keyword"},keyword:r,function:/\b(?!\d)\w+(?=\s*\()/,number:/\b(?:0b[01]+|0o[0-7]+|0x[a-fA-F\d]+(?:\.[a-fA-F\d]*)?(?:[pP][+-]?[a-fA-F\d]+)?|\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)\b/,boolean:/\b(?:false|true)\b/,operator:/\.[*?]|\.{2,3}|[-=]>|\*\*|\+\+|\|\||(?:<<|>>|[-+*]%|[-+*/%^&|<>!=])=?|[?~]/,punctuation:/[.:,;(){}[\]]/},n.languages.zig["class-name"].forEach(function(e){null===e.inside&&(e.inside=n.languages.zig)})}(Prism); !function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows");if(t){var i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null}(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1 /}}}}},Prism.hooks.add("wrap",function(e){if("treeview"===e.language&&"entry-name"===e.type){var t=e.classes,n=/(^|[^\\])\/\s*$/;if(n.test(e.content))e.content=e.content.replace(n,"$1"),t.push("dir");else{e.content=e.content.replace(/(^|[^\\])[=*|]\s*$/,"$1");for(var a=e.content.toLowerCase().replace(/\s+/g,"").split(".");1 { if (event.data.hash && event.data.hash == 'sha1') { const localFilePath = event.data.localFilePath const access_token = event.data.access_token fileSha1(localFilePath, access_token).catch((e) => { worker.postMessage({ hash: 'sha1', sha1: 'error', proof_code: '', error: FileSystemErrorMessage(e.code, e.message) }) running = false }) } if (event.data.stop) { running = false } if (event.data.close) { close() } }) worker.addEventListener('error', (e) => { worker.postMessage({ hash: 'sha1', sha1: 'error', proof_code: '', error: FileSystemErrorMessage(e.code, e.message) }) running = false }) async function fileSha1(localFilePath, access_token) { running = true let hash = '' var sha1 = crypto.createHash('sha1') const fileHandle = await fspromises.open(localFilePath, 'r') try { if (fileHandle) { const stat = await fileHandle.stat() const size = stat.size const buff = Buffer.alloc(4 * 1024 * 1024) let readlen = 0 let timer = setInterval(function () { const message = '计算sha1(' + Math.floor((readlen * 100) / size).toString() + '%)' worker.postMessage({ hash: 'sha1', readlen, size, message }) }, 300) while (true) { if (!running) break const len = await fileHandle.read(buff, 0, buff.length, null) if (len.bytesRead > 0 && len.bytesRead == buff.length) { sha1.update(buff) } else if (len.bytesRead > 0) { sha1.update(buff.slice(0, len.bytesRead)) } readlen += len.bytesRead if (len.bytesRead <= 0) break } clearInterval(timer) let proof_code = '' if (running) { hash = sha1.digest('hex') hash = hash.toUpperCase() const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(size)) const end = Math.min(start + 8, size) const buffb = Buffer.alloc(end - start) await fileHandle.read(buffb, 0, buffb.length, start) proof_code = buffb.toString('base64') } else { hash = 'error' proof_code = '' /** 这里无所谓了,外部会error='' */ } worker.postMessage({ hash: 'sha1', sha1: hash, proof_code, error: '' }) running = false } else { worker.postMessage({ hash: 'sha1', sha1: 'error', proof_code: '', error: '打开文件失败' }) running = false } } catch {} try { await fileHandle?.close() } catch {} } function FileSystemErrorMessage(code, message) { if (!code && !message) return '读取文件失败' if (code) { switch (code) { case 'EACCES': return '没有权限访问' case 'EEXIST': return '存在重名文件' case 'EISDIR': return '不能是文件夹' case 'EMFILE': return '同时打开文件过多' case 'ENFILE': return '同时打开文件过多' case 'ENOENT': return '该路径不存在' case 'ENOTDIR': return '不能是文件' case 'ENOTEMPTY': return '文件夹不为空' case 'EPERM': return '没有权限访问' case 'EBUSY': return '文件被其他程序占用' case 'ETIMEDOUT': return '操作超时' case 'EDQUOT': return '超出磁盘配额' case 'EFBIG': return '文件太大' case 'EIDRM': return '文件已被删除' case 'EIO': return 'IO错误' case 'ELOOP': return '路径级别过多' case 'ENAMETOOLONG': return '文件名太长' case 'ENODEV': return '找不到设备' case 'ENOMEM': return '没有足够的空间' case 'ENOSPC': return '没有可用空间' case 'EROFS': return '只读文件' } } if (message && typeof message == 'string' && message.indexOf('EACCES') >= 0) return '没有权限访问' let err = (code || '') + (message || '') if (err) return err return '读取文件失败' } ================================================ FILE: public/silvermine-videojs-quality-selector.css ================================================ .vjs-quality-selector .vjs-menu-button { margin: 0; padding: 0; height: 100%; width: 100%; } .vjs-quality-selector .vjs-icon-placeholder { font-family: 'VideoJS'; font-weight: normal; font-style: normal; } .vjs-quality-selector .vjs-icon-placeholder::before { content: '\f110'; } .vjs-quality-changing .vjs-big-play-button { display: none; } .vjs-quality-changing .vjs-control-bar { display: -webkit-box; display: -webkit-flex; display: flex; visibility: visible; opacity: 1; } .vjs-quality-selector .vjs-menu{ width: 6em; left: -1em; } ================================================ FILE: public/wasm_exec.js ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // // This file has been modified for use by the TinyGo compiler. (() => { // Map multiple JavaScript environments to a single common API, // preferring web standards over Node.js API. // // Environments considered: // - Browsers // - Node.js // - Electron // - Parcel if (typeof global !== "undefined") { // global already exists } else if (typeof window !== "undefined") { window.global = window; } else if (typeof self !== "undefined") { self.global = self; } else { throw new Error("cannot export Go (neither global, window nor self is defined)"); } if (!global.require && typeof require !== "undefined") { global.require = require; } if (!global.fs && global.require) { global.fs = require("fs"); } const enosys = () => { const err = new Error("not implemented"); err.code = "ENOSYS"; return err; }; if (!global.fs) { let outputBuf = ""; global.fs = { constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused writeSync(fd, buf) { outputBuf += decoder.decode(buf); const nl = outputBuf.lastIndexOf("\n"); if (nl != -1) { console.log(outputBuf.substr(0, nl)); outputBuf = outputBuf.substr(nl + 1); } return buf.length; }, write(fd, buf, offset, length, position, callback) { if (offset !== 0 || length !== buf.length || position !== null) { callback(enosys()); return; } const n = this.writeSync(fd, buf); callback(null, n); }, chmod(path, mode, callback) { callback(enosys()); }, chown(path, uid, gid, callback) { callback(enosys()); }, close(fd, callback) { callback(enosys()); }, fchmod(fd, mode, callback) { callback(enosys()); }, fchown(fd, uid, gid, callback) { callback(enosys()); }, fstat(fd, callback) { callback(enosys()); }, fsync(fd, callback) { callback(null); }, ftruncate(fd, length, callback) { callback(enosys()); }, lchown(path, uid, gid, callback) { callback(enosys()); }, link(path, link, callback) { callback(enosys()); }, lstat(path, callback) { callback(enosys()); }, mkdir(path, perm, callback) { callback(enosys()); }, open(path, flags, mode, callback) { callback(enosys()); }, read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, readdir(path, callback) { callback(enosys()); }, readlink(path, callback) { callback(enosys()); }, rename(from, to, callback) { callback(enosys()); }, rmdir(path, callback) { callback(enosys()); }, stat(path, callback) { callback(enosys()); }, symlink(path, link, callback) { callback(enosys()); }, truncate(path, length, callback) { callback(enosys()); }, unlink(path, callback) { callback(enosys()); }, utimes(path, atime, mtime, callback) { callback(enosys()); }, }; } if (!global.process) { global.process = { getuid() { return -1; }, getgid() { return -1; }, geteuid() { return -1; }, getegid() { return -1; }, getgroups() { throw enosys(); }, pid: -1, ppid: -1, umask() { throw enosys(); }, cwd() { throw enosys(); }, chdir() { throw enosys(); }, } } if (!global.crypto) { const nodeCrypto = require("crypto"); global.crypto = { getRandomValues(b) { nodeCrypto.randomFillSync(b); }, }; } if (!global.performance) { global.performance = { now() { const [sec, nsec] = process.hrtime(); return sec * 1000 + nsec / 1000000; }, }; } if (!global.TextEncoder) { global.TextEncoder = require("util").TextEncoder; } if (!global.TextDecoder) { global.TextDecoder = require("util").TextDecoder; } // End of polyfills for common API. const encoder = new TextEncoder("utf-8"); const decoder = new TextDecoder("utf-8"); var logLine = []; global.Go = class { constructor() { this._callbackTimeouts = new Map(); this._nextCallbackTimeoutID = 1; const mem = () => { // The buffer may change when requesting more memory. return new DataView(this._inst.exports.memory.buffer); } const setInt64 = (addr, v) => { mem().setUint32(addr + 0, v, true); mem().setUint32(addr + 4, Math.floor(v / 4294967296), true); } const getInt64 = (addr) => { const low = mem().getUint32(addr + 0, true); const high = mem().getInt32(addr + 4, true); return low + high * 4294967296; } const loadValue = (addr) => { const f = mem().getFloat64(addr, true); if (f === 0) { return undefined; } if (!isNaN(f)) { return f; } const id = mem().getUint32(addr, true); return this._values[id]; } const storeValue = (addr, v) => { const nanHead = 0x7FF80000; if (typeof v === "number") { if (isNaN(v)) { mem().setUint32(addr + 4, nanHead, true); mem().setUint32(addr, 0, true); return; } if (v === 0) { mem().setUint32(addr + 4, nanHead, true); mem().setUint32(addr, 1, true); return; } mem().setFloat64(addr, v, true); return; } switch (v) { case undefined: mem().setFloat64(addr, 0, true); return; case null: mem().setUint32(addr + 4, nanHead, true); mem().setUint32(addr, 2, true); return; case true: mem().setUint32(addr + 4, nanHead, true); mem().setUint32(addr, 3, true); return; case false: mem().setUint32(addr + 4, nanHead, true); mem().setUint32(addr, 4, true); return; } let id = this._ids.get(v); if (id === undefined) { id = this._idPool.pop(); if (id === undefined) { id = this._values.length; } this._values[id] = v; this._goRefCounts[id] = 0; this._ids.set(v, id); } this._goRefCounts[id]++; let typeFlag = 1; switch (typeof v) { case "string": typeFlag = 2; break; case "symbol": typeFlag = 3; break; case "function": typeFlag = 4; break; } mem().setUint32(addr + 4, nanHead | typeFlag, true); mem().setUint32(addr, id, true); } const loadSlice = (array, len, cap) => { return new Uint8Array(this._inst.exports.memory.buffer, array, len); } const loadSliceOfValues = (array, len, cap) => { const a = new Array(len); for (let i = 0; i < len; i++) { a[i] = loadValue(array + i * 8); } return a; } const loadString = (ptr, len) => { return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len)); } const timeOrigin = Date.now() - performance.now(); this.importObject = { wasi_snapshot_preview1: { // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) { let nwritten = 0; if (fd == 1) { for (let iovs_i=0; iovs_i { if (global.process) { // Node.js process.exit(code); } else { // Can't exit in a browser. throw 'trying to exit with code ' + code; } }, }, env: { // func ticks() float64 "runtime.ticks": () => { return timeOrigin + performance.now(); }, // func sleepTicks(timeout float64) "runtime.sleepTicks": (timeout) => { // Do not sleep, only reactivate scheduler after the given timeout. setTimeout(this._inst.exports.go_scheduler, timeout); }, // func finalizeRef(v ref) "syscall/js.finalizeRef": (sp) => { // Note: TinyGo does not support finalizers so this should never be // called. //console.error('syscall/js.finalizeRef not implemented'); }, // func stringVal(value string) ref "syscall/js.stringVal": (ret_ptr, value_ptr, value_len) => { const s = loadString(value_ptr, value_len); storeValue(ret_ptr, s); }, // func valueGet(v ref, p string) ref "syscall/js.valueGet": (retval, v_addr, p_ptr, p_len) => { let prop = loadString(p_ptr, p_len); let value = loadValue(v_addr); let result = Reflect.get(value, prop); storeValue(retval, result); }, // func valueSet(v ref, p string, x ref) "syscall/js.valueSet": (v_addr, p_ptr, p_len, x_addr) => { const v = loadValue(v_addr); const p = loadString(p_ptr, p_len); const x = loadValue(x_addr); Reflect.set(v, p, x); }, // func valueDelete(v ref, p string) "syscall/js.valueDelete": (v_addr, p_ptr, p_len) => { const v = loadValue(v_addr); const p = loadString(p_ptr, p_len); Reflect.deleteProperty(v, p); }, // func valueIndex(v ref, i int) ref "syscall/js.valueIndex": (ret_addr, v_addr, i) => { storeValue(ret_addr, Reflect.get(loadValue(v_addr), i)); }, // valueSetIndex(v ref, i int, x ref) "syscall/js.valueSetIndex": (v_addr, i, x_addr) => { Reflect.set(loadValue(v_addr), i, loadValue(x_addr)); }, // func valueCall(v ref, m string, args []ref) (ref, bool) "syscall/js.valueCall": (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => { const v = loadValue(v_addr); const name = loadString(m_ptr, m_len); const args = loadSliceOfValues(args_ptr, args_len, args_cap); try { const m = Reflect.get(v, name); storeValue(ret_addr, Reflect.apply(m, v, args)); mem().setUint8(ret_addr + 8, 1); } catch (err) { storeValue(ret_addr, err); mem().setUint8(ret_addr + 8, 0); } }, // func valueInvoke(v ref, args []ref) (ref, bool) "syscall/js.valueInvoke": (ret_addr, v_addr, args_ptr, args_len, args_cap) => { try { const v = loadValue(v_addr); const args = loadSliceOfValues(args_ptr, args_len, args_cap); storeValue(ret_addr, Reflect.apply(v, undefined, args)); mem().setUint8(ret_addr + 8, 1); } catch (err) { storeValue(ret_addr, err); mem().setUint8(ret_addr + 8, 0); } }, // func valueNew(v ref, args []ref) (ref, bool) "syscall/js.valueNew": (ret_addr, v_addr, args_ptr, args_len, args_cap) => { const v = loadValue(v_addr); const args = loadSliceOfValues(args_ptr, args_len, args_cap); try { storeValue(ret_addr, Reflect.construct(v, args)); mem().setUint8(ret_addr + 8, 1); } catch (err) { storeValue(ret_addr, err); mem().setUint8(ret_addr+ 8, 0); } }, // func valueLength(v ref) int "syscall/js.valueLength": (v_addr) => { return loadValue(v_addr).length; }, // valuePrepareString(v ref) (ref, int) "syscall/js.valuePrepareString": (ret_addr, v_addr) => { const s = String(loadValue(v_addr)); const str = encoder.encode(s); storeValue(ret_addr, str); setInt64(ret_addr + 8, str.length); }, // valueLoadString(v ref, b []byte) "syscall/js.valueLoadString": (v_addr, slice_ptr, slice_len, slice_cap) => { const str = loadValue(v_addr); loadSlice(slice_ptr, slice_len, slice_cap).set(str); }, // func valueInstanceOf(v ref, t ref) bool "syscall/js.valueInstanceOf": (v_addr, t_addr) => { return loadValue(v_addr) instanceof loadValue(t_addr); }, // func copyBytesToGo(dst []byte, src ref) (int, bool) "syscall/js.copyBytesToGo": (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => { let num_bytes_copied_addr = ret_addr; let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable const dst = loadSlice(dest_addr, dest_len); const src = loadValue(source_addr); if (!(src instanceof Uint8Array)) { mem().setUint8(returned_status_addr, 0); // Return "not ok" status return; } const toCopy = src.subarray(0, dst.length); dst.set(toCopy); setInt64(num_bytes_copied_addr, toCopy.length); mem().setUint8(returned_status_addr, 1); // Return "ok" status }, // copyBytesToJS(dst ref, src []byte) (int, bool) // Originally copied from upstream Go project, then modified: // https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416 "syscall/js.copyBytesToJS": (ret_addr, dest_addr, source_addr, source_len, source_cap) => { let num_bytes_copied_addr = ret_addr; let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable const dst = loadValue(dest_addr); const src = loadSlice(source_addr, source_len); if (!(dst instanceof Uint8Array)) { mem().setUint8(returned_status_addr, 0); // Return "not ok" status return; } const toCopy = src.subarray(0, dst.length); dst.set(toCopy); setInt64(num_bytes_copied_addr, toCopy.length); mem().setUint8(returned_status_addr, 1); // Return "ok" status }, } }; } async run(instance) { this._inst = instance; this._values = [ // JS values that Go currently has references to, indexed by reference id NaN, 0, null, true, false, global, this, ]; this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id this._ids = new Map(); // mapping from JS values to reference ids this._idPool = []; // unused ids that have been garbage collected this.exited = false; // whether the Go program has exited const mem = new DataView(this._inst.exports.memory.buffer) while (true) { const callbackPromise = new Promise((resolve) => { this._resolveCallbackPromise = () => { if (this.exited) { throw new Error("bad callback: Go program has already exited"); } setTimeout(resolve, 0); // make sure it is asynchronous }; }); this._inst.exports._start(); if (this.exited) { break; } await callbackPromise; } } _resume() { if (this.exited) { throw new Error("Go program has already exited"); } this._inst.exports.resume(); if (this.exited) { this._resolveExitPromise(); } } _makeFuncWrapper(id) { const go = this; return function () { const event = { id: id, this: this, args: arguments }; go._pendingEvent = event; go._resume(); return event.result; }; } } if ( global.require && global.require.main === module && global.process && global.process.versions && !global.process.versions.electron ) { if (process.argv.length != 3) { console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); process.exit(1); } const go = new Go(); WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { return go.run(result.instance); }).catch((err) => { console.error(err); process.exit(1); }); } })(); ================================================ FILE: src/main/index.ts ================================================ import { getCrxPath, getResourcesPath, getUserDataPath } from './mainfile' import { release } from 'os' import { AppWindow, creatElectronWindow, createMainWindow, createTray, Referer, ShowError, ShowErrorAndExit, ua } from './window' const Electron = require('electron') const { app, BrowserWindow, dialog, Menu, MenuItem, ipcMain, shell, session } = require('electron') const { exec, spawn } = require('child_process') const { existsSync, readFileSync, writeFileSync } = require('fs') const path = require('path') if (release().startsWith('6.1')) app.disableHardwareAcceleration() process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true' process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at:', p, 'reason:', reason) }) process.on('uncaughtException', (err) => { const stack = err.stack || '' if (app.isReady()) ShowErrorAndExit('发生未定义的异常', err.message + '\n' + stack) }) // app.commandLine.appendSwitch('proxy-server', '192.168.31.74:8888') app.commandLine.appendSwitch('no-sandbox') app.commandLine.appendSwitch('disable-web-security') app.commandLine.appendSwitch('disable-renderer-backgrounding') app.commandLine.appendSwitch('disable-site-isolation-trials') app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors,SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure') app.commandLine.appendSwitch('ignore-connections-limit', 'bj29.cn-beijing.data.alicloudccp.com,alicloudccp.com,api.aliyundrive.com,aliyundrive.com') app.commandLine.appendSwitch('ignore-certificate-errors') app.commandLine.appendSwitch('proxy-bypass-list', '') app.commandLine.appendSwitch('wm-window-animations-disabled') app.setAppUserModelId('com.github.liupan1890') app.name = 'alixby3' const DEBUGGING = !app.isPackaged const userData = getResourcesPath('userdir.config') try { if (existsSync(userData)) { const configData = readFileSync(userData, 'utf-8') if (configData) app.setPath('userData', configData) } } catch {} const gotTheLock = app.requestSingleInstanceLock() if (DEBUGGING == false) { if (!gotTheLock) { app.exit() } else { app.on('second-instance', (event, commandLine, workingDirectory) => { if (commandLine && commandLine.join(' ').indexOf('exit') >= 0) { app.exit() } else if (AppWindow.mainWindow && AppWindow.mainWindow.isDestroyed() == false) { if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore() AppWindow.mainWindow.show() AppWindow.mainWindow.focus() } }) } } if (process.argv && process.argv.join(' ').indexOf('exit') >= 0) { app.exit() } app.on('window-all-closed', () => { if (process.platform == 'darwin') { AppWindow.appTray?.destroy() } else { app.quit() // 未测试应该使用哪一个 } }) app.on('activate', () => { if (!AppWindow.mainWindow || AppWindow.mainWindow.isDestroyed()) createMainWindow() else { if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore() AppWindow.mainWindow.show() AppWindow.mainWindow.focus() } }) app.on('will-quit', () => { try { if (AppWindow.appTray) { AppWindow.appTray.destroy() AppWindow.appTray = undefined } } catch { } }) app.setAboutPanelOptions({ applicationName: '阿里云盘小白羊版', copyright: 'liupan1890', website: 'https://github.com/liupan1890/aliyunpan', iconPath: getResourcesPath('app.png'), applicationVersion: '30' }) let userToken: { access_token: string; user_id: string; refresh: boolean } = { access_token: '', user_id: '', refresh: false } ipcMain.on('WebUserToken', (event, data) => { if (data.login) { userToken = data } else if (userToken.user_id == data.user_id) { userToken = data // ShowError('WebUserToken', 'update' + data.name) } else { // ShowError('WebUserToken', 'nothing' + data.name) } }) app .whenReady() .then(() => { session.defaultSession.webRequest.onBeforeSendHeaders((details, cb) => { const should115Referer = details.url.indexOf('.115.com') > 0 const shouldGieeReferer = details.url.indexOf('gitee.com') > 0 const shouldAliOrigin = details.url.indexOf('.aliyundrive.com') > 0 const shouldAliReferer = !should115Referer && !shouldGieeReferer && (!details.referrer || details.referrer.trim() === '' || /(\/localhost:)|(^file:\/\/)|(\/127.0.0.1:)/.exec(details.referrer) !== null) const shouldToken = details.url.includes('aliyundrive') && details.url.includes('download') cb({ cancel: false, requestHeaders: { ...details.requestHeaders, ...(should115Referer && { Referer: 'http://115.com/s/swn4bs33z88', Origin: 'http://115.com' }), ...(shouldGieeReferer && { Referer: 'https://gitee.com/' }), ...(shouldAliOrigin && { Origin: 'https://www.aliyundrive.com' }), ...(shouldAliReferer && { Referer: 'https://www.aliyundrive.com/' }), ...(shouldToken && { Authorization: userToken.access_token }), 'X-Canary': 'client=web,app=adrive,version=v3.0.0', 'Accept-Language': 'zh-CN,zh;q=0.9' } }) }) session.defaultSession.loadExtension(getCrxPath(), { allowFileAccess: true }).then((le) => { createMenu() createTray() createMainWindow() }) }) .catch((err: any) => { console.log(err) }) let menuEdit: Electron.Menu | undefined let menuCopy: Electron.Menu | undefined export function createMenu() { menuEdit = new Menu() menuEdit.append(new MenuItem({ label: '剪切', role: 'cut' })) menuEdit.append(new MenuItem({ label: '复制', role: 'copy' })) menuEdit.append(new MenuItem({ label: '粘贴', role: 'paste' })) menuEdit.append(new MenuItem({ label: '删除', role: 'delete' })) menuEdit.append(new MenuItem({ label: '全选', role: 'selectAll' })) menuCopy = new Menu() menuCopy.append(new MenuItem({ label: '复制', role: 'copy' })) menuCopy.append(new MenuItem({ label: '全选', role: 'selectAll' })) } ipcMain.on('WebToElectron', (event, data) => { let mainWindow = AppWindow.mainWindow if (data.cmd && data.cmd === 'close') { if (mainWindow && !mainWindow.isDestroyed()) mainWindow.hide() } else if (data.cmd && data.cmd === 'exit') { if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.destroy() mainWindow = undefined } try { app.exit() } catch {} } else if (data.cmd && data.cmd === 'minsize') { if (mainWindow && !mainWindow.isDestroyed()) mainWindow.minimize() } else if (data.cmd && data.cmd === 'maxsize') { if (mainWindow && !mainWindow.isDestroyed()) { if (mainWindow.isMaximized()) { mainWindow.unmaximize() } else { mainWindow.maximize() } } } else if (data.cmd && data.cmd === 'menuedit') { if (menuEdit) menuEdit.popup() } else if (data.cmd && data.cmd === 'menucopy') { if (menuCopy) menuCopy.popup() } else { event.sender.send('ElectronToWeb', 'mainsenddata') } }) ipcMain.on('WebToElectronCB', (event, data) => { const mainWindow = AppWindow.mainWindow if (data.cmd && data.cmd === 'maxsize') { if (mainWindow && !mainWindow.isDestroyed()) { if (mainWindow.isMaximized()) { mainWindow.unmaximize() event.returnValue = 'unmaximize' } else { mainWindow.maximize() event.returnValue = 'maximize' } } } else { event.returnValue = 'backdata' } }) ipcMain.on('WebShowOpenDialogSync', (event, config) => { dialog.showOpenDialog(AppWindow.mainWindow!, config).then((result) => { event.returnValue = result.filePaths }) }) ipcMain.on('WebShowSaveDialogSync', (event, config) => { dialog.showSaveDialog(AppWindow.mainWindow!, config).then((result) => { event.returnValue = result.filePath || '' }) }) ipcMain.on('WebShowItemInFolder', (event, fullPath) => { for (let i = 0; i < 5; i++) { if (existsSync(fullPath)) break if (fullPath.lastIndexOf(path.sep) > 0) { fullPath = fullPath.substring(0, fullPath.lastIndexOf(path.sep)) } else return } if (fullPath.length > 2) shell.showItemInFolder(fullPath) }) ipcMain.on('WebPlatformSync', (event) => { const asarPath = app.getAppPath() const basePath = path.resolve(asarPath, '..') const findMPV = process.platform !== 'win32' || existsSync(path.join(basePath, 'MPV', 'mpv.exe')) const appPath = app.getPath('userData') event.returnValue = { platform: process.platform, arch: process.arch, version: process.version, execPath: process.execPath, appPath: appPath, asarPath: asarPath, argv0: process.argv0, findMPV } }) ipcMain.on('WebSpawnSync', (event, data) => { try { const options = { ...data.options } options.detached = true options.stdio = 'ignore' if (data.command === 'mpv') { const basePath = path.resolve(app.getAppPath(), '..') if (process.platform === 'win32') { data.command = path.join(basePath, 'MPV', 'mpv.exe') } else if (process.platform === 'darwin') { data.command = path.join(basePath, 'mpv') } else { data.command = 'mpv' } } if ((process.platform === 'win32' || process.platform === 'darwin') && existsSync(data.command) == false) { event.returnValue = { error: '找不到文件' + data.command } ShowError('找不到文件', data.command) } else { const subprocess = spawn(data.command, data.args, options) const ret = { data: data, exitCode: subprocess.exitCode, pid: subprocess.pid, spawnfile: subprocess.spawnfile, command: data.command } subprocess.unref() event.returnValue = ret } } catch (err: any) { event.returnValue = { error: err } } }) ipcMain.on('WebExecSync', (event, data) => { try { const cmdArguments = [] if (data.command === 'mpv') { const basePath = path.resolve(app.getAppPath(), '..') if (process.platform === 'win32') { const exe = path.join(basePath, 'MPV', 'mpv.exe') if (existsSync(exe) == false) { event.returnValue = { error: '找不到文件' + data.command + ' ' + exe } ShowError('找不到文件', data.command + ' ' + exe) return } cmdArguments.push('"' + exe + '"') } else if (process.platform === 'darwin') { const exe = path.join(basePath, 'mpv') if (existsSync(exe) == false) { event.returnValue = { error: '找不到文件' + data.command + ' ' + exe } ShowError('找不到文件', data.command + ' ' + exe) return } cmdArguments.push("'" + exe + "'") } else { cmdArguments.push('mpv') } } else { cmdArguments.push(data.command) } if (data.args) cmdArguments.push(...data.args) const finalCmd = cmdArguments.join(' ') exec(finalCmd, (err: any) => { event.returnValue = err }) event.returnValue = '' } catch (err: any) { event.returnValue = { error: err } } }) ipcMain.on('WebSaveTheme', (event, data) => { try { const themeJson = getUserDataPath('theme.json') writeFileSync(themeJson, `{"theme":"${data.theme || ''}"}`, 'utf-8') } catch {} }) ipcMain.on('WebClearCookies', (event, data) => { session.defaultSession.clearStorageData(data) }) ipcMain.on('WebSetCookies', (event, data) => { for (let i = 0, maxi = data.length; i < maxi; i++) { const cookie = { url: data[i].url, name: data[i].name, value: data[i].value, domain: '.' + data[i].url.substring(data[i].url.lastIndexOf('/') + 1), secure: data[i].url.indexOf('https://') == 0, expirationDate: data[i].expirationDate } session.defaultSession.cookies.set(cookie).catch((err: any) => console.error(err)) } }) ipcMain.on('WebClearCache', (event, data) => { if (data.cache) { session.defaultSession.clearCache() session.defaultSession.clearAuthCache() } else { session.defaultSession.clearStorageData(data) } }) ipcMain.on('WebReload', (event, data) => { if (AppWindow.mainWindow && !AppWindow.mainWindow.isDestroyed()) AppWindow.mainWindow.reload() }) ipcMain.on('WebRelaunch', (event, data) => { app.relaunch() try { app.exit() } catch {} }) ipcMain.on('WebSetProgressBar', (event, data) => { if (AppWindow.mainWindow && !AppWindow.mainWindow.isDestroyed()) { if (data.pro) { AppWindow.mainWindow.setProgressBar(data.pro, { mode: data.mode || 'normal' }) } else AppWindow.mainWindow.setProgressBar(-1) } }) ipcMain.on('WebShutDown', (event, data) => { if (process.platform === 'darwin') { const shutdownCmd = 'osascript -e \'tell application "System Events" to shut down\'' exec(shutdownCmd, (err: any) => { if (data.quitApp) { try { app.exit() } catch {} } if (err) { // donothing } }) } else { const cmdArguments = ['shutdown'] if (process.platform === 'linux') { if (data.sudo) { cmdArguments.unshift('sudo') } cmdArguments.push('-h') cmdArguments.push('now') } if (process.platform === 'win32') { cmdArguments.push('-s') cmdArguments.push('-f') cmdArguments.push('-t 0') } const finalcmd = cmdArguments.join(' ') exec(finalcmd, (err: any) => { if (data.quitApp) { try { app.exit() } catch {} } if (err) { // donothing } }) } }) ipcMain.on('WebSetProxy', (event, data) => { // if (data.proxyUrl) app.commandLine.appendSwitch('proxy-server', data.proxyUrl) // else app.commandLine.removeSwitch('proxy-server') console.log(JSON.stringify(data)) if (data.proxyUrl) { session.defaultSession.setProxy({ proxyRules: data.proxyUrl }) } else { session.defaultSession.setProxy({}) } }) ipcMain.on('WebOpenWindow', (event, data) => { const win = creatElectronWindow(AppWindow.winWidth, AppWindow.winHeight, true, 'main2', data.theme) win.on('ready-to-show', function () { win.webContents.send('setPage', data) win.setTitle('预览窗口') win.show() }) }) ipcMain.on('WebOpenUrl', (event, data) => { const win = new BrowserWindow({ show: false, width: AppWindow.winWidth, height: AppWindow.winHeight, center: true, minWidth: 680, minHeight: 500, icon: getResourcesPath('app.ico'), useContentSize: true, frame: true, hasShadow: true, autoHideMenuBar: true, backgroundColor: data.theme && data.theme == 'dark' ? '#23232e' : '#ffffff', webPreferences: { spellcheck: false, devTools: DEBUGGING, sandbox: false, webSecurity: false, allowRunningInsecureContent: true, backgroundThrottling: false, enableWebSQL: false, disableBlinkFeatures: 'OutOfBlinkCors,SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure' } }) win.on('ready-to-show', function () { win.setTitle('预览窗口') win.show() }) win.loadURL(data.PageUrl, { userAgent: ua, httpReferrer: Referer }) }) ================================================ FILE: src/main/mainfile.ts ================================================ const { app } = require('electron') const path = require('path') const { existsSync, mkdirSync, writeFileSync, copyFileSync, rmSync } = require('fs') const DEBUGGING = !app.isPackaged let NewCopyed = false let NewSaved = false export function getAsarPath(fileName: string) { if (DEBUGGING) { const basePath = path.resolve(app.getAppPath()) return path.join(basePath, fileName) } else { const basePath = path.resolve(app.getAppPath()) const baseNew = path.join(basePath, '..', 'app.new') const baseSave = path.join(basePath, '..', 'default_app.asar') if (NewCopyed == false) { if (existsSync(baseNew)) { try { console.log('copyFileSync', baseNew, '-->', baseSave) copyFileSync(baseNew, baseSave) rmSync(baseNew, { force: true }) NewCopyed = true } catch (err: any) { console.log(err) } } } if (NewSaved == false) NewSaved = existsSync(baseSave) if (NewSaved) return path.join(baseSave, fileName) return path.join(basePath, fileName) } } export function getResourcesPath(fileName: string) { if (DEBUGGING) { const basePath = path.resolve(app.getAppPath(), '..') return path.join(basePath, fileName) } else { const basePath = path.resolve(app.getAppPath(), '..') if (fileName == 'app.ico' && process.platform !== 'win32') { fileName = 'app.png' } if (fileName == 'app.ico') { try { const png = path.join(basePath, fileName) if (!existsSync(png)) { const bufferData = Buffer.from(appicon, 'base64') writeFileSync(png, bufferData) } } catch {} } if (fileName == 'app.png') { try { const png = path.join(basePath, fileName) if (!existsSync(png)) { const bufferData = Buffer.from(apppng, 'base64') writeFileSync(png, bufferData) } } catch {} } return path.join(basePath, fileName) } } export function getCrxPath() { if (DEBUGGING) { const basePath = path.resolve(app.getAppPath(), '..') return path.join(basePath, 'crx') } else { let basePath = path.resolve(app.getAppPath(), '..') basePath = path.join(basePath, 'crx') try { if (!existsSync(basePath)) mkdirSync(basePath) } catch {} try { const manifest = path.join(basePath, 'manifest.json') if (!existsSync(manifest)) writeFileSync(manifest, crxmanifest, 'utf-8') } catch {} try { const devtoolshtml = path.join(basePath, 'devtools.html') if (!existsSync(devtoolshtml)) writeFileSync(devtoolshtml, crxdevtoolshtml, 'utf-8') } catch {} try { const devtoolsjs = path.join(basePath, 'devtools.js') if (!existsSync(devtoolsjs)) writeFileSync(devtoolsjs, crxdevtoolsjs, 'utf-8') } catch {} return basePath } } export function getUserDataPath(fileName: string) { return path.join(app.getPath('userData'), fileName) } const appicon = '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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+WOZUPtkm3/6ZJu/+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+mSbz/tkm4/3ZJtA/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdglyD4ZJtw+mSbv/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+mSbv/tkm3/6ZZow/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92CXIPhkm3D6ZJvP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+2Wcr/plmjD/YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3YJcg+GSbcPpkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pjnN/4ZJtw/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZZow+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+mOcn/plmjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZZow+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mWaMPpjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//KfG//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/8zd7/+5S6//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm7/6ZZowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtkm3/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//Nfl//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Onw//ynxv/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZJuP/2CfEAAAAAAAAAAAAAAAAAAAAAAA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/f3//f39//39/f/86O///Nrm//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3V5P/95u7//fX4//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//7utL/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2Sbj/9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJu/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3u9P/84Or//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Nrm//zo7//9+vv//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbv/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSbz/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//ODq//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zo7//91eT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3S4v/82ub//fX4//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Nfl//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPpkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zo7//91eT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Nrm//31+P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//ynxv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJvP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zr8f/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//za5v/89/n//f39//39/f/9/f3//f39//39/f/9/f3//f39//u60v/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSbz/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//31+P/83ej//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3S4v/86O///fr7//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//ODq//39/f/9/f3//f39//39/f/9/f3//f39//39/f/86O///M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/82ub//fX4//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Y5yf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9+vv//Nrm//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/90uL//Ovx//39/f/9/f3//f39//39/f/9/f3//f39//3z9//7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mKaYPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fL2//3S4v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//ebu//39/f/9/f3//f39//39/f/9/f3//f39//3z9//7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2SbjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdkm0D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//3m7v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//OPs//36+//9/f3//f39//39/f/9/f3//f39//3z9//6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+WOZUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3YJcg+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//3z9//9/f3//f39//39/f/9/f3//f39//39/f/84+z//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Nrm//36+//9/f3//f39//39/f/9/f3//f39//3z9//7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+mWaMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/98/f//f39//39/f/9/f3//f39//39/f/9/f3//N3o//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+9fk//z3+f/9/f3//f39//39/f/9/f3//f39//zg6v/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvP/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Yppg+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//Onw//39/f/9/f3//f39//39/f/9/f3//f39//za5v/7rcr/+5q9//uMtf/7jLX/+4ax//uGsf/7jLX//JO5//utyv/8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+5q9//uMtf/7hrH/+4ax//uGsf/7hrH/+4ax//uMtf/7rcr//cve//3u9P/9/f3//f39//39/f/9/f3//f39//zg6v/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZJuPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/82ub//JO5//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//p4qP/8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+5q9//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8k7n//dLi//3u9P/9/f3//f39//39/f/9/f3//f39//zD2P/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3ZJtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ZZyv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//N3o//zP4P/7hrH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uavf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zI3P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//p4qP/8z+D//dLi//z3+f/9/f3//f39//39/f/9/f3//f39//u60v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm8//YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+WOZUPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/8z+D//M/g//qgwv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+nio//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+6bG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+5q9//zP4P/8z+D/+9fk//36+//9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tkm38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6Y5zf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/86O///M/g//zP4P/8z+D//LvT//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7TP//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7caT/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7psb//M/g//zP4P/8z+D//ODq//39/f/9/f3//f39//39/f/9/f3//fP3//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7/dkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Nfl//39/f/9/f3//f39//39/f/9/f3//fL2//zP4P/8z+D//M/g//zP4P/8z+D/+nio//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8k7n//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+muf//zP4P/8z+D//M/g//zP4P/8z+D//ebu//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2WcrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//36+//91eT//M/g//zP4P/8z+D//M/g//zP4P/7mr3/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//prn//8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8k7n/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7jLX//M/g//zP4P/8z+D//M/g//zP4P/8z+D//e70//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/92SbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mSbv/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/9/f3//OPs//zP4P/8z+D//M/g//zP4P/8z+D//M/g//vB1//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//utyv/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/90uL//fX4//39/f/9/f3//f39//39/f/86fD/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZZyvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdglyD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zN3v/9/f3//f39//39/f/9/f3//f39//3y9v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uGsf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4ax//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8u9P/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7caT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/71+T//fr7//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3ZJtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//f39//39/f/9/f3//f39//39/f/9+vv//dXk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+63K//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6a5///Mjc//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//yTuf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qgwv/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/84+z//f39//39/f/9/f3//f39//3z9//6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zN3v/9/f3//f39//39/f/9/f3//f39//zj7P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+muf//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7rcr//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+muf//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+8HX//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3S4v/99fj//f39//39/f/9/f3//f39//zX5f/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//ljmVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Sbj/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/98vb//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7jLX/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uGsf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//utyv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uGsf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zd6P/9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2WcrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6Y5zf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zg6v/9/f3//f39//39/f/9/f3//f39//3V5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//u0z//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+muf//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4y1//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+6bG//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zr8f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mKaYPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/86/H//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+5q9//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zI3P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//prn//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+9fk//39/f/9/f3//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6YppgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Y5zf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//vX5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+5q9//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6eKj//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+6bG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4y1//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//e70//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tlnK8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92SbQPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/89/n//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7wdf/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7wdf//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7caT/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7wdf//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/83ej//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ZJuP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//zg6v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7hrH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uavf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+muf//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/98vb//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2SbfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9+vv//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//utyv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+nio//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8k7n/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6oML//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zg6v/9/f3//f39//39/f/9/f3//Onw//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvPAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//9/f3//f39//39/f/9/f3//f39//zj7P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//prn//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7TP//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//z3+f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3ZJtAAAAAAAAAAAAAAAAAAAAAAPhkm3D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9+vv//dXk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4y1//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7mr3//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7tM//+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7hrH//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//ebu//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAA+mSbv/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//zr8f/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//txpP/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uMtf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//umxv/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/71+T//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbzwAAAAAAAAAAAAAAAP9gnxD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//ODq//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7caT/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//umxv/7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7tM//+7TP//u0z//7rcr/+muf//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6a5///M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/89/n//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/92CXIAAAAAAAAAAA+WOZUPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uavf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uMtf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3u9P/9/f3//f39//39/f/9/f3/+53A//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//5Y5lQAAAAAAAAAAD7ZJuP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//fL2//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+8HX//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+8HX//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//N3o//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAPtlnK/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/84+z//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4ax//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//prn//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/90uL//f39//39/f/9/f3//f39//zp8P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbzwAAAAAAAAAA+mOc3/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/9/f3//f39//39/f/9/f3//f39//3V5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+qDC//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/99fj//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvvAAAAAP9gnxD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+5S6//39/f/9/f3//f39//39/f/9+vv//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zI3P/6a5//+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7wdf//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//N3o//zj7P/84+z//ODq//za5v/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3m7v/9/f3//f39//39/f/9/f3//LHM//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3YJcg92CXIPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//36+//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uMtf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4ax//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/83ej//fX4//39/f/9/f3//f39//39/f/9/f3//f39//39/f/99fj//Ovx//vX5P/8z+D//M/g//zP4P/8z+D//N3o//39/f/9/f3//f39//39/f/8w9j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//ljmVD5Y5lQ+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//e70//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+63K//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7psb//M/g//zP4P/8z+D//M/g//zP4P/71+T//Pf5//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3y9v/84+z//dLi//zP4P/91eT//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+GSbcPtkm4/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/95u7//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+3Gk//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+muf//zP4P/8z+D//M/g//zP4P/8z+D//OPs//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9+vv//OPs//3S4v/89/n//f39//39/f/9/f3//Onw//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZJuP+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//98/f//f39//39/f/9/f3//f39//zj7P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7mr3/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/81+X//Nfl//zX5f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7jLX//M/g//zP4P/8z+D/+9fk//z3+f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fr7//36+//9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pjnJ/7ZZyv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3/+9fk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//y70//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//vB1//8z+D/+9fk//zr8f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbv/pkm7/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//p/rP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bKD//OPs//3y9v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvP+mSbz/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+6bG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//u60v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pjnN/6Y5zf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9+vv//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+muf//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7ncD/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//36+//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7hrH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//fr7//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//utyv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6Y5zf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9+vv//ebu//3m7v/84+z//OPs//za5v/71+T//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//tzpf/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7/pjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9+vv//fL2//vX5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/91eT//LHM//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//ynxv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvv+mOc3/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3y9v/84+z//dLi//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//31+P/84Or/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+53A//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm+/6ZJvP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/99fj/+9fk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/97vT//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7/pkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9+vv//OPs//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//OPs//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6Y5zf+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Ojv//3S4v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zj7P/9/f3//f39//39/f/9/f3//fP3//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tlnK/6Y5yf+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fX4//3V5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/95u7//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2Wcr/hkm3D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fr7//zd6P/8z+D//M/g//zP4P/8z+D//ebu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZJt/+mKaYPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fr7//3m7v/71+T//dLi//zr8f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/81+X/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//hkm3D3ZJtA+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/92SbQPdglyD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3YJcgAAAAAPpjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+oqz//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7wAAAAAAAAAA+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//ODq//zD2P/84Or//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ZZyvAAAAAAAAAAD4ZJtw+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zN3v/9/f3//f39//39/f/9/f3//f39//zX5f/6ZJv/+mSb//pkm//8p8b//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tkm38AAAAAAAAAAPdkm0D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mKaYAAAAAAAAAAA/2CfEPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8w9j//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm///YJ8QAAAAAAAAAAAAAAAA+mSbv/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2WcrwAAAAAAAAAAAAAAAAAAAAD7ZJt/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv//LHM//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/7d6j/+mSb//qKs//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//MPY//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//4ZJtwAAAAAAAAAAAAAAAAAAAAAPplmjD6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+3eo//39/f/9/f3//f39//39/f/98/f/+3eo//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAPpjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Sbj/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//u60v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//hkm3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3ZJtA+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Onw//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Onw//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/92CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZJvP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+5S6//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8w9j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm+8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtkm3/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+3eo//3z9//9/f3//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zN3v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zN3v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2SbfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPpkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm+/3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7d6j//fP3//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//LHM//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//8scz/+4Gu//pkm//7ga7//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uBrv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZZow+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//zX5f/6bqH/+mSb//pkm//6ZJv/+mSb//puof/81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/98/f/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/86fD/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ZZyv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/98/f//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdkm0D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//fP3//uBrv/6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//u60v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpkm7/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//ODq//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92SbQPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+5S6//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//LHM//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6irP//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Sbj/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//KfG//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2WcrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//ODq//39/f/9/f3//f39//39/f/98/f/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm+/3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4ZJtw+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7//fP3//39/f/9/f3//f39//39/f/98/f/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+GSbcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJvP+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//f39//39/f/9/f3//f39//39/f/86fD/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//ynxv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pjnN8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD6ZJvv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/84Or/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//ynxv/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+oqz//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mWaMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPhkm3D6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/84Or//f39//39/f/9/f3//f39//39/f/84Or/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtlnK/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/84Or//f39//39/f/9/f3//f39//39/f/84Or/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJu/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPpkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/86fD//f39//39/f/9/f3//f39//39/f/86fD/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/86fD/+m6h//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb7/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+WOZUPpkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//t3qP/86fD//f39//39/f/9/f3//f39//39/f/98/f/+5S6//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8w9j//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//uBrv/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//3ZJtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+GSbcPpkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/86fD//f39//39/f/9/f3//f39//39/f/98/f/+53A//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//7ga7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+GSbcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Sbj/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/98/f//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//uBrv/84Or//f39//39/f/9/f3//f39//39/f/9/f3//Nfl//t3qP/6ZJv/+mSb//pkm//7ga7//f39//39/f/84Or/+7rS//zD2P/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJu/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/8w9j//f39//39/f/9/f3//f39//39/f/9/f3//fP3//yxzP/6irP//KfG//3z9//9/f3//Nfl//pkm//6ZJv/+mSb//puof/7utL//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zX5f/7ga7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSbz/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8p8b//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7ga7/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//LHM//zg6v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f//ODq//zX5f/8zd7//M3e//zN3v/81+X//Nfl//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pjnN//YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6irP//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//qKs//7utL//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvP/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH/+oqz//u60v/84Or//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Nfl//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Wcr/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+oqz//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6irP//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mOcn/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//u60v/98/f//f39//39/f/9/f3//f39//39/f/9/f3//fP3//zX5f/7ga7/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6irP//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//u60v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJu/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+GSbcPpkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//qKs//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/81+X/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//u60v/7d6j/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6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ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH/+oqz//yxzP/84Or//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or//LHM//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJvP+mWaMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3ZJtA+mSbz/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH/+5S6//zD2P/84Or//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//zN3v/8scz/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+GSbcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Sbj/pkm+/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ga7/+53A//yxzP/81+X//ODq//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f//Onw//zN3v/8scz/+5S6//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcn/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPtkm4/6ZJvv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+m6h//puof/7ga7/+5S6//uUuv/7ncD/+53A//udwP/6irP/+oqz//t3qP/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2Wcr/dglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdkm0D6ZJu/+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbv/dkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3YJcg+2Sbf/pjnN/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+2Sbj/plmjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPdkm0D7ZZyv+mSb7/pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6Y5zf+2SbfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+2Sbf/pkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm7/7ZJt/92SbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPplmjD4ZJtw+2Wcr/pkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOcn/pimmD/YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD5Y5lQ+2Sbj/pkm8/6ZJvv+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mOc3/tlnK/7ZJt/92SbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZZow+WOZUPhkm3D4ZJtw+2Sbj/pjnJ/6ZJu/+mSbz/pjnN/6ZJvv+mSb7/pkm+/6ZJvv+mOc3/tlnK/6Y5yf+2Sbf/pimmD3ZJtA92CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////wAAB////////////////8AAAAA///////////////4AAAAAA//////////////wAAAAAAB/////////////gAAAAAAAH////////////gAAAAAAAAf///////////gAAAAAAAAB///////////gAAAAAAAAAH//////////gAAAAAAAAAAf/////////wAAAAAAAAAAB/////////wAAAAAAAAAAAP////////4AAAAAAAAAAAA////////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAA///////+AAAAAAAAAAAAAH///////AAAAAAAAAAAAAAf//////AAAAAAAAAAAAAAD//////gAAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAD/////4AAAAAAAAAAAAAAAf////8AAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAf////gAAAAAAAAAAAAAAAH////wAAAAAAAAAAAAAAAA////4AAAAAAAAAAAAAAAAH///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAH///gAAAAAAAAAAAAAAAAB///wAAAAAAAAAAAAAAAAAP//8AAAAAAAAAAAAAAAAAB//+AAAAAAAAAAAAAAAAAAf//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//4AAAAAAAAAAAAAAAAAAH/+AAAAAAAAAAAAAAAAAAB//AAAAAAAAAAAAAAAAAAAP/wAAAAAAAAAAAAAAAAAAD/4AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAH/AAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAB8AAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH8AAAAAAAAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAP+AAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAB/8AAAAAAAAAAAAAAAAAAA//AAAAAAAAAAAAAAAAAAAP/4AAAAAAAAAAAAAAAAAAH/+AAAAAAAAAAAAAAAAAAB//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//gAAAAAAAAAAAAAAAAAH//4AAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAAA///4AAAAAAAAAAAAAAAAAf///AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///+AAAAAAAAAAAAAAAAB////wAAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAB/////8AAAAAAAAAAAAAAA//////gAAAAAAAAAAAAAAf/////8AAAAAAAAAAAAAAf//////gAAAAAAAAAAAAAP//////+AAAAAAAAAAAAAH///////wAAAAAAAAAAAAD///////+AAAAAAAAAAAAB////////wAAAAAAAAAAAB/////////AAAAAAAAAAAA/////////8AAAAAAAAAAA//////////gAAAAAAAAAAf/////////+AAAAAAAAAAf//////////4AAAAAAAAAf///////////gAAAAAAAAf///////////+AAAAAAAA/////////////8AAAAAAA//////////////wAAAAAB///////////////4AAAAH////////////////4AAA/////////KAAAAEAAAACAAAAAAQAgAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD5Y5lQ+2Sbf/pkm7/6ZJu/+mOc3/pkm//6ZJv/+mSb//pmnPH6ZJvv+mSbz/tlnK/7ZJuP+mKaYPdglyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZZow+GSbcPpkm8/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSbz/tkm4/6ZZow/2CfEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAPpjnJ/6ZJv/+mSb//pkm//6ZJv/+m6h//zg6v/9/f3//f39//39/f/99fj/+9fk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/90uL//Ojv//36+//9/f3//f39//zg6v/7ga7/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPhkm3D6ZJv/+mSb//pkm//6ZJv/+4Gu//3z9//9/f3//f39//z3+f/84Or//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/82ub//fX4//39/f/9/f3//fP3//udwP/6ZJv/+mSb//pkm//6ZJv/+2SbjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPljmVD6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//31+P/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/95u7//f39//39/f/98/f/+53A//pkm//6ZJv/+mSb//pkm//4ZJtwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdkm0D6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//zo7//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zj7P/9+vv//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//ljmVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJv/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//zj7P/7rcr/+6bG//utyv/8u9P//Mjc//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+63K//umxv/7tM//+8vc//36+//9/f3//fP3//uUuv/6ZJv/+mSb//pkm//6Zpzy+mWaMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ZZyv+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//zg6v/6eKj/+mSb//pkm//6ZJv/+mSb//uMtf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7caT/+mSb//pkm//6ZJv/+mSb//p4qP/71+T//fr7//39/f/98/f/+4Gu//pkm//6ZJv/+mSb//tlnK8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5Y5lQ+mSb//pkm//6ZJv/+mSb//zX5f/9/f3//f39//zo7//8z+D/+4ax//pkm//6ZJv/+mSb//pkm//6a5//+8HX//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+mSb//pkm//6ZJv/+mSb//pkm//7hrH//M/g//zj7P/9/f3//f39//zg6v/6bqH/+mSb//pkm//6ZJv/+WOZUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mSc4Ppkm//6ZJv/+mSb//ynxv/9/f3//f39//3y9v/8z+D//M/g//utyv/6ZJv/+mSb//pkm//6ZJv/+mSb//uavf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4y1//pkm//6ZJv/+mSb//pkm//6ZJv/+6bG//zP4P/8z+D//ebu//39/f/9/f3//LHM//pkm//6ZJv/+mSb//pknOD/YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+2Sbf/pkm//6ZJv/+mSb//t3qP/9/f3//f39//36+//91eT//M/g//zP4P/8yNz/+3Gk//pkm//6ZJv/+mSb//pkm//7hrH//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//pkm//6ZJv/+mSb//pkm//6ZJv/+muf//zP4P/8z+D//M/g//3S4v/97vT//f39//3z9//7ga7/+mSb//pkm//6ZJv/+2SbfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtmneP6ZJv/+mSb//pkm//8w9j//f39//39/f/83ej//M/g//zP4P/8z+D//M/g//uavf/6ZJv/+mSb//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//umxv/6ZJv/+mSb//pkm//6ZJv/+mSb//uMtf/8z+D//M/g//zP4P/8z+D//dXk//36+//9/f3//Nfl//pkm//6ZJv/+mSb//pmnPH3YJcgAAAAAAAAAAAAAAAAAAAAAPpimmD6ZJv/+mSb//pkm//7d6j//f39//39/f/98vb//M/g//zP4P/8z+D//M/g//zP4P/8u9P/+mSb//pkm//6ZJv/+mSb//pkm//7mr3//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/6f6z/+mSb//pkm//6ZJv/+mSb//pkm//7tM///M/g//zP4P/8z+D//M/g//zP4P/95u7//f39//39/f/6irP/+mSb//pkm//6ZJv/+2SbfwAAAAAAAAAAAAAAAAAAAAD6ZJzg+mSb//pkm//6ZJv//MPY//39/f/9/f3/+9fk//zP4P/8z+D//M/g//zP4P/8z+D//M/g//p/rP/6ZJv/+mSb//pkm//6ZJv/+nio//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+mSb//pkm//6ZJv/+mSb//pkm//6a5///M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//z3+f/9/f3//M3e//pkm//6ZJv/+mSb//plnNAAAAAAAAAAAAAAAAD/YJ8Q+mSb//pkm//6ZJv/+m6h//39/f/9/f3//Pf5//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/6oML/+mSb//pkm//6ZJv/+mSb//pkm//8u9P//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+5q9//pkm//6ZJv/+mSb//pkm//6ZJv/+qDC//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/95u7//f39//39/f/7ga7/+mSb//pkm//6ZJv/92SbQAAAAAAAAAAA+2Sbf/pkm//6ZJv/+mSb//u60v/9/f3//f39//zg6v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//prn//6ZJv/+mSb//pkm//6ZJv/+5q9//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//36+//9/f3/+7rS//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAPpjnN/6ZJv/+mSb//pkm//86fD//f39//36+//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7hrH/+mSb//pkm//6ZJv/+mSb//p4qP/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//vB1//6ZJv/+mSb//pkm//6ZJv/+mSb//p4qP/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/97vT//f39//zg6v/6ZJv/+mSb//pkm//6ZJvPAAAAAP9gnxD6ZJv/+mSb//pkm//6bqH//f39//39/f/97vT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+63K//pkm//6ZJv/+mSb//pkm//6ZJv/+4y1//uMtf/7jLX/+4y1//uMtf/7jLX/+4y1//uMtf/7jLX/+4y1//uMtf/7jLX/+4y1//uMtf/7jLX/+4y1//uMtf/6eKj/+mSb//pkm//6ZJv/+mSb//pkm//7psb//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//ODq//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//dglyD5Y5lQ+mSb//pkm//6ZJv/+53A//39/f/9/f3//OPs//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zI3P/7caT/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6a5///Mjc//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//3V5P/9/f3//f39//udwP/6ZJv/+mSb//pkm//5Y5lQ+2Sbf/pkm//6ZJv/+mSb//u60v/9/f3//f39//vX5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+5q9//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+4y1//zP4P/8z+D//M/g//zP4P/8z+D/+9fk//3S4v/8z+D//M/g//zP4P/8z+D//Pf5//39/f/8zd7/+mSb//pkm//6ZJv/+2Sbf/tkm4/6ZJv/+mSb//pkm//84Or//f39//36+//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//y70//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//utyv/8z+D//M/g//vX5P/86/H//f39//39/f/9/f3//fr7//3y9v/71+T//M/g//zr8f/9/f3//Onw//pkm//6ZJv/+mSb//tlnK/6ZJvP+mSb//pkm//6ZJv//fP3//39/f/97vT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+nio//pkm//6ZJv/+mSb//pkm//7c6b/+53A//udwP/7ncD/+53A//udwP/7ncD/+53A//udwP/7ncD/+53A//udwP/7ncD/+53A//ubv//6ZJv/+mSb//pkm//6ZJv/+mSb//prn//8z+D//dLi//zr8f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3y9v/99fj//f39//39/f/6ZJv/+mSb//pkm//6ZJvP+mSbz/pkm//6ZJv/+m6h//39/f/9/f3//Ojv//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uavf/6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb//pkm//6qMb//OPs//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSbz/pnntT6ZJv/+mSb//puof/9/f3//f39//3m7v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+muf//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+53A//pkm//6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uBrv/6ZJv/+mSb//pmneL5ap/Z+mSb//pkm//7d6j//f39//39/f/95u7//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uGsf/6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//7aJ7l+2ie5fpkm//6ZJv/+4Gu//39/f/9/f3//Pf5//3u9P/86/H//ebu//vX5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7t8//+mSb//pkm//6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+oqz//pkm//6ZJv/+mac8vpmneL6ZJv/+mSb//t3qP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fL2//zd6P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/91eT//fP3//t3qP/6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uBrv/6ZJv/+mSb//pmnPH6Y5zf+mSb//pkm//6ZJv//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Ojv//3S4v/8z+D//M/g//zP4P/90uL//fX4//39/f/8scz/+mSb//pkm//6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6bqH/+mSb//pkm//6ZJvv+2Wcr/pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98vb//dLi//zP4P/90uL//fX4//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+mSb//pkm//6ZJv/+2Wcr/hkm3D6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//z3+f/86O///fr7//39/f/9/f3//f39//39/f/7ga7/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//tkm4/6Yppg+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//LHM//pkm//6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/6ZJv/+mSb//pkm//6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//pkm//4ZJtw+mWaMPpkm//6ZJv/+mSb//udwP/9/f3//f39//3z9//8scz/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zp8P/6bqH/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7ncD/+mSb//pkm//6ZJv/92SbQP9gnxD6ZJv/+mSb//pkm//7ga7//f39//39/f/8zd7/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//dglyAAAAAA+mSbv/pkm//6ZJv/+mSb//zX5f/9/f3//Nfl//pkm//6ZJv/+5S6//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zN3v/6ZJv/+mSb//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/7utL//Onw//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pjnN8AAAAAAAAAAPhkm3D6ZJv/+mSb//pkm//8p8b//f39//39/f/7ga7/+mSb//puof/86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+3eo//pkm//6ZJv/+mSb//pkm//84Or//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//puof/86fD//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//4ZJtwAAAAAAAAAAD/YJ8Q+mSb//pkm//6ZJv/+3eo//39/f/9/f3//LHM//pkm//6ZJv//LHM//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv//LHM//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv/92CXIAAAAAAAAAAAAAAAAPtmnbH6ZJv/+mSb//pkm//8w9j//f39//3z9//6bqH/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+mSb//pkm//6ZJv/+mSb//t3qP/9/f3//f39//39/f/8w9j/+mSb//pkm//6ZJv/+mSb//pkm//8w9j//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//zg6v/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv/+mSb7wAAAAAAAAAAAAAAAAAAAAD4ZJtw+mSb//pkm//6ZJv/+4Gu//3z9//9/f3/+7rS//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uBrv/6ZJv/+mSb//pkm//6ZJv//Nfl//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zX5f/7ga7/+3eo//yxzP/9/f3//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pimmAAAAAAAAAAAAAAAAAAAAAA/2CfEPpontX6ZJv/+mSb//pkm//8w9j//f39//3z9//7ga7/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//6ZJv/+mSb//ynxv/9/f3//fP3//pkm//6ZJv/+mSb//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//pmnPEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Yppg+mSb//pkm//6ZJv/+3eo//3z9//9/f3//ODq//puof/6ZJv/+m6h//zg6v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Onw//pkm//6ZJv/+mSb//pkm//6bqH//fP3//u60v/6ZJv/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uBrv/6ZJv/+mSb//pkm//4ZJtwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpnnML6ZJv/+mSb//pkm//8p8b//f39//39/f/7utL/+mSb//pkm//6bqH//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6ZJv/+mSb//zN3v/7d6j/+mSb//pkm//6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//ynxv/6ZJv/+mSb//pkm//6ZZvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5Y5lQ+mSb//pkm//6ZJv/+mSb//zN3v/9/f3//f39//ynxv/6ZJv/+mSb//puof/8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//pkm//6irP/+mSb//pkm//6ZJv/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zX5f/6ZJv/+mSb//pkm//6ZJv/+WOZUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtlnK/6ZJv/+mSb//pkm//7d6j//fP3//39/f/9/f3/+5S6//pkm//6ZJv/+m6h//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//7d6j/+mSb//pkm//6ZJv/+2WcrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+mqf1/pkm//6ZJv/+mSb//uBrv/98/f//f39//3z9//7lLr/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//LHM//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mac8v9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD6Z530+mSb//pkm//6ZJv/+oqz//3z9//9/f3//fP3//ynxv/6ZJv/+mSb//pkm//8scz//f39//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//dkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mKaYPpkm//6ZJv/+mSb//pkm//6irP//fP3//39/f/9/f3/+7rS//puof/6ZJv/+m6h//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+4Gu//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6ZJv/+mSb//tkm38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ZJt/+mSb//pkm//6ZJv/+mSb//qKs//86fD//f39//39/f/81+X/+4Gu//yxzP/98/f//KfG//udwP/84Or//f39//39/f/9/f3//f39//u60v/6bqH/+mSb//pkm//6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6irP/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPpjnJ/6ZJv/+mSb//pkm//6ZJv/+m6h//zN3v/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+m6h//qKs//84Or//fP3//39/f/9/f3//f39//zp8P/86fD//Onw//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/6bqH/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+GSbcPppnvb6ZJv/+mSb//pkm//6bqH/+7rS//3z9//9/f3//f39//3z9//6irP/+mSb//pkm//6ZJv/+mSb//puof/7lLr//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//tkm48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5Y5lQ+med9Ppkm//6ZJv/+mSb//pkm//7ga7//M3e//39/f/9/f3//f39//zX5f/8p8b/+m6h//pkm//6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//MPY//t3qP/6ZJv/+mSb//pkm//6ZJv/+mSb//tkm38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD7Z57k+mSb//pkm//6ZJv/+mSb//pkm//6irP/+7rS//3z9//9/f3//f39//3z9//8zd7/+4Gu//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8zd7/+3eo//pkm//6ZJv/+mSb//pkm//6ZJv/+mac8vdkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92CXIPtlnK/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6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z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//zo7//9/f3//f39//ynxv/6ZJv/+mSb//ppnvb5Y5lQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92CXIPpnnfT6ZJv/+mSb//qKs//9/f3//f39//3m7v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/84+z//fr7//39/f/7ncD/+mSb//pkm//6Z530+mWaMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+mqf2Ppkm//6ZJv/+oqz//39/f/9/f3//Mvd//p/rP/6f6z/+4ax//umxv/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7mr3/+n+s//p4qP/7hrH/+7zT//36+//98/f/+5S6//pkm//6ZJv/+W2gzP9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Yppg+mSb//pkm//6bqH//Onw//39/f/84+z/+63K//pkm//6ZJv/+mSb//prn//8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zI3P/6ZJv/+mSb//pkm//6ZJv/+6bG//zj7P/9/f3//fP3//uBrv/6ZJv/+mSb//hkm3AAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD6ZJv/+mSb//pkm//8zd7//f39//3y9v/8z+D//Mjc//txpP/6ZJv/+mSb//pkm//7rcr//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//yTuf/6ZJv/+mSb//pkm//6a5///M/g//zP4P/86O///f39//zN3v/6ZJv/+mSb//pnnfT/YJ8QAAAAAAAAAAAAAAAAAAAAAPtkm4/6ZJv/+mSb//uUuv/9/f3//fr7//3V5P/8z+D//M/g//uavf/6ZJv/+mSb//pkm//7hrH//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//pkm//7jLX//M/g//zP4P/90uL//fL2//39/f/7ncD/+mSb//pkm//7ZJuPAAAAAAAAAAAAAAAA/2CfEPtsoez6ZJv/+mSb//zp8P/9/f3//ODq//zP4P/8z+D//M/g//y70//6ZJv/+mSb//pkm//6a5//+8HX//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+7TP//pkm//6ZJv/+mSb//pkm//7wdf//M/g//zP4P/8z+D/+9fk//36+//86fD/+m6h//pkm//6aJ31/2CfEAAAAAAAAAAA+mKaYPpkm//6ZJv/+oqz//39/f/9+vv//M/g//zP4P/8z+D//M/g//zP4P/6f6z/+mSb//pkm//6ZJv/+5q9//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4y1//pkm//6ZJv/+mSb//prn//8z+D//M/g//zP4P/8z+D//M/g//zr8f/9/f3/+5S6//pkm//6ZJv/+2SbfwAAAAAAAAAA+mqexvpkm//6ZJv//Nfl//39/f/84+z//M/g//zP4P/8z+D//M/g//zP4P/6oML/+mSb//pkm//6ZJv/+n+s//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+mSb//pkm//6ZJv/+mSb//qgwv/8z+D//M/g//zP4P/8z+D//M/g//vX5P/9/f3//Nfl//pkm//6ZJv/+mee1AAAAAAAAAAA+mme9vpkm//6bqH//f39//36+//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+muf//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7psb/+mSb//pkm//6ZJv/+mSb//vB1//8z+D//M/g//zP4P/8z+D//M/g//zP4P/98vb//f39//t3qP/6ZJv/+mSb//dglyD/YJ8Q+mSb//pkm//7ncD//f39//3u9P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4ax//pkm//6ZJv/+mSb//p4qP/6f6z/+n+s//p/rP/6f6z/+n+s//p/rP/6f6z/+n+s//p/rP/6f6z/+n+s//p/rP/7caT/+mSb//pkm//6ZJv/+n+s//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/84+z//f39//udwP/6ZJv/+mSb//ljmVD6Yppg+mSb//pkm//7utL//f39//3m7v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+63K//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+6bG//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/71+T//f39//zN3v/6ZJv/+mSb//tkm4/8bqKZ+mSb//pkm//86fD//f39//za5v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//txpP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6a5///M/g//zP4P/71+T//Ovx//36+//99fj//e70//vX5P/8z+D//Pf5//zp8P/6ZJv/+mSb//ppnsX6ap/Y+mSb//pkm//98/f//f39//3S4v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//uavf/6ZJv/+mSb//pkm//7fKv/+7rS//u60v/7utL/+7rS//u60v/7utL/+7rS//u60v/7utL/+7jR//t/rP/6ZJv/+mSb//pkm//7jLX//dLi//zr8f/9/f3//f39//39/f/9/f3//f39//39/f/98vb//fr7//39/f/6bqH/+mSb//tonuX6bqLd+mSb//puof/9/f3//fr7//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//y70//6ZJv/+mSb//pkm//7ga7//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//84Or//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//tqn+j7a6Hr+mSb//puof/9/f3//Pf5//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/6gK3/+mSb//pkm//6ZJv//ODq//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7ga7/+mSb//ponfX7a6Hr+mSb//t3qP/9/f3//fr7//31+P/97vT//Ojv//3V5P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7sc3/+mSb//pkm//6ZJv//LHM//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//u60v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7ga7/+mSb//pkm//7ap/o+mSb//puof/9/f3//f39//39/f/9/f3//f39//36+//84+z//dLi//zP4P/8z+D//M/g//zd6P/98/f/+m6h//pkm//6ZJv/+4Gu//39/f/9/f3//f39//39/f/9/f3//f39//39/f/86fD/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6bqH/+mSb//pnnfT6baHL+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//fX4//3V5P/8z+D//Nrm//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//zX5f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6ZJv/+mSb//tonuX6a6Cn+mSb//pkm//8zd7//f39//39/f/9/f3//f39//39/f/9/f3//f39//36+//98vb//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6ZJv/+mSb//tqoLb4ZJtw+mSb//pkm//8w9j//f39//39/f/84Or//fP3//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//t3qP/6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//zN3v/6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mSb//tkm3/5Y5lQ+mSb//pkm//7lLr//f39//zg6v/6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//8zd7//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pimmD/YJ8Q+mme9vpkm//6bqH//fP3//zp8P/6ZJv/+m6h//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//7lLr//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3/+7rS//yxzP/84Or//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//9gnxAAAAAA+2yhuPpkm//6ZJv//M3e//39/f/7lLr/+mSb//yxzP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//6bqH//fP3//39/f/9/f3//MPY//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/86fD/+mSb//pkm//6bqH//f39//39/f/9/f3//ODq//pkm//6ZJv/+2yhuAAAAAAAAAAA+WOZUPpkm//6ZJv/+5S6//39/f/8zd7/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//6ZJv//MPY//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//u60v/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+mSb//pkm//6bqH//f39//39/f/9/f3/+53A//pkm//6ZJv/+GSbcAAAAAAAAAAA/2CfEPponfX6ZJv/+mSb//zX5f/9/f3/+oqz//pkm//8p8b//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+m6h//pkm//6ZJv/+5S6//39/f/98/f/+mSb//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//MPY//uUuv/81+X//f39//39/f/98/f/+mSb//pkm//6aJ31AAAAAAAAAAAAAAAAAAAAAPtkm3/6ZJv/+mSb//uUuv/9/f3//ODq//puof/6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv/+mSb//zp8P/7utL/+mSb//pkm//6ZJv/+oqz//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//7ZJt/AAAAAAAAAAAAAAAAAAAAAP9gnxD6ap/q+mSb//pkm//7utL//f39//u60v/6ZJv/+m6h//zN3v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+mSb//yxzP/7d6j/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zN3v/6ZJv/+mSb//pnnfT3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAD4ZJtw+mSb//pkm//6bqH//M3e//39/f/8scz/+mSb//puof/8w9j//f39//39/f/9/f3//f39//39/f/9/f3//fP3//t3qP/6ZJv/+mSb//t3qP/6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//puof/6ZJv/+mSb//hkm3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+nCjv/pkm//6ZJv/+m6h//zg6v/9/f3/+5S6//pkm//6bqH/+7rS//39/f/9/f3//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//7ncD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+oqz//pkm//6ZJv/+W2gzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPpvot/6ZJv/+mSb//uBrv/98/f//fP3//ynxv/6ZJv/+mSb//ynxv/9/f3//f39//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//81+X//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/7lLr/+mSb//pkm//6Z53092CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPplmjD6aZ72+mSb//pkm//7ncD//fP3//39/f/7utL/+m6h//t3qP/98/f//f39//39/f/9/f3//f39//39/f/7ga7/+mSb//pkm//6ZJv/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//udwP/6ZJv/+mSb//pkm//3ZJtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Yppg+muf+fpkm//6ZJv/+oqz//zp8P/9/f3//Nfl//zX5f/8zd7/+m6h//qKs//84Or//f39//39/f/84Or//LHM//ynxv/7ncD//LHM//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/98/f/+4Gu//pkm//6ZJv/+mSb//dkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7cqWv+mSb//pkm//6irP//f39//39/f/86O///M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//zg6v/89/n//fP3//udwP/6ZJv/+mSb//typa//YJ8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6Zp2i+mSb//pkm//8p8b//f39//36+//71+T//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dXk//3y9v/9/f3//KfG//pkm//6ZJv//GedkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5Y5lQ+mSb//pkm//6irP//f39//31+P/8qsj/+5q9//qgwv/8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+qDC//uavf/7osP//eXv//39/f/7ncD/+mSb//pkm//4ZJtwAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+22h7fpkm//6bqH//f39//36+//9y97/+mSb//pkm//6ZJv/+5q9//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+4y1//pkm//6ZJv/+mSb//zE2f/98vb//fP3//qKs//6ZJv/+mme9v9gnxAAAAAAAAAAAAAAAAAAAAAA+madovpkm//6ZJv//ODq//39/f/71+T//M/g//uGsf/6ZJv/+mSb//p4qP/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//prn//6ZJv/+mSb//txpP/8z+D//dXk//36+//84Or/+m6h//pkm//8Z52SAAAAAAAAAAAAAAAA/2CfEPpkm//6ZJv/+53A//39/f/86O///M/g//zP4P/7rcr/+mSb//pkm//6ZJv/+7TP//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//umxv/6ZJv/+mSb//pkm//6oML//M/g//zP4P/83ej//f39//yxzP/6ZJv/+mme9/plmjAAAAAAAAAAAPtrn4X6ZJv/+mSb//zp8P/9+vv//M/g//zP4P/8z+D//Mjc//prn//6ZJv/+mSb//uavf/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7jLX/+mSb//pkm//6ZJv/+8HX//zP4P/8z+D//M/g//3y9v/98/f/+m6h//pkm//7a5+FAAAAAAAAAAD7a6Dq+mSb//udwP/9/f3//OPs//zP4P/8z+D//M/g//zP4P/7jLX/+mSb//pkm//7caT//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+mSb//pkm//6ZJv/+4y1//zP4P/8z+D//M/g//zP4P/83ej//f39//udwP/6ZJv/+2ug6gAAAAD/YJ8Q+mSb//pkm//8w9j//fr7//3V5P/8z+D//M/g//zP4P/8z+D/+63K//pkm//6ZJv/+mSb//u0z//8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+6bG//pkm//6ZJv/+mSb//umxv/8z+D//M/g//zP4P/8z+D//M/g//31+P/84Or/+mSb//pkm//5Y5lQ+WOZUPpkm//6bqH//f39//3u9P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7caT/+mSb//pkm//7caT/+n+s//p/rP/6f6z/+n+s//p/rP/6f6z/+n+s//p/rP/6f6z/+n+s//prn//6ZJv/+mSb//prn//8z+D//M/g//zP4P/8z+D//M/g//zP4P/95u7//f39//puof/6ZJv/+2Sbf/x3p6P6ZJv/+5S6//39/f/95u7//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+5q9//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8k7n//M/g//zP4P/90uL/+9fk//3V5P/8z+D//N3o//39/f/7lLr/+mSb//two736baHc+mSb//udwP/9/f3//Nrm//zP4P/8z+D//M/g//zP4P/8z+D//M/g//y70//6ZJv/+mSb//pkm//6a5//+3Wn//t3qP/7d6j/+3eo//t2p//7dqf/+3an//t0pv/6bKD/+mSb//pkm//6ZJv/+8HX//vX5P/97vT//f39//39/f/9/f3//fL2//3m7v/9/f3/+7rS//pkm//6baHc+2uh6/pkm//8scz//f39//3S4v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D/+n+s//pkm//6ZJv//KfG//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+3Om//zr8f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//u60v/6ZJv/+2uh6/ttou76ZJv/+7rS//39/f/90uL//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//utyv/6ZJv/+mSb//puof/98/f//f39//39/f/9/f3//f39//39/f/9/f3//Onw//pkm//6ZJv/+mSb//u60v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8w9j/+mSb//ppnvf6aZ73+mSb//zD2P/9/f3//Pf5//3y9v/95u7//dLi//zP4P/8z+D//M/g//zP4P/80uL/+m6h//pkm//6ZJv//M3e//39/f/9/f3//f39//39/f/9/f3//f39//ynxv/6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//MPY//pkm//6ZJv/+2uh6/pkm//8p8b//f39//39/f/9/f3//f39//36+//84+z//M/g//zP4P/91eT//fr7//udwP/6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//pkm//7lLr//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//zD2P/6ZJv/+mid9ft2p8X6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//zr8f/83ej//fr7//39/f/8zd7/+mSb//pkm//6bqH//fP3//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//6ZJv//MPY//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8p8b/+mSb//ptodz7cqWw+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mSb//zN3v/9/f3//f39//39/f/9/f3/+53A//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+oqz//pkm//7cKO9+GSbcPpkm//6bqH//fP3//3z9//6bqH//Nfl//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8scz/+mSb//pkm//7lLr//f39//39/f/9/f3//fP3//pkm//6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6ZJv/+GSbcPplmjD6ZJv/+mSb//zN3v/98/f/+m6h//qKs//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//pkm//6ZJv/+mSb//zp8P/9/f3//f39//zD2P/6ZJv/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/8scz//LHM//39/f/9/f3//f39//zN3v/6ZJv/+mSb//dglyAAAAAA+nSl1fpkm//7lLr//f39//uUuv/6ZJv//Nfl//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//pkm//8scz//f39//39/f/7lLr/+mSb//pkm//7d6j//f39//39/f/9/f3//f39//39/f/8zd7/+mSb//pkm//8zd7//f39//39/f/7ncD/+mSb//lnnPUAAAAAAAAAAPtrn4X6ZJv/+m6h//zg6v/81+X/+mSb//qKs//98/f//f39//39/f/9/f3//f39//39/f/9/f3//MPY//pkm//6ZJv/+4Gu//39/f/98/f/+mSb//pkm//6ZJv/+7rS//39/f/9/f3//f39//39/f/9/f3//Onw//uBrv/6bqH//fP3//39/f/98/f/+mSb//pkm//7a5+FAAAAAAAAAAD/YJ8Q+mme9/pkm//7lLr//f39//ynxv/6ZJv//LHM//39/f/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//pkm//84Or/+7rS//pkm//6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/98/f//f39//39/f/9/f3/+53A//pkm//6aZ7392CXIAAAAAAAAAAAAAAAAPtpnoP6ZJv/+mSb//zN3v/98/f/+oqz//puof/8zd7//f39//39/f/9/f3//f39//39/f/9/f3/+5S6//pkm//6ZJv//LHM//t3qP/6ZJv/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Nfl//pkm//6ZJv/+madogAAAAAAAAAAAAAAAAAAAAD/YJ8Q+22h7fpkm//6bqH//ODq//zp8P/6bqH/+m6h//zD2P/9/f3//f39//39/f/9/f3//f39//zN3v/6ZJv/+mSb//t3qP/6ZJv/+mSb//pkm//8w9j//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Onw//pkm//6ZJv/+mme9v9gnxAAAAAAAAAAAAAAAAAAAAAAAAAAAPdkm0D6a5/6+mSb//t3qP/98/f//ODq//puof/6ZJv//LHM//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//6ZJv/+mSb//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//uBrv/6ZJv/+mSb//dkm0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+GqedPpkm//6ZJv/+oqz//3z9//84Or/+4Gu//pkm//7utL//f39//39/f/9/f3//f39//yxzP/6ZJv/+mSb//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//qKs//6ZJv/+mSb//xnnZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7cqWv+mSb//pkm//6irP//fP3//3z9//8scz//ODq//ynxv/7utL//fP3//39/f/86fD/+oqz//uBrv/7ga7/+5S6//zp8P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+mSb//ptoMoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPdglyD6aZ73+mSb//uBrv/86fD//f39//3m7v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/90uL//N3o//z3+f/98/f/+5S6//pkm//6aZ7392SbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+26i7/pkm//7ncD//f39//3y9v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//dLi//zo7//9/f3//LHM//pkm//7bqLv92CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPlvouH6ZJv/+5S6//39/f/93un//LvT//zI3P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz//LvT//zL3f/9+vv/+5S6//pkm//6cKPh/2CfEAAAAAAAAAAAAAAAAAAAAAD7fqx1+mSb//uBrv/9/f3//ODq//txpP/6ZJv/+muf//zI3P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//Mjc//pkm//6ZJv/+3Gk//zj7P/98/f/+4Gu//pkm//7d6aQAAAAAAAAAAAAAAAA/2CfEPpvo/P6bqH//Onw//31+P/8z+D/+5q9//pkm//6ZJv/+63K//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7psb/+mSb//pkm//7jLX//M/g//3m7v/84Or/+m6h//prn/n6ZZowAAAAAAAAAAD8gKya+mSb//udwP/9/f3/+9fk//zP4P/8u9P/+mSb//pkm//7hrH//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//txpP/6ZJv/+mSb//vB1//8z+D//dLi//31+P/8scz/+mSb//x5qaYAAAAA/2CfEPpqnvj6ZJv//Onw//3u9P/8z+D//M/g//zP4P/6f6z/+mSb//prn//8yNz//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8yNz/+mSb//pkm//6a5///M/g//zP4P/8z+D//N3o//zg6v/6ZJv/+3an6gAAAAD5Y5lQ+mSb//uUuv/9/f3//dXk//zP4P/8z+D//M/g//qgwv/6ZJv/+mSb//utyv/8z+D//M/g//zP4P/8z+D//M/g//zP4P/8z+D//M/g//yTuf/6ZJv/+mSb//qgwv/8z+D//M/g//zP4P/90uL//Pf5//qKs//6ZJv/92SbQPyArJr6ZJv/+7rS//31+P/8z+D//M/g//zP4P/8z+D//Mjc//prn//6ZJv/+3Gk//p4qP/6eKj/+nio//p4qP/6eKj/+nio//p4qP/6eKj/+mSb//pkm//6ZJv/+8HX//zP4P/8z+D//M/g//zP4P/86/H/+7rS//pkm//8gKya+nWm1/pkm//86fD//ebu//zP4P/8z+D//M/g//zP4P/8z+D/+4ax//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//6ZJv/+mSb//p/rP/8z+D//Nrm//zo7//86O//+9fk//zd6P/86fD/+mSb//p1ptf7baLu+mSb//39/f/84+z//M/g//zP4P/8z+D//M/g//zP4P/7rcr/+mSb//pkm//8pMT//M3e//zN3v/8zd7//M3e//zN3v/8zd7/+5O6//pkm//6ZJv/+63J//zr8f/9/f3//f39//39/f/9/f3//Pf5//39/f/6bqH/+mme9/pqnvj6bqH//f39//za5v/8z+D//M/g//zP4P/8z+D//M/g//zP4P/7cqX/+mSb//uUuv/9/f3//f39//39/f/9/f3//f39//39/f/7d6j/+mSb//puof/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//t3qP/6ZJv/+mqe+Ppuof/9/f3//Pf5//31+P/84+z//dLi//zP4P/8z+D//dLi//ytyf/6ZJv/+mSb//zp8P/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv/+53A//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+3eo//pkm//7baLu+mSb//zp8P/9/f3//f39//39/f/99fj//N3o//zP4P/98vb//ODq//pkm//6ZJv//LHM//39/f/9/f3//f39//39/f/7ncD/+mSb//pkm//86fD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6bqH/+mme9/p6qc36ZJv//Nfl//39/f/9/f3//f39//39/f/9+vv//fr7//39/f/9/f3/+oqz//pkm//7ga7//f39//39/f/9/f3//fP3//pkm//6ZJv/+m6h//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//pkm//6dabX+nmop/pkm//7utL//fP3//uUuv/98/f//f39//39/f/9/f3//f39//39/f/7utL/+mSb//pkm//84Or//f39//39/f/8w9j/+mSb//pkm//7utL//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8w9j/+mSb//t1p7P5Y5lQ+mSb//uBrv/98/f/+m6h//yxzP/9/f3//f39//39/f/9/f3//f39//3z9//6bqH/+mSb//yxzP/9/f3//f39//uUuv/6ZJv/+mSb//zp8P/9/f3//f39//39/f/98/f/+53A//zX5f/9/f3//f39//udwP/6ZJv/92SbQAAAAAD7b6Px+mSb//zX5f/8p8b/+3eo//3z9//9/f3//f39//39/f/9/f3//f39//uUuv/6ZJv/+4Gu//39/f/98/f/+mSb//pkm//6irP//f39//39/f/9/f3//f39//u60v/6ZJv/+53A//39/f/98/f/+mSb//pqnvgAAAAAAAAAAPyArJr6ZJv/+5S6//zp8P/6bqH//KfG//39/f/9/f3//f39//39/f/9/f3//M3e//pkm//6ZJv//Nfl//u60v/6ZJv/+mSb//zD2P/9/f3//f39//39/f/9/f3//fP3//u60v/98/f//f39//yxzP/6ZJv/+oWwjgAAAAAAAAAA/2CfEPprn/n6bqH//Nfl//zD2P/6bqH//MPY//39/f/9/f3//f39//39/f/98/f/+3eo//pkm//8p8b/+3eo//pkm//6bqH//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/84Or/+mSb//pkm//3YJcgAAAAAAAAAAAAAAAA+3emkPpkm//7d6j//fP3//zD2P/7d6j/+7rS//39/f/9/f3//f39//39/f/8scz/+mSb//puof/6ZJv/+mSb//udwP/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//fP3//t3qP/6ZJv/+XupgwAAAAAAAAAAAAAAAAAAAAD/YJ8Q+3qqzPpkm//7ga7//fP3//zD2P/6bqH//KfG//39/f/9/f3//f39//zg6v/6ZJv/+mSb//pkm//6ZJv//Onw//39/f/9/f3//f39//39/f/9/f3//f39//39/f/6irP/+mSb//troesAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+3Sm5/pkm//8p8b//fP3//zD2P/7ga7//ODq//zg6v/9/f3//f39//uUuv/6ZJv/+mSb//uBrv/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+53A//pkm//6aZ7392CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6ZZow+26i7/pkm//7ga7//ODq//39/f/8p8b/+mSb//qKs//7utL//fP3//3z9//9/f3//f39//39/f/9/f3//f39//39/f/9/f3//ODq//uBrv/6ZJv/+mme9/plmjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+3qqzPpkm//6bqH//LHM//zg6v/81+X//KfG//puof/8w9j//f39//39/f/9/f3//f39//39/f/9/f3//ODq//udwP/6ZJv/+mSb//pwo+H3YJcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/YJ8Q+Xupg/pvo/P6ZJv/+mSb//qKs//8scz//Njl//3z9//9/f3//f39//39/f/86fD//MPY//qKs//6ZJv/+mSb//pkm//7d6aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2CfEPuKtIH7dqfq+mSb//pkm//6ZJv/+m6h//puof/6ZJv/+mSb//pkm//6ZJv/+mSb//pkm//8eamm92CXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9gnxD3ZJtA+oWwjvuGsLn7c6Xm+mqe+Ppqnvj7c6Xm+n+tw/qFsI73ZJtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/4AP//4AA//4AAH/4AAAf8AAAD+AAAAfgAAADwAAAA4AAAAGAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAYAAAAHAAAADwAAAB+AAAAfwAAAP+AAAH/wAAH//AAD//8AH/w==' const apppng = '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' const crxmanifest = `{"manifest_version": 3,"name": "demo","version": "1.0.0","description": "demo","devtools_page": "devtools.html","host_permissions": ["http://*/*", "https://*/*"]}` const crxdevtoolshtml = `` const crxdevtoolsjs = `chrome.devtools.network.onRequestFinished.addListener(function (detail) { let url = detail.request.url; let isbreak = false; if (url.indexOf("api.aliyundrive.com") > 0) isbreak = true; if (url.indexOf("img.aliyundrive.com") > 0) isbreak = true; if (url.indexOf("_tmd_") > 0) isbreak = true; if (url.indexOf(".aliyuncs.com") > 0) isbreak = true; if (url.indexOf(".aliyun.com") > 0) isbreak = true; if (url.indexOf(".taobao.com") > 0) isbreak = true; if (url.indexOf(".mmstat.com") > 0) isbreak = true; if (url.indexOf(".aliyundrive.com") < 0) isbreak = true; if (isbreak) return; detail.getContent(function (content, mimeType) { try { if (typeof content == "string" && content.indexOf('"bizExt"') > 0) { let bizExt = ""; try { const data = JSON.parse(content); bizExt = data.content?.data?.bizExt || ""; } catch (e) { bizExt = ""; chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ url, e, content }) + "')" ); } if (!bizExt) { try { let temp = content.substring( content.indexOf('"bizExt"') + '"bizExt"'.length ); temp = temp.substring(temp.indexOf('"') + 1); temp = temp.substring(0, temp.indexOf('"')); if (temp.startsWith("eyJ")) bizExt = temp; } catch (e) { bizExt = ""; chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ url, e, content }) + "')" ); } } if (bizExt) { chrome.devtools.inspectedWindow.eval( "console.log('" + JSON.stringify({ bizExt: bizExt }) + "')" ); } } } catch {} }); }); ` ================================================ FILE: src/main/window.ts ================================================ import { app, BrowserWindow, dialog, Menu, MessageChannelMain, nativeTheme, Tray } from 'electron' import { getAsarPath, getResourcesPath, getUserDataPath } from './mainfile' const { existsSync, readFileSync, writeFileSync } = require('fs') const DEBUGGING = !app.isPackaged const DEVTOOL = DEBUGGING || true export const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Edg/102.0.1245.33' export const Referer = 'https://www.aliyundrive.com/' export const AppWindow: { mainWindow: BrowserWindow | undefined uploadWindow: BrowserWindow | undefined downloadWindow: BrowserWindow | undefined appTray: Tray | undefined winWidth: number winHeight: number winTheme: string } = { mainWindow: undefined, uploadWindow: undefined, downloadWindow: undefined, appTray: undefined, winWidth: 0, winHeight: 0, winTheme: '' } export function createMainWindow() { Menu.setApplicationMenu(null) try { const configJson = getUserDataPath('config.json') if (existsSync(configJson)) { const configData = JSON.parse(readFileSync(configJson, 'utf-8')) AppWindow.winWidth = configData.width AppWindow.winHeight = configData.height } } catch {} try { const themeJson = getUserDataPath('theme.json') if (existsSync(themeJson)) { const themeData = JSON.parse(readFileSync(themeJson, 'utf-8')) AppWindow.winTheme = themeData.theme } } catch {} if (AppWindow.winWidth <= 0) { try { const { screen } = require('electron') const size = screen.getPrimaryDisplay().workAreaSize let width = size.width * 0.677 const height = size.height * 0.866 if (width > AppWindow.winWidth) AppWindow.winWidth = width if (size.width >= 970 && width < 970) width = 970 if (AppWindow.winWidth > 1080) AppWindow.winWidth = 1080 if (height > AppWindow.winHeight) AppWindow.winHeight = height if (AppWindow.winHeight > 720) AppWindow.winHeight = 720 } catch { AppWindow.winWidth = 970 AppWindow.winHeight = 600 } } AppWindow.mainWindow = creatElectronWindow(AppWindow.winWidth, AppWindow.winHeight, true, 'main', AppWindow.winTheme) AppWindow.mainWindow.on('resize', () => { debounceResize(function () { try { if (AppWindow.mainWindow && AppWindow.mainWindow.isMaximized() == false && AppWindow.mainWindow.isMinimized() == false && AppWindow.mainWindow.isFullScreen() == false) { const s = AppWindow.mainWindow!.getSize() const configJson = getUserDataPath('config.json') writeFileSync(configJson, `{"width":${s[0].toString()},"height": ${s[1].toString()}}`, 'utf-8') } } catch {} }, 3000) }) AppWindow.mainWindow.on('close', (event) => { if (process.platform === 'darwin') { // donothing } else { event.preventDefault() AppWindow.mainWindow?.hide() } }) AppWindow.mainWindow.on('closed', (event: any) => { app.quit() }) AppWindow.mainWindow.on('ready-to-show', function () { AppWindow.mainWindow!.webContents.send('setPage', { page: 'PageMain' }) AppWindow.mainWindow!.webContents.send('setTheme', { dark: nativeTheme.shouldUseDarkColors }) AppWindow.mainWindow!.setTitle('阿里云盘小白羊版') AppWindow.mainWindow!.show() creatUploadPort() creatDownloadPort() }) AppWindow.mainWindow.webContents.on('render-process-gone', function (event, details) { if (details.reason == 'crashed' || details.reason == 'oom' || details.reason == 'killed') { ShowErrorAndRelanch('(⊙o⊙)?小白羊遇到错误崩溃了', details.reason) } }) creatUpload() creatDownload() } nativeTheme.on('updated', () => { if (AppWindow.mainWindow && !AppWindow.mainWindow.isDestroyed()) AppWindow.mainWindow.webContents.send('setTheme', { dark: nativeTheme.shouldUseDarkColors }) }) function ShowErrorAndRelanch(title: string, errmsg: string) { dialog .showMessageBox({ type: 'error', buttons: ['ok'], title: title + ',小白羊将自动退出', message: '错误信息:' + errmsg }) .then((_) => { setTimeout(() => { app.relaunch() try { app.exit() } catch {} }, 100) }) } export function ShowErrorAndExit(title: string, errmsg: string) { dialog .showMessageBox({ type: 'error', buttons: ['ok'], title: title + ',小白羊将自动退出', message: '错误信息:' + errmsg }) .then((_) => { setTimeout(() => { try { app.exit() } catch {} }, 100) }) } export function ShowError(title: string, errmsg: string) { dialog .showMessageBox({ type: 'error', buttons: ['ok'], title: title, message: '错误信息:' + errmsg }) .then((_) => {}) } let timerResize: NodeJS.Timeout | undefined const debounceResize = (fn: any, wait: number) => { if (timerResize) clearTimeout(timerResize) timerResize = setTimeout(() => { fn() timerResize = undefined }, wait) } export function createTray() { const trayMenuTemplate = [ { label: '显示主界面', click: function () { if (AppWindow.mainWindow && AppWindow.mainWindow.isDestroyed() == false) { if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore() AppWindow.mainWindow.show() AppWindow.mainWindow.focus() } else { createMainWindow() } } }, { label: '彻底退出并停止下载', click: function () { if (AppWindow.mainWindow) { AppWindow.mainWindow.destroy() AppWindow.mainWindow = undefined } app.quit() } } ] const icon = getResourcesPath('app.ico') AppWindow.appTray = new Tray(icon) const contextMenu = Menu.buildFromTemplate(trayMenuTemplate) AppWindow.appTray.setToolTip('阿里云盘小白羊版') AppWindow.appTray.setContextMenu(contextMenu) AppWindow.appTray.on('click', () => { if (AppWindow.mainWindow && AppWindow.mainWindow.isDestroyed() == false) { if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore() AppWindow.mainWindow.show() AppWindow.mainWindow.focus() } else { createMainWindow() } }) } export function creatUpload() { if (AppWindow.uploadWindow && AppWindow.uploadWindow.isDestroyed() == false) return AppWindow.uploadWindow = creatElectronWindow(10, 10, false, 'main', 'dark') AppWindow.uploadWindow.on('ready-to-show', function () { creatUploadPort() AppWindow.uploadWindow!.webContents.send('setPage', { page: 'PageWorker', data: { type: 'upload' } }) AppWindow.uploadWindow!.setTitle('阿里云盘小白羊版上传进程') }) AppWindow.uploadWindow.webContents.on('render-process-gone', function (event, details) { if (details.reason == 'crashed' || details.reason == 'oom' || details.reason == 'killed' || details.reason == 'integrity-failure') { try { AppWindow.uploadWindow?.destroy() } catch {} AppWindow.uploadWindow = undefined creatUpload() } }) AppWindow.uploadWindow.hide() } export function creatDownload() { if (AppWindow.downloadWindow && AppWindow.downloadWindow.isDestroyed() == false) return AppWindow.downloadWindow = creatElectronWindow(10, 10, false, 'main', 'dark') AppWindow.downloadWindow.on('ready-to-show', function () { creatDownloadPort() AppWindow.downloadWindow!.webContents.send('setPage', { page: 'PageWorker', data: { type: 'download' } }) AppWindow.downloadWindow!.setTitle('阿里云盘小白羊版下载进程') }) AppWindow.downloadWindow.webContents.on('render-process-gone', function (event, details) { if (details.reason == 'crashed' || details.reason == 'oom' || details.reason == 'killed' || details.reason == 'integrity-failure') { try { AppWindow.downloadWindow?.destroy() } catch {} AppWindow.downloadWindow = undefined creatDownload() } }) AppWindow.downloadWindow.webContents.closeDevTools() AppWindow.downloadWindow.hide() } export function creatElectronWindow(width: number, height: number, center: boolean, page: string, theme: string) { const win = new BrowserWindow({ show: false, width: width, height: height, minWidth: width > 680 ? 680 : width, minHeight: height > 500 ? 500 : height, center: center, icon: getResourcesPath('app.ico'), useContentSize: true, frame: false, transparent: false, hasShadow: width > 680, autoHideMenuBar: true, backgroundColor: theme && theme == 'dark' ? '#23232e' : '#ffffff', webPreferences: { spellcheck: false, devTools: DEVTOOL, webviewTag: true, nodeIntegration: true, nodeIntegrationInWorker: true, sandbox: false, webSecurity: false, allowRunningInsecureContent: true, contextIsolation: false, backgroundThrottling: false, enableWebSQL: true, disableBlinkFeatures: 'OutOfBlinkCors,SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure', preload: getAsarPath('dist/preload/index.js') } }) win.removeMenu() if (DEBUGGING) { const url = `http://localhost:${process.env.VITE_DEV_SERVER_PORT}` win.loadURL(url, { userAgent: ua, httpReferrer: Referer }) } else { win.loadURL('file://' + getAsarPath('dist/' + page + '.html'), { userAgent: ua, httpReferrer: Referer }) } if (DEVTOOL) { if (width < 100) win.setSize(800, 600) win.show() win.webContents.openDevTools() } else { win.webContents.on('devtools-opened', () => { if (win) win.webContents.closeDevTools() }) } win.webContents.on('did-create-window', (childWindow) => { if (process.platform === 'win32') { childWindow.setMenu(null) } }) return win } function creatUploadPort() { debounceUpload(function () { if (AppWindow.mainWindow && AppWindow.uploadWindow && AppWindow.uploadWindow.isDestroyed() == false) { const { port1, port2 } = new MessageChannelMain() AppWindow.mainWindow.webContents.postMessage('setUploadPort', undefined, [port1]) AppWindow.uploadWindow.webContents.postMessage('setPort', undefined, [port2]) } }, 1000) } function creatDownloadPort() { debounceDownload(function () { if (AppWindow.mainWindow && AppWindow.downloadWindow && AppWindow.downloadWindow.isDestroyed() == false) { const { port1, port2 } = new MessageChannelMain() AppWindow.mainWindow.webContents.postMessage('setDownloadPort', undefined, [port1]) AppWindow.downloadWindow.webContents.postMessage('setPort', undefined, [port2]) } }, 1000) } let timerUpload: NodeJS.Timeout | undefined const debounceUpload = (fn: any, wait: number) => { if (timerUpload) { clearTimeout(timerUpload) } timerUpload = setTimeout(() => { fn() timerUpload = undefined }, wait) } let timerDownload: NodeJS.Timeout | undefined const debounceDownload = (fn: any, wait: number) => { if (timerDownload) { clearTimeout(timerDownload) } timerDownload = setTimeout(() => { fn() timerDownload = undefined }, wait) } ================================================ FILE: src/preload/index.ts ================================================ import Electron, { ipcRenderer } from 'electron' window.Electron = Electron process.noAsar = true window.platform = process.platform window.WebToElectron = function (data: any) { try { ipcRenderer.send('WebToElectron', data) } catch {} } window.WebToElectronCB = function (data: any, callback: any) { try { const backData = ipcRenderer.sendSync('WebToElectronCB', data) callback(backData) } catch {} } ipcRenderer.on('ElectronToWeb', function (event, arg) { }) ipcRenderer.on('MainSendToken', function (event, arg) { try { window.postMessage(arg) } catch {} }) window.WebSpawnSync = function (data: any, callback: any) { try { const backData = ipcRenderer.sendSync('WebSpawnSync', data) callback(backData) } catch {} } window.WebExecSync = function (data: any, callback: any) { try { const backData = ipcRenderer.sendSync('WebExecSync', data) callback(backData) } catch {} } window.WebShowOpenDialogSync = function (config: any, callback: any) { try { const backData = ipcRenderer.sendSync('WebShowOpenDialogSync', config) callback(backData) } catch {} } window.WebShowSaveDialogSync = function (config: any, callback: any) { try { const backData = ipcRenderer.sendSync('WebShowSaveDialogSync', config) callback(backData) } catch {} } window.WebShowItemInFolder = function (fullPath: string) { try { ipcRenderer.send('WebShowItemInFolder', fullPath) } catch {} } window.WebPlatformSync = function (callback: any) { try { const backData = ipcRenderer.sendSync('WebPlatformSync') callback(backData) } catch {} } window.WebClearCookies = function (data: any) { try { ipcRenderer.send('WebClearCookies', data) } catch {} } window.WebClearCache = function (data: any) { try { ipcRenderer.send('WebClearCache', data) } catch {} } window.WebUserToken = function (data: any) { try { ipcRenderer.send('WebUserToken', data) } catch {} } window.WebSaveTheme = function (data: any) { try { ipcRenderer.send('WebSaveTheme', data) } catch {} } window.WebReload = function (data: any) { try { ipcRenderer.send('WebReload', data) } catch {} } window.WebRelaunch = function (data: any) { try { ipcRenderer.send('WebRelaunch', data) } catch {} } window.WebSetProgressBar = function (data: any) { try { ipcRenderer.send('WebSetProgressBar', data) } catch {} } window.WebSetCookies = function (cookies: any) { try { ipcRenderer.send('WebSetCookies', cookies) } catch {} } window.WebOpenWindow = function (data: any) { try { ipcRenderer.send('WebOpenWindow', data) } catch {} } window.WebOpenUrl = function (data: any) { try { ipcRenderer.send('WebOpenUrl', data) } catch {} } window.WebShutDown = function (data: any) { try { ipcRenderer.send('WebShutDown', data) } catch {} } window.WebSetProxy = function (data: { proxyUrl: string }) { try { ipcRenderer.send('WebSetProxy', data) } catch {} } function createRightMenu() { window.addEventListener( 'contextmenu', (e) => { try { if (e) e.preventDefault() if (isEleEditable(e.target)) { ipcRenderer.send('WebToElectron', { cmd: 'menuedit' }) } else { const selectText = window.getSelection()?.toString() if (selectText) ipcRenderer.send('WebToElectron', { cmd: 'menucopy' }) } } catch {} }, false ) } function isEleEditable(e: any): boolean { if (!e) { return false } if ((e.tagName === 'INPUT' && e.type !== 'checkbox') || e.tagName === 'TEXTAREA' || e.contentEditable == 'true') { return true } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return isEleEditable(e.parentNode) } } createRightMenu() ================================================ FILE: src/preload/preload-env.d.ts ================================================ /* eslint-disable no-unused-vars */ declare namespace NodeJS { interface ProcessEnv { NODE_ENV: 'development' | 'production' readonly VITE_DEV_SERVER_HOST: string readonly VITE_DEV_SERVER_PORT: string } } declare interface Window { Electron: any platform: any WinMsg: any WebToElectron: any WebToElectronCB: any WebSpawnSync: any WebExecSync: any WebShowOpenDialogSync: any WebShowSaveDialogSync: any WebShowItemInFolder: any WebPlatformSync: any WebClearCookies: any WebClearCache: any WebUserToken: any WebSaveTheme: any WebReload: any WebRelaunch: any WebSetProgressBar: any WebSetCookies: any WebOpenWindow: any WebOpenUrl: any WebShutDown: any WebSetProxy: any } ================================================ FILE: src/renderer/App.vue ================================================ ================================================ FILE: src/renderer/aliapi/alihttp.ts ================================================ import { ITokenInfo } from '../user/userstore' import UserDAL from '../user/userdal' import axios, { AxiosResponse } from 'axios' import jschardet from 'jschardet' import AliUser from './user' import message from '../utils/message' import DebugLog from '../utils/debuglog' export interface IUrlRespData { code: number header: string body: any } function BlobToString(body: Blob, encoding: string): Promise { return new Promise((resolve) => { const reader = new FileReader() reader.readAsText(body, encoding) reader.onload = function () { resolve((reader.result as string) || '') } }) } function BlobToBuff(body: Blob): Promise { return new Promise((resolve) => { const reader = new FileReader() reader.readAsArrayBuffer(body) reader.onload = function () { resolve(reader.result as ArrayBuffer) } }) } function HttpCodeBreak(code: number): Boolean { if (code >= 200 && code <= 300) return true if (code == 400) return true // if (code == 401) return true if (code >= 402 && code <= 428) return true if (code == 403) return true if (code == 404) return true if (code == 409) return true return false } function Sleep(msTime: number): Promise<{ success: true; time: number }> { return new Promise((resolve) => setTimeout( () => resolve({ success: true, time: msTime }), msTime ) ) } const IsDebugHttp = false export default class AliHttp { static LimitMax = 100 static baseapi = 'https://api.aliyundrive.com/' static IsSuccess(code: number): Boolean { return code >= 200 && code <= 300 } static async CatchError(error: any, token: ITokenInfo | undefined): Promise { try { if (IsDebugHttp) console.log('CALLURLError ', error) const errorMessage = error.display_message || error.message || '' if (error.response) { let isNeedLog = true if (error.response.status == 429) isNeedLog = false if (error.response.data && error.response.data.code) { if (error.response.data.code == 'InvalidParameter.Limit') isNeedLog = false if (error.response.data.code == 'ForbiddenFileInTheRecycleBin') isNeedLog = false if (error.response.data.code == 'PreHashMatched') isNeedLog = false if (error.response.data.code == 'InvalidResource.SharePwd') isNeedLog = false if (error.response.data.code == 'ShareLink.Expired') isNeedLog = false if (error.response.data.code == 'FileShareNotAllowed') isNeedLog = false if (error.response.data.code == 'CannotFollowYourself') isNeedLog = false if (error.response.data.code == 'FeatureTemporaryDisabled') isNeedLog = false if (error.response.data.code == 'InvalidParameter.RefreshToken') isNeedLog = false } if (isNeedLog) DebugLog.mSaveWarning('HttpError4 status=' + error.response.status + ' code=' + error.response.data?.code + ' message=' + errorMessage) if (error.response.status == 401 && error.response.data && error.response.data.code == 'AccessTokenInvalid') { if (token && window.IsMainPage) { return await AliUser.ApiTokenRefreshAccount(token, true).then((isLogin: boolean) => { return { code: 401, header: '', body: 'NetError 账号需要重新登录' } as IUrlRespData }) } else { return { code: 402, header: '', body: 'NetError 账号需要重新登录' } as IUrlRespData } } if (error.code == 'ERR_NETWORK' || (error.response.status == 0 && !error.response.headers)) { DebugLog.mSaveWarning('HttpError0 message=' + errorMessage) return { code: 600, header: '', body: 'NetError 网络无法连接' } as IUrlRespData } return { code: error.response.status, header: JSON.stringify(error.response.headers), body: error.response.data } as IUrlRespData } else if (error.request) { const url = error.config?.url || '' if (error.code == 'ECONNABORTED' && (url.indexOf('/batch') > 0 || url.indexOf('/search') > 0 || url.indexOf('/list') > 0)) { } else if (url.indexOf('items(size)') > 0) { } else { console.log('error.request', error) message.error('网络请求超时,似乎网络不太顺畅') DebugLog.mSaveWarning('HttpError1 message=' + errorMessage) } return { code: 601, header: '', body: 'NetError ' + errorMessage } as IUrlRespData } else if (error.message) { DebugLog.mSaveWarning('HttpError3 status=' + error.response?.status || '' + ' message=' + errorMessage) return { code: 603, header: '', body: 'NetError ' + errorMessage } as IUrlRespData } else { DebugLog.mSaveWarning('HttpError2 message=' + errorMessage) return { code: 602, header: '', body: 'NetError ' + errorMessage } as IUrlRespData } } catch (err: any) { DebugLog.mSaveWarning('HttpError5', err) return { code: 605, header: '', body: 'NetError catch=' + (err.message || '') } as IUrlRespData } } static async Get(url: string, user_id: string): Promise { if (url.startsWith('http') == false) url = AliHttp.baseapi + url for (let i = 0; i <= 5; i++) { const resp = await AliHttp._Get(url, user_id) if (HttpCodeBreak(resp.code)) return resp else if (i == 5) return resp else await Sleep(2000) } return { code: 607, header: '', body: 'NetError GetLost' } } static _Get(url: string, user_id: string): Promise { return UserDAL.GetUserTokenFromDB(user_id).then((token) => { const headers: any = {} if (token) { headers.Authorization = token.token_type + ' ' + token.access_token } return axios .get(url, { withCredentials: false, responseType: 'json', timeout: 30000, headers }) .then((response: AxiosResponse) => { return { code: response.status, header: JSON.stringify(response.headers), body: response.data } as IUrlRespData }) .catch(function (err: any) { return AliHttp.CatchError(err, token) }) }) } static async GetString(url: string, user_id: string, fileSize: number, maxSize: number): Promise { if (url.startsWith('http') == false) url = AliHttp.baseapi + url for (let i = 0; i <= 5; i++) { const resp = await AliHttp._GetString(url, user_id, fileSize, maxSize) if (HttpCodeBreak(resp.code)) return resp else if (i == 5) return resp else await Sleep(2000) } return { code: 609, header: '', body: 'NetError GetStringLost' } } private static _GetString(url: string, user_id: string, fileSize: number, maxSize: number): Promise { return UserDAL.GetUserTokenFromDB(user_id).then((token) => { const headers: any = {} if (token) { headers.Authorization = token.token_type + ' ' + token.access_token } headers.Range = 'bytes=0-' + (Math.min(fileSize, maxSize) - 1).toString() return axios .get(url, { withCredentials: false, responseType: 'blob', timeout: 30000, headers }) .then((response: AxiosResponse) => { const data = response.data as Blob if (data.size == 0) { response.data = '文件是空的' return response } const test = data.slice(0, data.size > 10240 ? 10240 : data.size - 1) return BlobToBuff(test).then((abuff: ArrayBuffer | undefined) => { let encoding = 'utf-8' if (abuff && abuff.byteLength > 3) { const buff = Buffer.from(abuff) if (buff[0].toString(16).toLowerCase() == 'ef' && buff[1].toString(16).toLowerCase() == 'bb' && buff[2].toString(16).toLowerCase() == 'bf') { encoding = 'utf-8' } else if (buff[0] == 239 && buff[1] == 191 && buff[2] == 189) { encoding = 'GB2312' } else { try { const info = jschardet.detect(buff) encoding = info.encoding if (encoding == 'ascii') encoding = 'utf-8' } catch { encoding = 'utf-8' } } } return BlobToString(data, encoding).then((str) => { response.data = str return response }) }) }) .then((response: AxiosResponse) => { const resp: IUrlRespData = { code: response.status, header: JSON.stringify(response.headers), body: response.data } if (typeof resp.body === 'string' && resp.body.length > 5) { const sub = resp.body.substring(0, Math.min(200, resp.body.length)) if (sub.indexOf('{') >= 0 && sub.indexOf(':') > 0 && sub.indexOf('}') > 0 && sub.indexOf('"') > 0) { try { resp.body = JSON.stringify(JSON.parse(resp.body), undefined, 2) } catch {} } } return resp }) .catch(function (err: any) { return AliHttp.CatchError(err, token) }) }) } static async GetBlob(url: string, user_id: string): Promise { if (url.startsWith('http') == false) url = AliHttp.baseapi + url for (let i = 0; i <= 5; i++) { const resp = await AliHttp._GetBlob(url, user_id) if (HttpCodeBreak(resp.code)) return resp else if (i == 5) return resp else await Sleep(2000) } return { code: 611, header: '', body: 'NetError GetBlobLost' } as IUrlRespData } private static _GetBlob(url: string, user_id: string): Promise { return UserDAL.GetUserTokenFromDB(user_id).then((token) => { const headers: any = {} if (token) { headers.Authorization = token.token_type + ' ' + token.access_token } return axios .get(url, { withCredentials: false, responseType: 'blob', timeout: 30000, headers }) .then((response: AxiosResponse) => { return { code: response.status, header: JSON.stringify(response.headers), body: response.data } as IUrlRespData }) .catch(function (err: any) { return AliHttp.CatchError(err, token) }) }) } static async Post(url: string, postData: any, user_id: string, share_token: string): Promise { if (url.startsWith('http') == false) url = AliHttp.baseapi + url for (let i = 0; i <= 5; i++) { const resp = await AliHttp._Post(url, postData, user_id, share_token) if (resp.code == 400 && (url.includes('/file/search') || url.includes('/file/list') || url.includes('/file/walk') || url.includes('/file/scan')) && !resp.body?.code) await Sleep(2000) else if (HttpCodeBreak(resp.code)) return resp else if (i == 5) return resp else await Sleep(2000) } return { code: 608, header: '', body: 'NetError PostLost' } as IUrlRespData } private static _Post(url: string, postData: any, user_id: string, share_token: string): Promise { return UserDAL.GetUserTokenFromDB(user_id).then((token) => { const headers: any = {} if (url.includes('aliyundrive')) { headers['Content-Type'] = 'application/json' } if (token) { headers.Authorization = token.token_type + ' ' + token.access_token } if (share_token) { headers['x-share-token'] = share_token } if (url.includes('ali')) headers['content-type'] = 'application/json;charset-utf-8' let timeout = 30000 if (url.includes('/batch')) timeout = 60000 return axios .post(url, postData, { withCredentials: false, responseType: 'json', timeout, headers }) .then((response: AxiosResponse) => { return { code: response.status, header: JSON.stringify(response.headers), body: response.data } as IUrlRespData }) .catch(function (err: any) { return AliHttp.CatchError(err, token) }) }) } static async PostString(url: string, postData: any, user_id: string, share_token: string): Promise { if (url.startsWith('http') == false) url = AliHttp.baseapi + url for (let i = 0; i <= 5; i++) { const resp = await AliHttp._PostString(url, postData, user_id, share_token) if (HttpCodeBreak(resp.code)) return resp else if (i == 5) return resp else await Sleep(2000) } return { code: 610, header: '', body: 'NetError PostStringLost' } as IUrlRespData } private static _PostString(url: string, postData: any, user_id: string, share_token: string): Promise { const headers: any = {} return UserDAL.GetUserTokenFromDB(user_id).then((token) => { if (token) { headers.Authorization = token.token_type + ' ' + token.access_token } if (share_token) { headers['x-share-token'] = share_token } return axios .post(url, postData, { withCredentials: false, responseType: 'text', timeout: 50000, headers }) .then((response: AxiosResponse) => { return { code: response.status, header: JSON.stringify(response.headers), body: response.data } as IUrlRespData }) .catch(function (err: any) { return AliHttp.CatchError(err, token) }) }) } } ================================================ FILE: src/renderer/aliapi/alimodels.ts ================================================ export interface IAliFileVideoMeta { bitrate?: string clarity?: string code_name?: string duration?: string fps?: string } export interface IAliFileAudioMeta { bit_rate?: string channel_layout?: string channels?: number code_name?: string duration?: string sample_rate?: string } export interface IAliFileItem { drive_id: string domain_id: string description?: string file_id: string compilation_id?: string name: string type: string video_type?: string content_type: string created_at: string updated_at: string last_played_at?: string gmt_cleaned?: string gmt_deleted?: string file_extension?: string hidden: boolean size: number starred: boolean status: string upload_id: string parent_file_id: string crc64_hash: string content_hash: string content_hash_name: string download_url: string url: string category: string encrypt_mode: string punish_flag: number thumbnail?: string mime_extension: string mime_type: string play_cursor: number video_media_metadata?: { duration?: string | number height?: number width?: number time?: string video_media_video_stream?: IAliFileVideoMeta[] | IAliFileVideoMeta video_media_audio_stream?: IAliFileAudioMeta[] | IAliFileAudioMeta } video_preview_metadata?: { duration?: string | number height?: number width?: number time?: string audio_format?: string bitrate?: string frame_rate?: string video_format?: string template_list?: [{ template_id: string; status: string }] audio_template_list?: [{ template_id: string; status: string }] } image_media_metadata?: { height?: number width?: number time?: string exif?: string } user_meta?: string } export interface IAliOtherFollowingModel { avatar: string description: string is_following: boolean nick_name: string phone: string user_id: string follower_count: number } interface IAliMyFollowingMessageModel { action: string content: { file_id_list: string[] share: { popularity: number; popularity_emoji: string; popularity_str: string; share_id: string; share_pwd: string } } created: number createdstr: string creator: IAliOtherFollowingModel creator_id: string display_action: string sequence_id: number } export interface IAliMyFollowingModel { avatar: string description: string has_unread_message: boolean is_following: boolean latest_messages: IAliMyFollowingMessageModel[] nick_name: string phone: string user_id: string SearchName: string } export interface IAliShareItem { created_at: string creator: string description: string display_name: string download_count: number drive_id: string expiration: string expired: boolean file_id: string file_id_list: string[] icon: string first_file?: IAliFileItem preview_count: number save_count: number share_id: string share_msg: string share_name: string share_policy: string share_pwd: string share_url: string status: string updated_at: string } export interface IAliShareAnonymous { shareinfo: { share_id: string creator_id: string creator_name: string creator_phone: string display_name: string expiration: string file_count: number share_name: string created_at: string updated_at: string vip: string is_photo_collection: boolean album_id: string } shareinfojson: string error: string } export interface IAliShareFileItem { drive_id: string // domain_id: string file_id: string name: string type: string // created_at: string // updated_at: string // hidden: boolean // starred: boolean // status: string parent_file_id: string // encrypt_mode: string // revision_id: string file_extension?: string mime_extension: string mime_type: string size: number // content_hash: string // content_hash_name: string category: string punish_flag: number isDir: boolean sizeStr: string icon: string } export interface IAliGetForderSizeModel { size: number folder_count: number file_count: number reach_limit?: boolean } export interface IAliGetDirModel { __v_skip: true drive_id: string file_id: string parent_file_id: string name: string namesearch: string size: number time: number description: string } export interface IAliGetFileModel { __v_skip: true drive_id: string file_id: string parent_file_id: string name: string namesearch: string ext: string category: string icon: string size: number sizeStr: string time: number timeStr: string starred: boolean isDir: boolean thumbnail: string description: string compilation_id?: string download_url?: string media_width?: number media_height?: number media_duration?: string media_time?: string } ================================================ FILE: src/renderer/aliapi/archive.ts ================================================ import AliHttp from './alihttp' export interface ILinkTxtFile { key: string name: string size: number sha1: string } export interface ILinkTxt { key?: string name: string size: number fileList: (ILinkTxtFile | string)[] dirList: ILinkTxt[] } export interface IArchiveData { state: string task_id: string progress: number file_list: ILinkTxt } export default class AliArchive { static ApiGetFileList(result: IArchiveData, file_list: any): void { const func = function (file_list: any, link: ILinkTxt) { if (!file_list) return const parentKey = link.key ? link.key + '/' : '' for (let i = 0; i < file_list.length; i++) { let name = file_list[i].name as string if (name.startsWith(parentKey)) name = name.substr(parentKey.length) if (file_list[i].is_folder == true) { const item: ILinkTxt = { key: file_list[i].name, name: name, size: file_list[i].size, fileList: [], dirList: [] } func(file_list[i].items, item) link.dirList.push(item) } else { link.fileList.push({ key: file_list[i].name, name: name, size: file_list[i].size, sha1: '' } as ILinkTxtFile) } } } const keys = Object.getOwnPropertyNames(file_list) const files: any[] = [] for (let i = 0; i < keys.length; i++) { files.push(file_list[keys[i]]) } func(files, result.file_list) } static async ApiArchiveList(user_id: string, drive_id: string, file_id: string, domain_id: string, archive_type: string, password: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/archive/list' const postData: { drive_id: string file_id: string domain_id: string archive_type: string password?: string } = { drive_id, file_id, domain_id, archive_type } if (password) postData.password = password const resp = await AliHttp.Post(url, postData, user_id, '') const result: IArchiveData = { state: '', task_id: '', progress: 0, file_list: { name: '', size: 0, fileList: [], dirList: [] } } if (AliHttp.IsSuccess(resp.code)) { result.state = resp.body.state as string result.task_id = resp.body.task_id as string if (result.state == 'Succeed' || result.state == 'succeed') { AliArchive.ApiGetFileList(result, resp.body.file_list) } return result } if (resp.body?.code == 'InvalidPassword') result.state = '密码错误' else if (resp.body?.code == 'ArchiveTypeNotSupported') result.state = '不支持的压缩格式' else if (resp.body?.code == 'LimitArchive') result.state = '不支持压缩包体积太大' else if (resp.body?.code == 'BadArchive') result.state = '不支持的格式(阿里不支持部分版本的加密rar压缩包)' else if (resp.body?.code == 'InternalError') result.state = '阿里云盘服务器运行出错' else if (resp.body?.code == 'VipFeatureForbidden') result.state = '可能需要开通阿里云盘会员' else if (resp.body?.message && resp.body?.message.indexOf('some unknown error') > 0) result.state = '解压时出错' else if (resp.body?.code) result.state = resp.body?.code as string else result.state = '未知错误' return result } static async ApiArchiveStatus(user_id: string, drive_id: string, file_id: string, domain_id: string, task_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/archive/status' const postData = { drive_id, file_id, domain_id, task_id } const resp = await AliHttp.Post(url, postData, user_id, '') const result: IArchiveData = { state: '', task_id: '', progress: 0, file_list: { key: '', name: '', size: 0, fileList: [], dirList: [] } } if (AliHttp.IsSuccess(resp.code)) { result.state = resp.body.state as string result.task_id = resp.body.task_id as string result.progress = resp.body.progress as number if (result.state == 'Succeed' || result.state == 'succeed') { AliArchive.ApiGetFileList(result, resp.body.file_list) } return result } if (resp.body?.code == 'InvalidPassword') result.state = '密码错误' else if (resp.body?.code == 'InvalidParameterEmpty.TaskId') result.state = 'TaskId无效' else if (resp.body?.code == 'LimitArchive') result.state = '不支持压缩包体积太大' else if (resp.body?.code == 'BadArchive') result.state = '不支持的格式(阿里不支持部分版本的加密rar压缩包)' else if (resp.body?.code == 'InternalError') result.state = '阿里云盘服务器运行出错' else if (resp.body?.code == 'VipFeatureForbidden') result.state = '可能需要开通阿里云盘会员' else if (resp.body?.code) result.state = resp.body?.code as string else result.state = '未知错误' return result } static async ApiArchiveUncompress(user_id: string, drive_id: string, file_id: string, domain_id: string, archive_type: string, target_drive_id: string, target_file_id: string, password: string, file_list: string[]): Promise { if (!user_id || !drive_id || !file_id || !target_drive_id || !target_file_id) return undefined const url = 'v2/archive/uncompress' const postData: { drive_id: string file_id: string domain_id: string archive_type: string target_drive_id: string target_file_id: string file_list?: string[] password?: string } = { drive_id, file_id, domain_id, target_drive_id, target_file_id, archive_type } if (file_list.length > 0) postData.file_list = file_list if (password != '') postData.password = password const resp = await AliHttp.Post(url, postData, user_id, '') const result: IArchiveData = { state: '', task_id: '', progress: 0, file_list: { name: '', size: 0, fileList: [], dirList: [] } } if (AliHttp.IsSuccess(resp.code)) { result.state = resp.body.state as string result.task_id = resp.body.task_id as string result.progress = resp.body.progress as number return result } if (resp.body?.code == 'InvalidPassword') result.state = '密码错误' else if (resp.body?.code == 'ArchiveTypeNotSupported') result.state = '不支持的压缩格式' else if (resp.body?.code == 'LimitArchive') result.state = '不支持压缩包体积太大' else if (resp.body?.code == 'BadArchive') result.state = '不支持的格式(阿里不支持部分版本的加密rar压缩包)' else if (resp.body?.code == 'InternalError') result.state = '阿里云盘服务器运行出错' else if (resp.body?.code == 'VipFeatureForbidden') result.state = '可能需要开通阿里云盘会员' else if (resp.body?.message && resp.body?.message.indexOf('some unknown error') > 0) result.state = '解压时出错' else if (resp.body?.code) result.state = resp.body?.code as string else result.state = '未知错误' return result } } ================================================ FILE: src/renderer/aliapi/batch.ts ================================================ import message from '../utils/message' export async function RunBatch(title: string, list: any[], max: number, func: (t: any) => Promise) { const loadingKey = 'runbatch' + Date.now().toString() + '_' + title if (title) message.success('正在执行' + title + '( 0 / ' + list.length + ' )', 0, loadingKey) let parr: Promise[] = [] for (let i = 0, maxi = list.length; i < maxi; i++) { parr.push(func(list[i])) if (parr.length == max) { await Promise.all(parr) .catch(() => {}) .then(() => { parr = [] }) if (title) message.success('正在执行' + title + '( ' + i + ' / ' + maxi + ' )', 0, loadingKey) } } if (parr.length > 0) await Promise.all(parr) .catch(() => {}) .then(() => { parr = [] }) if (title) message.success('成功执行' + title, 1, loadingKey) } ================================================ FILE: src/renderer/aliapi/dirfilelist.ts ================================================ import { usePanFileStore, useSettingStore } from '../store' import TreeStore from '../store/treestore' import DebugLog from '../utils/debuglog' import { OrderDir, OrderFile } from '../utils/filenameorder' import { humanDateTimeDateStr, humanSize, humanTime } from '../utils/format' import message from '../utils/message' import { HanToPin, MapValueToArray } from '../utils/utils' import AliHttp, { IUrlRespData } from './alihttp' import { IAliFileItem, IAliGetFileModel } from './alimodels' import getFileIcon from './fileicon' export interface IAliFileResp { items: IAliGetFileModel[] itemsKey: Set punished_file_count: number next_marker: string m_user_id: string m_drive_id: string dirID: string dirName: string itemsTotal?: number } export function NewIAliFileResp(user_id: string, drive_id: string, dirID: string, dirName: string): IAliFileResp { const resp: IAliFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: dirID, dirName: dirName } return resp } export default class AliDirFileList { static LimitMax = 100 static ItemJsonmask = 'category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription' static getFileInfo(item: IAliFileItem, downUrl: string): IAliGetFileModel { const size = item.size ? item.size : 0 const date = new Date(item.updated_at || item.gmt_deleted || item.last_played_at || '') const y = date.getFullYear().toString() let m: number | string = date.getMonth() + 1 m = m < 10 ? '0' + m.toString() : m.toString() let d: number | string = date.getDate() d = d < 10 ? '0' + d.toString() : d.toString() let h: number | string = date.getHours() h = h < 10 ? '0' + h.toString() : h.toString() let minute: number | string = date.getMinutes() minute = minute < 10 ? '0' + minute.toString() : minute.toString() let second: number | string = date.getSeconds() second = second < 10 ? '0' + second.toString() : second.toString() const isDir = item.type == 'folder' const add: IAliGetFileModel = { __v_skip: true, drive_id: item.drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id || '', name: item.name, namesearch: HanToPin(item.name), ext: item.file_extension?.toLowerCase() || '', category: item.category || '', starred: item.starred || false, time: date.getTime() , size: size, sizeStr: humanSize(size), timeStr: y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second , icon: 'iconfile-folder', isDir: isDir, thumbnail: '', description: item.description || '' } if (!isDir) { const icon = getFileIcon(add.category, add.ext, item.mime_extension, item.mime_type, add.size) add.category = icon[0] add.icon = icon[1] if (downUrl) { if (downUrl == 'download_url') { add.download_url = item.download_url || '' } else if (add.category == 'image') { add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&image_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1' } else if (add.category == 'image2') { add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id } else if (add.category.startsWith('video')) { add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&video_thumbnail_process=video%2Fsnapshot%2Ct_106000%2Cf_jpg%2Car_auto%2Cw_260%2Cm_fast' } else if (add.category == 'doc' || add.category == 'doc2') { if (add.ext != 'txt' && add.ext != 'epub' && add.ext != 'azw' && add.ext != 'azw3') { add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&office_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1' } } } if (item.video_media_metadata) { add.media_width = item.video_media_metadata.width || 0 add.media_height = item.video_media_metadata.height || 0 add.media_time = humanDateTimeDateStr(item.video_media_metadata.time) add.media_duration = humanTime(item.video_media_metadata.duration) } else if (item.video_preview_metadata) { add.media_width = item.video_preview_metadata.width || 0 add.media_height = item.video_preview_metadata.height || 0 add.media_time = humanDateTimeDateStr(item.video_preview_metadata.time) add.media_duration = humanTime(item.video_preview_metadata.duration) } else if (item.image_media_metadata) { add.media_width = item.image_media_metadata.width || 0 add.media_height = item.image_media_metadata.height || 0 add.media_time = humanDateTimeDateStr(item.image_media_metadata.time) } } if (item.punish_flag == 2) add.icon = 'iconweifa' else if (item.punish_flag > 0) add.icon = 'iconweixiang' return add } static async ApiDirFileList(user_id: string, drive_id: string, dirID: string, dirName: string, order: string, type: string = ''): Promise { const dir: IAliFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: dirID, dirName: dirName } if (!user_id || !drive_id || !dirID) return dir if (!order) order = 'updated_at desc' order = order.replace(' desc', ' DESC').replace(' asc', ' ASC') const orders = order.split(' ') let pageIndex = 0 if (dirID == 'video') { await AliDirFileList._ApiVideoListRecent(dir) pageIndex++ } let max: number = useSettingStore().debugFileListMax if (dirID == 'favorite' || dirID.startsWith('color') || dirID.startsWith('search') || dirID.startsWith('video')) max = useSettingStore().debugFavorListMax let needTotal do { let isGet = false if (dirID == 'favorite') { if (!needTotal) { needTotal = AliDirFileList._ApiFavoriteFileListCount(dir).then((total) => { dir.itemsTotal = total }) } isGet = await AliDirFileList._ApiFavorFileListOnePage(orders[0], orders[1], dir, pageIndex) } else if (dirID == 'trash') isGet = await AliDirFileList._ApiTrashFileListOnePage(orders[0], orders[1], dir, pageIndex) else if (dirID == 'recover') isGet = await AliDirFileList._ApiDeleteedFileListOnePage(orders[0], orders[1], dir, pageIndex) else if (dirID.startsWith('color')) { if (!needTotal) { needTotal = AliDirFileList._ApiSearchFileListCount(dir).then((total) => { dir.itemsTotal = total }) } isGet = await AliDirFileList._ApiSearchFileListOnePage(orders[0], orders[1], dir, pageIndex) } else if (dirID.startsWith('search')) { if (!needTotal) { needTotal = AliDirFileList._ApiSearchFileListCount(dir).then((total) => { dir.itemsTotal = total }) } isGet = await AliDirFileList._ApiSearchFileListOnePage(orders[0], orders[1], dir, pageIndex) } else if (dirID == 'video') isGet = await AliDirFileList._ApiVideoListOnePage(orders[0], orders[1], dir, pageIndex) else if (dirID.startsWith('video')) isGet = await AliDirFileList._ApiVideoFileListOnePage(orders[0], orders[1], dir, pageIndex) else { if (!needTotal) { needTotal = AliDirFileList._ApiDirFileListCount(dir, type).then((total) => { dir.itemsTotal = total }) } isGet = await AliDirFileList._ApiDirFileListOnePage(orders[0], orders[1], dir, type, pageIndex) } if (isGet != true) { if (needTotal) dir.itemsTotal = -1 break } if (dir.next_marker == 'cancel') { if (needTotal) dir.itemsTotal = -1 break } if (dir.items.length >= max && max > 0) { dir.next_marker = '' break } pageIndex++ } while (dir.next_marker) if (needTotal) await needTotal return dir } private static async _ApiDirFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string, pageIndex: number): Promise { let url = 'adrive/v3/file/list' if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')' else url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)' let postData = { drive_id: dir.m_drive_id, parent_file_id: dir.dirID, marker: dir.next_marker, limit: 200, all: false, url_expire_sec: 14400, fields: '*', order_by: orderby, order_direction: order.toUpperCase() } if (type) { postData = Object.assign(postData, { type }) pageIndex = -1 } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex, type) } private static async _ApiDirFileListCount(dir: IAliFileResp, type: string): Promise { const url = 'adrive/v3/file/search' const postData = { drive_id: dir.m_drive_id, marker: '', limit: 1, all: false, url_expire_sec: 14400, fields: 'thumbnail', query: 'parent_file_id="' + dir.dirID + '"' + (type ? ' and type="' + type + '"' : ''), return_total_count: true } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { return resp.body.total_count || 0 } else { DebugLog.mSaveWarning('_ApiDirFileListCount err=' + dir.dirID + ' ' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ApiDirFileListCount ' + dir.dirID, err) } return 0 } private static async _ApiFavoriteFileListCount(dir: IAliFileResp): Promise { const url = 'adrive/v3/file/search' const postData = { drive_id: dir.m_drive_id, marker: '', limit: 1, all: false, url_expire_sec: 14400, fields: 'thumbnail', query: 'starred=true', return_total_count: true } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { return resp.body.total_count || 0 } else { DebugLog.mSaveWarning('_ApiFavoriteFileListCount err=' + dir.dirID + ' ' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ApiFavoriteFileListCount ' + dir.dirID, err) } return 0 } private static async _ApiFavorFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { let url = 'v2/file/list_by_custom_index_key' if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')' else url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)' const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 100, url_expire_sec: 14400, fields: '*', order_by: orderby, order_direction: order.toUpperCase(), custom_index_key: 'starred_yes', parent_file_id: 'root' } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } private static async _ApiTrashFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { const url = 'v2/recyclebin/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')' const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 100, all: false, url_expire_sec: 14400, fields: 'thumbnail', order_by: orderby, order_direction: order.toUpperCase() } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } static async _ApiDeleteedFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { const url = 'adrive/v1/file/listDeleted' const postData = { drive_id: dir.m_drive_id, album_drive_id: dir.m_drive_id, marker: dir.next_marker } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } static async _ApiSearchFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { let url = 'adrive/v3/file/search' if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')' else url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)' let query = '' if (dir.dirID.startsWith('color')) { const color = dir.dirID.substring('color'.length).split(' ')[0].replace('#', 'c') query = 'description="' + color + '"' } else if (dir.dirID.startsWith('search')) { const search = dir.dirID.substring('search'.length).split(' ') let word = '' for (let i = 0; i < search.length; i++) { const itemstr = search[i] if (itemstr.split(':').length !== 2) { word += itemstr + ' ' continue } const kv = search[i].split(':') const k = kv[0] const v = kv[1] if (k == 'type') { const arr = v.split(',') let type = '' for (let j = 0; j < arr.length; j++) { if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or ' else if (arr[j]) type += 'category="' + arr[j] + '" or ' } type = type.substring(0, type.length - 4).trim() if (type && type.indexOf(' or ') > 0) query += '(' + type + ') and ' else if (type) query += type + ' and ' } else if (k == 'size') { const size = parseInt(v) if (size > 0) query += 'size = ' + v + ' and ' } else if (k == 'max') { const max = parseInt(v) if (max > 0) query += 'size <= ' + v + ' and ' } else if (k == 'min') { const min = parseInt(v) if (min > 0) query += 'size >= ' + v + ' and ' } else if (k == 'begin') { const dt = new Date(v).toISOString() query += 'updated_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and ' } else if (k == 'end') { const dt = new Date(v).toISOString() query += 'updated_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and ' } else if (k == 'ext') { const arr = v.split(',') let extin = '' for (let j = 0; j < arr.length; j++) { extin += '"' + arr[j] + '",' } if (extin.length > 0) extin = extin.substring(0, extin.length - 1) if (extin) query += 'file_extension in [' + extin + '] and ' } else if (k == 'fav') query += 'starred = ' + v + ' and ' } word = word.trim() if (word) query += 'name match "' + word.replaceAll('"', '\\"') + '" and ' if (query.length > 0) query = query.substring(0, query.length - 5) if (query.startsWith('(') && query.endsWith(')')) query = query.substring(1, query.length - 1) } const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 100 , fields: '*', query: query, order_by: orderby + ' ' + order } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } static async _ApiSearchFileListCount(dir: IAliFileResp): Promise { const url = 'adrive/v3/file/search' let query = '' if (dir.dirID.startsWith('color')) { const color = dir.dirID.substring('color'.length).split(' ')[0].replace('#', 'c') query = 'description="' + color + '"' } else if (dir.dirID.startsWith('search')) { const search = dir.dirID.substring('search'.length).split(' ') let word = '' for (let i = 0; i < search.length; i++) { const itemstr = search[i] if (itemstr.split(':').length !== 2) { word += itemstr + ' ' continue } const kv = search[i].split(':') const k = kv[0] const v = kv[1] if (k == 'type') { const arr = v.split(',') let type = '' for (let j = 0; j < arr.length; j++) { if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or ' else if (arr[j]) type += 'category="' + arr[j] + '" or ' } type = type.substring(0, type.length - 4).trim() if (type && type.indexOf(' or ') > 0) query += '(' + type + ') and ' else if (type) query += type + ' and ' } else if (k == 'size') { const size = parseInt(v) if (size > 0) query += 'size = ' + v + ' and ' } else if (k == 'max') { const max = parseInt(v) if (max > 0) query += 'size <= ' + v + ' and ' } else if (k == 'min') { const min = parseInt(v) if (min > 0) query += 'size >= ' + v + ' and ' } else if (k == 'begin') { const dt = new Date(v).toISOString() query += 'updated_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and ' } else if (k == 'end') { const dt = new Date(v).toISOString() query += 'updated_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and ' } else if (k == 'ext') { const arr = v.split(',') let extin = '' for (let j = 0; j < arr.length; j++) { extin += '"' + arr[j] + '",' } if (extin.length > 0) extin = extin.substring(0, extin.length - 1) if (extin) query += 'file_extension in [' + extin + '] and ' } else if (k == 'fav') query += 'starred = ' + v + ' and ' } word = word.trim() if (word) query += 'name match "' + word.replaceAll('"', '\\"') + '" and ' if (query.length > 0) query = query.substring(0, query.length - 5) if (query.startsWith('(') && query.endsWith(')')) query = query.substring(1, query.length - 1) } const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 1 , fields: '*', query: query, return_total_count: true } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { return (resp.body.total_count as number) || 0 } else { DebugLog.mSaveWarning('_ApiSearchFileListCount err=' + dir.dirID + ' ' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ApiSearchFileListCount ' + dir.dirID, err) } return 0 } static async _ApiVideoListRecent(dir: IAliFileResp): Promise { const url = 'adrive/v2/video/recentList' const postData = {} const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage('', '', dir, resp, 0) } static async _ApiVideoListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { const url = 'adrive/v2/video/list' const postData = { use_compilation: true, duration: 0, order_by: (orderby + ' ' + order).toLowerCase(), hidden_type: 'NO_HIDDEN', limit: 100, marker: dir.next_marker, url_expire_sec: 14400 } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } static async _ApiVideoFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise { const url = 'adrive/v2/video/compilation/list' const postData = { name: dir.dirID.substring('video'.length), use_compilation: true, duration: 0, order_by: (orderby + ' ' + order).toLowerCase(), hidden_type: 'NO_HIDDEN', limit: 100, marker: dir.next_marker, url_expire_sec: 14400 } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex) } static _FileListOnePage(orderby: string, order: string, dir: IAliFileResp, resp: IUrlRespData, pageIndex: number, type: string = ''): boolean { try { if (AliHttp.IsSuccess(resp.code)) { const dirPart: IAliFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: dir.next_marker, m_user_id: dir.m_user_id, m_drive_id: dir.m_drive_id, dirID: dir.dirID, dirName: dir.dirName } dir.next_marker = resp.body.next_marker || '' const isRecover = dir.dirID == 'recover' const isDirFile = dir.dirID == 'root' || (dir.dirID.length == 40 && !dir.dirID.startsWith('search')) const isVideo = dir.dirID.startsWith('video') // const issearch = dir.dirID.startsWith('search') // const iscolor = dir.dirID.startsWith('color') const downUrl = isRecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString() if (resp.body.items) { const driverData = TreeStore.GetDriver(dir.m_drive_id) const DirFileSizeMap = driverData?.DirFileSizeMap || {} const DirTotalSizeMap = driverData?.DirTotalSizeMap || {} const isFolderSize = useSettingStore().uiFolderSize let dirList: IAliGetFileModel[] = [] let fileList: IAliGetFileModel[] = [] for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliFileItem if (isVideo) { if (!item.compilation_id && (!item.drive_id || !item.file_id)) continue if (!item.compilation_id) { item.type = 'file' item.compilation_id = item.drive_id + '_' + item.file_id } if (item.video_type == 'COMPILATION') { item.type = 'folder' item.drive_id = item.compilation_id.split('_')[0] item.file_id = item.compilation_id.split('_')[1] } } if (dir.itemsKey.has(item.file_id)) continue const add = AliDirFileList.getFileInfo(item, downUrl) if (isRecover) add.description = item.content_hash if (isVideo) { add.compilation_id = item.compilation_id } if (add.isDir) { if (isFolderSize) { add.size = DirTotalSizeMap[add.file_id] || DirFileSizeMap[add.file_id] || 0 add.sizeStr = humanSize(add.size) } if (isDirFile) dirList.push(add) else fileList.push(add) } else fileList.push(add) dir.itemsKey.add(item.file_id) } if (dirList.length > 0) { dirList = OrderDir(orderby, order, dirList) as IAliGetFileModel[] dirPart.items.push(...dirList) dir.items.push(...dirList) } if (fileList.length > 0) { fileList = OrderFile(orderby, order, fileList) as IAliGetFileModel[] dirPart.items.push(...fileList) dir.items.push(...fileList) } } dirPart.punished_file_count = resp.body.punished_file_count || 0 dir.punished_file_count += resp.body.punished_file_count || 0 if (pageIndex >= 0 && type == '') { const pan = usePanFileStore() if (pan.DriveID == dir.m_drive_id) pan.mSaveDirFileLoadingPart(pageIndex, dirPart, dir.itemsTotal || 0) } if (dirPart.next_marker == 'cancel') dir.next_marker = 'cancel' if (isVideo && dir.items.length >= 500) dir.next_marker = '' return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出文件出错 ' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_FileListOnePage err=' + dir.dirID + ' ' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err) } dir.next_marker = 'error ' + resp.code return false } static async ApiDirFileSize(user_id: string, drive_id: string, file_idList: string[]): Promise<{ dirID: string; size: number }[] | undefined> { const list: Map = new Map() let postData = '{"requests":[' for (let i = 0, maxi = file_idList.length; i < maxi; i++) { list.set(file_idList[i], { dirID: file_idList[i], size: 0 }) if (i > 0) postData = postData + ',' const data2 = { body: { drive_id: drive_id, query: 'parent_file_id="' + file_idList[i] + '" and type="file"', limit: 100, fields: 'thumbnail', order_by: 'size DESC' }, headers: { 'Content-Type': 'application/json' }, id: file_idList[i], method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Citems(size)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const respi = responses[j] if (respi.id && respi.status && respi.status >= 200 && respi.status <= 205) { if (respi.body && respi.body.items && respi.body.items.length > 0) { let size = 0 const items = respi.body.items for (let k = 0, maxk = items.length; k < maxk; k++) { size += items[k].size || 0 } const find = list.get(respi.id) if (find) find.size = size } } } return MapValueToArray(list) } else { DebugLog.mSaveWarning('ApiDirFileSize err=' + (resp.code || '')) return undefined } } catch (err: any) { DebugLog.mSaveWarning('ApiDirFileSize', err) } return MapValueToArray(list) } } ================================================ FILE: src/renderer/aliapi/dirlist.ts ================================================ import DebugLog from '../utils/debuglog' import { MapValueToArray } from '../utils/utils' import AliHttp from './alihttp' import { IAliGetDirModel, IAliGetFileModel } from './alimodels' import AliDirFileList from './dirfilelist' import dayjs from 'dayjs' import AliTrash from './trash' import { DirData } from '../store/treestore' import AliUser from './user' export interface IAliDirResp { items: IAliGetDirModel[] next_marker: string m_user_id: string m_drive_id: string dirID: string dirName: string } export interface IDirDataResp { items: DirData[] next_marker: string m_user_id: string m_drive_id: string dirID: string dirName: string } export interface IAliDirBatchResp { items: IAliGetFileModel[] itemsKey: Set next_marker: string dirID: string } export default class AliDirList { static async ApiFastAllDirList(user_id: string, drive_id: string): Promise { const result: IAliDirResp = { items: [], next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: 'root', dirName: '' } if (!user_id || !drive_id) return result const lockSet = new Set() const allMap = new Map() let errorMessage = '' let next_marker1 = '' let next_marker2 = '' while (true) { let postData = '{"requests":[' postData += '{"body": {"drive_id": "' + drive_id + '","query": "type = \\"folder\\"","limit": 100,"fields": "thumbnail","order_by":"name ASC"' + (next_marker1 ? ',"marker":"' + next_marker1 + '"' : '') + '},' postData += '"headers": { "Content-Type": "application/json" }, "id": "id1","method": "POST","url": "/file/search"},' postData += '{"body": {"drive_id": "' + drive_id + '","query": "type = \\"folder\\"","limit": 100,"fields": "thumbnail","order_by":"name DESC"' + (next_marker2 ? ',"marker":"' + next_marker2 + '"' : '') + '},' postData += '"headers": { "Content-Type": "application/json" }, "id": "id2","method": "POST","url": "/file/search"}' postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Citems(name%2Cfile_id%2Cdrive_id%2Cupdated_at%2Csize%2Cdescription%2Cparent_file_id)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const resp1 = resp.body.responses[0] const resp2 = resp.body.responses[1] if (resp1.status >= 200 && resp1.status <= 205 && resp2.status >= 200 && resp2.status <= 205) { next_marker1 = resp1.body.next_marker next_marker2 = resp2.body.next_marker let isFind = false for (let i = 0, maxi = resp1.body.items.length; i < maxi; i++) { const item = resp1.body.items[i] if (lockSet.has(item.file_id)) { isFind = true } else { const add: IAliGetDirModel = { __v_skip: true, drive_id: item.drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, namesearch: '', size: item.size || 0, time: new Date(item.updated_at).getTime(), description: item.description || '' } allMap.set(add.file_id, add) lockSet.add(item.file_id) } } for (let i = 0, maxi = resp2.body.items.length; i < maxi; i++) { const item = resp2.body.items[i] if (lockSet.has(item.file_id)) { isFind = true } else { const add: IAliGetDirModel = { __v_skip: true, drive_id: item.drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, namesearch: '', size: item.size || 0, time: new Date(item.updated_at).getTime(), description: item.description || '' } allMap.set(add.file_id, add) lockSet.add(item.file_id) } } if (isFind) break if (resp1.body.next_marker == '' && resp2.body.next_marker == '') break } else { errorMessage += 'err1' + (resp1.status || '') errorMessage += 'err2' + (resp2.status || '') break } } else if (resp.code == 402) { DebugLog.mSaveWarning('ApiFastAllDirList err=' + drive_id + ' ' + (resp.code || '')) break } else { errorMessage += 'err' + (resp.code || '') DebugLog.mSaveWarning('ApiFastAllDirList err=' + (resp.code || '')) } } catch (err: any) { errorMessage += 'err' + (err.message || '') DebugLog.mSaveWarning('ApiFastAllDirList', err) break } } const list = MapValueToArray(allMap) console.log('listcount', list.length) result.items = errorMessage ? [] : list result.next_marker = errorMessage return result } static async ApiBatchDirFileList(user_id: string, drive_id: string, dirList: IAliDirBatchResp[], limit: number, listTypeOrQuery: string): Promise { if (!user_id || !drive_id) return false let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' let query = 'parent_file_id="' + dirList[i].dirID + '"' if (listTypeOrQuery == 'all') query = 'parent_file_id="' + dirList[i].dirID + '"' else if (listTypeOrQuery == 'folder') query = 'parent_file_id="' + dirList[i].dirID + '" and type = "folder"' else if (listTypeOrQuery == 'file') query = 'parent_file_id="' + dirList[i].dirID + '" and type = "file"' else query = query + listTypeOrQuery const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, url_expire_sec: 14400, limit: limit, // fields: 'thumbnail', image_thumbnail_process: '', video_thumbnail_process: '', image_url_process: '' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID, method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID == id) { const dir = dirList[i] dir.next_marker = respi.body.next_marker const items = respi.body.items for (let i = 0, maxi = items.length; i < maxi; i++) { const add = AliDirFileList.getFileInfo(items[i], '') dir.items.push(add) } break } } } } return true } else { DebugLog.mSaveWarning('ApiBatchDirFileList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveWarning('ApiBatchDirFileList', err) } return false } static async ApiFastAllDirListByTime(user_id: string, drive_id: string, created_at: Date): Promise { const result: IAliDirResp = { items: [], next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: 'root', dirName: '' } if (!user_id || !drive_id) return result const allMap = new Map() let dirList: IAliDirBatchResp[] = [] let time = dayjs(created_at).add(1, 'hour') const day = 10 const end = dayjs().add(day + 1, 'day') let errorMessage = '' while (true) { while (dirList.length < 30) { const timeEnd = time.add(day, 'day') if (timeEnd.isBefore(end)) { const dirID = 'created_at > "' + time.toISOString().substring(0, 19) + '" and created_at <= "' + timeEnd.toISOString().substring(0, 19) + '"' dirList.push({ dirID: dirID, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp) time = timeEnd } else break } if (dirList.length == 0) break console.log('dirList.length', dirList.length) let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' const query = 'type="folder" and ' + dirList[i].dirID const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, limit: 100, fields: 'thumbnail' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll('-', '').replaceAll(':', '').replaceAll(',', ''), method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Citems(name%2Cfile_id%2Cdrive_id%2Cupdated_at%2Csize%2Cdescription%2Cparent_file_id)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses const list: IAliDirBatchResp[] = [] for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll('-', '').replaceAll(':', '').replaceAll(',', '') == id) { const dir = dirList[i] const items = respi.body.items dir.next_marker = respi.body.next_marker if (dir.next_marker) list.push(dir) for (let i = 0, maxi = items.length; i < maxi; i++) { if (allMap.has(items[i].file_id)) continue const item = items[i] const add: IAliGetDirModel = { __v_skip: true, drive_id: item.drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, namesearch: '', size: item.size || 0, time: new Date(item.updated_at).getTime(), description: item.description || '' } allMap.set(add.file_id, add) } break } } } } dirList.length = 0 dirList = list } else { errorMessage = (resp.code || '').toString() DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || '')) } } catch (err: any) { errorMessage = err.message || '' DebugLog.mSaveWarning('ApiBatchDirFileList', err) } } const list = MapValueToArray(allMap) console.log('listcount', list.length) result.items = errorMessage ? [] : list result.next_marker = errorMessage return result } static async _ApiDirFileListInfo(user_id: string, drive_id: string) { const url = 'adrive/v3/file/search' const postData = { drive_id: drive_id, marker: '', limit: 1, all: false, url_expire_sec: 14400, fields: 'thumbnail', query: 'type="folder"', order_by: 'created_at ASC', return_total_count: true } const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const items = resp.body.items || [] const created_at = items.length > 0 ? new Date(items[0].created_at) : new Date() const total_count = resp.body.total_count || 0 return { created_at, total_count } } else { DebugLog.mSaveWarning('_ApiDirFileListInfo err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ApiDirFileListInfo', err) } return { created_at: new Date(), total_count: 0 } } static async ApiFastAllDirListByPID(user_id: string, drive_id: string): Promise { const result: IDirDataResp = { items: [], next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: 'root', dirName: '' } if (!user_id || !drive_id) return result const allMap = new Map() const dirCount = await AliUser.ApiUserDriveFileCount(user_id, '', 'folder') const PIDList: string[] = [] const root = await AliTrash.ApiDirFileListNoLock(user_id, drive_id, 'root', '', 'name ASC', 'folder', 0) for (let i = 0, maxi = root.items.length; i < maxi; i++) { const item = root.items[i] const add: DirData = { file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, time: item.time, size: 0 } allMap.set(add.file_id, add) PIDList.push(add.file_id) } let dirList: IAliDirBatchResp[] = [] let errorMessage = '' let index = 0 while (true) { while (dirList.length < 30) { if (PIDList.length > index) { let dirID = 'parent_file_id in [' let add = 0 for (let maxj = PIDList.length; index < maxj; index++) { dirID += add == 0 ? '"' + PIDList[index] + '"' : ',"' + PIDList[index] + '"' add++ if (add >= 50) break } dirID += ']' dirList.push({ dirID: dirID, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp) } else break } if (dirList.length == 0) break let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' const query = 'type="folder" and ' + dirList[i].dirID const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, limit: 100, fields: 'thumbnail', order_by: 'name ASC' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll(',', '').substring(0, 54), method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Citems(name%2Cfile_id%2Cdrive_id%2Cupdated_at%2Csize%2Cdescription%2Cparent_file_id)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses const list: IAliDirBatchResp[] = [] for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll(',', '').substring(0, 54) == id) { const dir = dirList[i] const items = respi.body.items dir.next_marker = respi.body.next_marker if (dir.next_marker) list.push(dir) for (let i = 0, maxi = items.length; i < maxi; i++) { if (allMap.has(items[i].file_id)) continue const item = items[i] const add: DirData = { file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, time: new Date(item.updated_at).getTime(), size: 0 } allMap.set(add.file_id, add) PIDList.push(add.file_id) } break } } } } dirList.length = 0 dirList = list if (window.WinMsgToMain) window.WinMsgToMain({ cmd: 'MainShowAllDirProgress', drive_id, index: allMap.size, total: dirCount }) } else { errorMessage = (resp.code || '').toString() DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || '')) } } catch (err: any) { errorMessage = err.message || '' DebugLog.mSaveWarning('ApiBatchDirFileList', err) } } const list = MapValueToArray(allMap) console.log('listcount', list.length) result.items = errorMessage ? [] : list result.next_marker = errorMessage return result } } ================================================ FILE: src/renderer/aliapi/file.ts ================================================ import { useSettingStore } from '../store' import DebugLog from '../utils/debuglog' import message from '../utils/message' import { GetOssExpires, HanToPin } from '../utils/utils' import AliHttp from './alihttp' import { IAliFileItem, IAliGetDirModel, IAliGetFileModel, IAliGetForderSizeModel } from './alimodels' import AliDirFileList from './dirfilelist' import { IDownloadUrl, IOfficePreViewUrl, IVideoPreviewUrl, IVideoXBTUrl } from './models' export default class AliFile { static async ApiFileInfo(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get' const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400' } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return resp.body as IAliFileItem } else { DebugLog.mSaveWarning('ApiFileInfo err=' + file_id + ' ' + (resp.code || '')) } return undefined } static async ApiFileInfoByPath(user_id: string, drive_id: string, file_path: string): Promise { if (!user_id || !drive_id || !file_path) return undefined if (file_path.startsWith('/') == false) file_path = '/' + file_path const url = 'v2/file/get_by_path' const postData = { drive_id: drive_id, file_path: file_path, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400' } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return resp.body as IAliFileItem } else { DebugLog.mSaveWarning('ApiFileInfoByPath err=' + file_path + ' ' + (resp.code || '')) } return undefined } static async ApiFileDownloadUrl(user_id: string, drive_id: string, file_id: string, expire_sec: number): Promise { if (!user_id || !drive_id || !file_id) return 'file_id错误' const data: IDownloadUrl = { drive_id: drive_id, file_id: file_id, expire_sec: 0, url: '', size: 0 } const url1 = 'v2/file/get' const postData1 = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400' } const resp1 = await AliHttp.Post(url1, postData1, user_id, '') if (AliHttp.IsSuccess(resp1.code)) { const info = resp1.body as IAliFileItem if (info.download_url && GetOssExpires(info.download_url) > 14400) { data.url = info.download_url data.size = info.size data.expire_sec = GetOssExpires(data.url) return data } } else { DebugLog.mSaveWarning('ApiFileDownloadUrl1 err=' + file_id + ' ' + (resp1.code || '')) } const url = 'v2/file/get_download_url' const postData = { drive_id: drive_id, file_id: file_id, expire_sec: expire_sec } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { data.url = resp.body.url data.size = resp.body.size data.expire_sec = GetOssExpires(data.url) return data } else if (resp.body.code == 'NotFound.FileId') { return '文件已从网盘中彻底删除' } else if (resp.body.code == 'ForbiddenFileInTheRecycleBin') { return '文件已放入回收站' } else if (resp.body.code) { return resp.body.code as string } else { DebugLog.mSaveWarning('ApiFileDownloadUrl err=' + file_id + ' ' + (resp.code || '')) } return '网络错误' } static async ApiVideoPreviewUrl(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get_video_preview_play_info' const postData = { drive_id: drive_id, file_id: file_id, category: 'live_transcoding', template_id: '', get_subtitle_info: true, url_expire_sec: 14400 } const resp = await AliHttp.Post(url, postData, user_id, '') if (resp.body.code == 'VideoPreviewWaitAndRetry') { message.warning('视频正在转码中,稍后重试') return undefined } const data: IVideoPreviewUrl = { drive_id: drive_id, file_id: file_id, expire_sec: 0, width: 0, height: 0, url: '', duration: 0, urlFHD: '', urlHD: '', urlSD: '', urlLD: '', subtitles: [] } if (AliHttp.IsSuccess(resp.code)) { const subtitle = resp.body.video_preview_play_info?.live_transcoding_subtitle_task_list || [] for (let i = 0, maxi = subtitle.length; i < maxi; i++) { if (subtitle[i].status == 'finished') { data.subtitles.push({ language: subtitle[i].language, url: subtitle[i].url }) } } const taskList = resp.body.video_preview_play_info?.live_transcoding_task_list || [] for (let i = 0, maxi = taskList.length; i < maxi; i++) { if (taskList[i].template_id && taskList[i].template_id == 'FHD' && taskList[i].status == 'finished') { data.urlFHD = taskList[i].url } else if (taskList[i].template_id && taskList[i].template_id == 'HD' && taskList[i].status == 'finished') { data.urlHD = taskList[i].url } else if (taskList[i].template_id && taskList[i].template_id == 'SD' && taskList[i].status == 'finished') { data.urlSD = taskList[i].url } else if (taskList[i].template_id && taskList[i].template_id == 'LD' && taskList[i].status == 'finished') { data.urlLD = taskList[i].url } } data.url = data.urlFHD || data.urlHD || data.urlSD || data.urlLD || '' data.duration = Math.floor(resp.body.video_preview_play_info?.meta?.duration || 0) data.width = resp.body.video_preview_play_info?.meta?.width || 0 data.height = resp.body.video_preview_play_info?.meta?.height || 0 data.expire_sec = GetOssExpires(data.url) return data } else { DebugLog.mSaveWarning('ApiVideoPreviewUrl err=' + file_id + ' ' + (resp.code || '')) } return undefined } static async ApiAudioPreviewUrl(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get_audio_play_info' const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400 } const resp = await AliHttp.Post(url, postData, user_id, '') if (resp.body.code == 'AudioPreviewWaitAndRetry') { message.warning('音频正在转码中,稍后重试') } const data: IDownloadUrl = { drive_id: drive_id, file_id: file_id, expire_sec: 0, url: '', size: 0 } if (AliHttp.IsSuccess(resp.code)) { const template_list = resp.body.template_list || [] if (!data.url) { for (let i = 0, maxi = template_list.length; i < maxi; i++) { if (template_list[i].template_id && template_list[i].template_id == 'HQ' && template_list[i].status == 'finished') data.url = template_list[i].url } } if (!data.url) { for (let i = 0, maxi = template_list.length; i < maxi; i++) { if (template_list[i].template_id && template_list[i].template_id == 'LQ' && template_list[i].status == 'finished') data.url = template_list[i].url } } return data } else { DebugLog.mSaveWarning('ApiAudioPreviewUrl err=' + file_id + ' ' + (resp.code || '')) } return undefined } static async ApiOfficePreViewUrl(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get_office_preview_url' const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400 } const resp = await AliHttp.Post(url, postData, user_id, '') const data: IOfficePreViewUrl = { drive_id: drive_id, file_id: file_id, access_token: '', preview_url: '' } if (AliHttp.IsSuccess(resp.code)) { data.access_token = resp.body.access_token data.preview_url = resp.body.preview_url return data } else { DebugLog.mSaveWarning('ApiOfficePreViewUrl err=' + file_id + ' ' + (resp.code || '')) } return undefined } static async ApiGetFile(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get' const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400' } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return AliDirFileList.getFileInfo(resp.body as IAliFileItem, '') } else { DebugLog.mSaveWarning('ApiGetFile err=' + file_id + ' ' + (resp.code || '')) } return undefined } static async ApiFileGetPath(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return [] const url = 'adrive/v1/file/get_path' const postData = { drive_id: drive_id, file_id: file_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code) && resp.body.items && resp.body.items.length > 0) { const list: IAliGetDirModel[] = [] for (let i = resp.body.items.length - 1; i > 0; i--) { const item = resp.body.items[i] list.push({ __v_skip: true, drive_id: item.drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id || '', name: item.name, namesearch: HanToPin(item.name), size: item.size || 0, time: new Date(item.updated_at).getTime(), description: item.description || '' } as IAliGetDirModel) } list.push({ __v_skip: true, drive_id: drive_id, file_id: 'root', parent_file_id: '', name: '根目录', namesearch: HanToPin('root'), size: 0, time: 0, description: '' } as IAliGetDirModel) return list } else { DebugLog.mSaveWarning('ApiFileGetPath err=' + file_id + ' ' + (resp.code || '')) } return [] } static async ApiFileGetPathString(user_id: string, drive_id: string, file_id: string, dirsplit: string): Promise { if (!user_id || !drive_id || !file_id) return '' if (file_id == 'root') return '根目录' const url = 'adrive/v1/file/get_path' const postData = { drive_id: drive_id, file_id: file_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code) && resp.body.items && resp.body.items.length > 0) { const list: string[] = [] for (let i = resp.body.items.length - 1; i >= 0; i--) { const item = resp.body.items[i] list.push(item.name) } return list.join(dirsplit) } else { DebugLog.mSaveWarning('ApiFileGetPathString err=' + file_id + ' ' + (resp.code || '')) } return '' } static async ApiFileGetFolderSize(user_id: string, drive_id: string, file_id: string): Promise { if (!user_id || !drive_id || !file_id) return undefined const url = 'adrive/v1/file/get_folder_size_info' const postData = { drive_id: drive_id, file_id: file_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return resp.body as IAliGetForderSizeModel } else { DebugLog.mSaveWarning('ApiFileGetFolderSize err=' + file_id + ' ' + (resp.code || '')) } return { size: 0, folder_count: 0, file_count: 0, reach_limit: false } } static async ApiFileDownText(user_id: string, drive_id: string, file_id: string, filesize: number, maxsize: number): Promise { if (!user_id || !drive_id || !file_id) return '' const downUrl = await AliFile.ApiFileDownloadUrl(user_id, drive_id, file_id, 14400) if (typeof downUrl == 'string') return downUrl const resp = await AliHttp.GetString(downUrl.url, '', filesize, maxsize) if (AliHttp.IsSuccess(resp.code)) { if (typeof resp.body == 'string') return resp.body return JSON.stringify(resp.body, undefined, 2) } else { DebugLog.mSaveWarning('ApiFileDownText err=' + file_id + ' ' + (resp.code || '')) } return '' } static async ApiBiXueTuBatch(user_id: string, drive_id: string, file_id: string, duration: number, imageCount: number, imageWidth: number): Promise { if (!user_id || !drive_id || !file_id) return [] if (duration <= 0) return [] const batchList: string[] = [] let mtime = 0 let subtime = Math.floor(duration / (imageCount + 2)) if (subtime < 1) subtime = 1 const imgList: IVideoXBTUrl[] = [] for (let i = 0; i < imageCount; i++) { mtime += subtime if (mtime > duration) break const postData = { body: { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, video_thumbnail_process: 'video/snapshot,t_' + mtime.toString() + '000,f_jpg,ar_auto,m_fast,w_' + imageWidth.toString() }, headers: { 'Content-Type': 'application/json' }, id: (i.toString() + file_id).substr(0, file_id.length), method: 'POST', url: '/file/get' } batchList.push(JSON.stringify(postData)) const time = Math.floor(mtime / 3600) .toString() .padStart(2, '0') + ':' + Math.floor((mtime % 3600) / 60) .toString() .padStart(2, '0') + ':' + Math.floor(mtime % 60) .toString() .padStart(2, '0') imgList.push({ time, url: '' } as IVideoXBTUrl) } let postData = '{"requests":[' let add = 0 for (let i = 0, maxi = batchList.length; i < maxi; i++) { if (add > 0) postData = postData + ',' add++ postData = postData + batchList[i] } postData += '],"resource":"file"}' const url = 'v2/batch' const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let i = 0, maxi = responses.length; i < maxi; i++) { const status = responses[i].status as number if (status >= 200 && status <= 205) { imgList[i].url = responses[i].body?.thumbnail || '' } else { console.log(responses[i]) } } } else { DebugLog.mSaveWarning('ApiBiXueTuBatch err=' + file_id + ' ' + (resp.code || '')) } return imgList } static async ApiUpdateVideoTime(user_id: string, drive_id: string, file_id: string, play_cursor: number): Promise { if (!useSettingStore().uiAutoPlaycursorVideo) return if (!user_id || !drive_id || !file_id) return undefined const url = 'v2/file/get' const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_' + Math.floor(play_cursor) + ',f_jpg,w_0,h_0,m_fast' } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const info = resp.body as IAliFileItem const urlvideo = 'adrive/v2/video/update' const postVideoData = { drive_id: drive_id, file_id: file_id, play_cursor: play_cursor.toString(), thumbnail: info.thumbnail || '' } const respvideo = await AliHttp.Post(urlvideo, postVideoData, user_id, '') if (AliHttp.IsSuccess(respvideo.code)) { return respvideo.body as IAliFileItem } else { DebugLog.mSaveWarning('ApiUpdateVideoTime2 err=' + file_id + ' ' + (respvideo.code || '')) } } else { DebugLog.mSaveWarning('ApiUpdateVideoTime err=' + file_id + ' ' + (resp.code || '')) } return undefined } } ================================================ FILE: src/renderer/aliapi/filecmd.ts ================================================ import DebugLog from '../utils/debuglog' import message from '../utils/message' import AliHttp from './alihttp' import { IAliFileItem, IAliGetFileModel } from './alimodels' import AliDirFileList from './dirfilelist' import { ApiBatch, ApiBatchMaker, ApiBatchMaker2, ApiBatchSuccess } from './utils' export default class AliFileCmd { static async ApiCreatNewForder(user_id: string, drive_id: string, parent_file_id: string, creatDirName: string): Promise<{ file_id: string; error: string }> { const result = { file_id: '', error: '新建文件夹失败' } if (!user_id || !drive_id || !parent_file_id) return result const url = 'adrive/v2/file/createWithFolders' const postData = JSON.stringify({ drive_id: drive_id, parent_file_id: parent_file_id, name: creatDirName, check_name_mode: 'refuse', type: 'folder' }) const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const file_id = resp.body.file_id as string | undefined if (file_id) return { file_id, error: '' } } else { DebugLog.mSaveWarning('ApiCreatNewForder err=' + parent_file_id + ' ' + (resp.code || '')) } if (resp.body?.code == 'QuotaExhausted.Drive') return { file_id: '', error: '网盘空间已满,无法创建' } if (resp.body?.code) return { file_id: '', error: resp.body?.code } return result } static async ApiTrashBatch(user_id: string, drive_id: string, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/recyclebin/trash', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id } }) return ApiBatchSuccess('放入回收站', batchList, user_id, '') } static async ApiDeleteBatch(user_id: string, drive_id: string, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/file/delete', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id } }) return ApiBatchSuccess('彻底删除', batchList, user_id, '') } static async ApiRenameBatch(user_id: string, drive_id: string, file_idList: string[], names: string[]): Promise<{ file_id: string; parent_file_id: string; name: string; isDir: boolean }[]> { const batchList = ApiBatchMaker2('/file/update', file_idList, names, (file_id: string, name: string) => { return { drive_id: drive_id, file_id: file_id, name: name, check_name_mode: 'refuse' } }) if (batchList.length == 0) return Promise.resolve([]) const successList: { file_id: string; parent_file_id: string; name: string; isDir: boolean }[] = [] const result = await ApiBatch(file_idList.length <= 1 ? '' : '批量重命名', batchList, user_id, '') result.reslut.map((t) => successList.push({ file_id: t.file_id!, name: t.name!, parent_file_id: t.parent_file_id!, isDir: t.type !== 'folder' })) return successList } static async ApiFavorBatch(user_id: string, drive_id: string, isfavor: boolean, ismessage: boolean, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/file/update', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id, custom_index_key: isfavor ? 'starred_yes' : '', starred: isfavor } }) return ApiBatchSuccess(ismessage ? (isfavor ? '收藏文件' : '取消收藏') : '', batchList, user_id, '') } static async ApiTrashCleanBatch(user_id: string, drive_id: string, ismessage: boolean, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/file/delete', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id } }) return ApiBatchSuccess(ismessage ? '从回收站删除' : '', batchList, user_id, '') } static async ApiTrashRestoreBatch(user_id: string, drive_id: string, ismessage: boolean, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/recyclebin/restore', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id } }) return ApiBatchSuccess(ismessage ? '从回收站还原' : '', batchList, user_id, '') } static async ApiFileColorBatch(user_id: string, drive_id: string, color: string, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/file/update', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id, description: color } }) return ApiBatchSuccess(color == '' ? '清除文件标记' : color == 'c5b89b8' ? '' : '标记文件', batchList, user_id, '') } static async ApiRecoverBatch(user_id: string, resumeList: { drive_id: string; file_id: string; content_hash: string; size: number; name: string }[]): Promise { const successList: string[] = [] if (!resumeList || resumeList.length == 0) return Promise.resolve(successList) const url = 'adrive/v1/file/resumeDeleted' const postData = JSON.stringify({ resume_file_list: resumeList }) const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const task_id = resp.body.task_id as string if (!user_id || !task_id) return [] for (let j = 0; j < 100; j++) { const url2 = 'adrive/v1/file/checkResumeTask' const resp2 = await AliHttp.Post(url2, { task_id }, user_id, '') if (AliHttp.IsSuccess(resp2.code)) { if (resp2.body.state == 'running') continue if (resp2.body.state == 'done') { const results = resp2.body.results as any[] if (results) { results.map((t: any) => { if (t.status && t.status == 200) successList.push(t.file_id) return true }) } return successList } } } } else if (resp.code && resp.code == 403) { if (resp.body?.code == 'UserNotVip') message.error('文件恢复功能需要开通阿里云盘会员') else message.error(resp.body?.code || '拒绝访问') } else { DebugLog.mSaveWarning('ApiRecoverBatch err=' + (resp.code || '')) message.error('操作失败') } return successList } static async ApiMoveBatch(user_id: string, drive_id: string, file_idList: string[], to_drive_id: string, to_parent_file_id: string): Promise { const batchList = ApiBatchMaker('/file/move', file_idList, (file_id: string) => { if (drive_id == to_drive_id) return { drive_id: drive_id, file_id: file_id, to_parent_file_id: to_parent_file_id, auto_rename: true } else return { drive_id: drive_id, file_id: file_id, to_drive_id: to_drive_id, to_parent_file_id: to_parent_file_id, auto_rename: true } }) return ApiBatchSuccess(file_idList.length <= 1 ? '移动' : '批量移动', batchList, user_id, '') } static async ApiCopyBatch(user_id: string, drive_id: string, file_idList: string[], to_drive_id: string, to_parent_file_id: string): Promise { const batchList = ApiBatchMaker('/file/copy', file_idList, (file_id: string) => { if (drive_id == to_drive_id) return { drive_id: drive_id, file_id: file_id, to_parent_file_id: to_parent_file_id, auto_rename: true } else return { drive_id: drive_id, file_id: file_id, to_drive_id: to_drive_id, to_parent_file_id: to_parent_file_id, auto_rename: true } }) return ApiBatchSuccess(file_idList.length <= 1 ? '复制' : '批量复制', batchList, user_id, '') } static async ApiGetFileBatch(user_id: string, drive_id: string, file_idList: string[]): Promise { const batchList = ApiBatchMaker('/file/get', file_idList, (file_id: string) => { return { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, office_thumbnail_process: 'image/resize,w_400/format,jpeg', image_thumbnail_process: 'image/resize,w_400/format,jpeg', image_url_process: 'image/resize,w_1920/format,jpeg', video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400' } }) const successList: IAliGetFileModel[] = [] const result = await ApiBatch('', batchList, user_id, '') result.reslut.map((t) => { if (t.body) successList.push(AliDirFileList.getFileInfo(t.body as IAliFileItem, 'download_url')) return true }) return successList } } ================================================ FILE: src/renderer/aliapi/fileicon.ts ================================================ export default function getFileIcon(category: string | undefined, ext: string | undefined, mimext: string | undefined, mime: string | undefined, size: number): string[] { if (!ext) ext = '' if (!mime) mime = '' if (!mimext) mimext = '' if (!category) category = 'others' ext = '.' + ext.toLowerCase().replace('.', '').trim() + '.' mimext = '.' + mimext.toLowerCase().replace('.', '').trim() + '.' switch (ext) { case '.txt.': return ['doc', 'iconfile-txt'] case '.rar.': return ['zip', 'iconfile-rar'] case '.rtf.': return ['doc', 'iconfile-doc'] case '.psd.': return ['others', 'iconfile-psd'] case '.torrent.': return ['others', 'iconfile-bt'] case '.iso.': return ['others', 'iconfile-iso'] case '.exe.': return ['others', 'iconfile-exe'] case '.apk.': return ['others', 'iconfile-apk'] case '.tar.': return ['others', 'iconfile-tar'] case '.7z.': return ['others', 'iconfile-7z'] case '.svg.': return ['image3', 'iconfile-image'] case '.azw.': return ['doc', 'iconwenjian'] case '.azw3.': return ['doc', 'iconwenjian'] case '.epub.': return ['doc', 'iconwenjian'] } if (category == 'zip' || mimext == '.zip.') { return ['zip', 'iconfile-zip'] } if (';.apng.avif.ico.webp.gif.'.indexOf(ext) > 0) { return ['image2', 'iconfile-img'] } if (category == 'image') { return ['image', 'iconfile-img'] } if (mime.startsWith('image/')) return ['image3', 'iconfile-image'] if (ext == '.pdf.' || mimext == '.pdf.') return ['doc', 'iconfile-pdf'] if (';.doc.docm.docx.dot.dotm.dotx.wps.wpt.'.indexOf(ext) > 0) return ['doc', 'iconfile-doc'] if (';.pot.ett.'.indexOf(ext) > 0) return ['doc2', 'iconfile-doc'] if ((mimext.startsWith('.txt') || mimext.startsWith('.doc') || mimext.startsWith('.ppt')) && ';.dps.dpt.potm.potx.pps.ppsm.ppsx.ppt.pptm.pptx.'.indexOf(ext) > 0) return ['doc', 'iconfile-ppt'] if ((mimext.startsWith('.txt') || mimext.startsWith('.xls')) && ';.xls.xlsx.et.xlsm.xlt.xltm.xltx.'.indexOf(ext) > 0) return ['doc', 'iconfile-xsl'] if (mime.startsWith('text/')) return ['others', 'iconfile_txt2'] if (ext == '.json.') return ['others', 'iconfile_txt2'] if (category == 'video') { return ['video', 'iconfile_video'] } if (mime.startsWith('video/')) return ['video2', 'iconfile_video'] if (ext == '.ts.' && size > 5 * 1024 * 1024) return ['video2', 'iconfile_video'] if (';.3iv.cpk.divx.hdv.fli.f4v.f4p.m2t.m2ts.mts.trp.mkv.mp4.mpg4.nsv.nut.nuv.rm.rmvb.vob.wmv.mk3d.hevc.yuv.y4m.mov.avi.flv.mpg.3gp.m4v.mpeg.asf.wmz.webm.pmp.mpga'.indexOf(ext) > 0) { return ['video2', 'iconfile_video'] } if (ext == '.mp3.' && category == 'audio') return ['audio', 'iconfile-mp3'] if (category == 'audio' && mimext != '.unknown.') { return ['audio', 'iconfile-audio'] } if (mime.startsWith('audio/')) return ['audio', 'iconfile-audio'] if (';.ape.aac.cda.dsf.dtshd.eac3.m1a.m2a.m4a.mka.mpa.mpc.opus.ra.tak.tta.wma.wv.'.indexOf(ext) > 0) { return ['audio2', 'iconfile-audio'] } return ['others', 'iconwenjian'] } ================================================ FILE: src/renderer/aliapi/filewalk.ts ================================================ import DebugLog from '../utils/debuglog' import AliHttp, { IUrlRespData } from './alihttp' import { IAliFileItem } from './alimodels' import AliDirFileList, { IAliFileResp } from './dirfilelist' export default class AliFileWalk { static async ApiWalkFileList(user_id: string, drive_id: string, dirID: string, dirName: string, order: string, type: string = '', max: number = 3000): Promise { const dir: IAliFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: dirID, dirName: dirName } if (!order) order = 'updated_at desc' const orders = order.split(' ') do { const isGet = await AliFileWalk._ApiWalkFileListOnePage(orders[0], orders[1], dir, type) if (isGet != true) { break } if (dir.items.length >= max && max > 0) { dir.next_marker = '' break } } while (dir.next_marker != '') return dir } private static async _ApiWalkFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string = '') { const url = 'v2/file/walk?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)' let postData = { drive_id: dir.m_drive_id, parent_file_id: dir.dirID, marker: dir.next_marker, limit: 1000, all: false, url_expire_sec: 14400, fields: 'thumbnail' // order_by: orderby, // order_direction: order.toUpperCase() } if (type) postData = Object.assign(postData, { type }) const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliFileWalk._FileListOnePage(dir, resp) } private static _FileListOnePage(dir: IAliFileResp, resp: IUrlRespData) { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker const isRecover = dir.dirID == 'recover' const downUrl = isRecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString() for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliFileItem if (dir.itemsKey.has(item.file_id)) continue const add = AliDirFileList.getFileInfo(item, downUrl) if (isRecover) add.description = item.content_hash dir.items.push(add) dir.itemsKey.add(item.file_id) } dir.punished_file_count += resp.body.punished_file_count || 0 return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code // message.warning('列出文件出错 ' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err) } dir.next_marker = 'error ' + resp.code console.log(resp) return false } } ================================================ FILE: src/renderer/aliapi/following.ts ================================================ import { humanTimeAgo } from '../utils/format' import message from '../utils/message' import DebugLog from '../utils/debuglog' import AliHttp, { IUrlRespData } from './alihttp' import { IAliOtherFollowingModel, IAliMyFollowingModel } from './alimodels' export interface IAliOtherFollowingResp { items: IAliOtherFollowingModel[] itemsKey: Set next_marker: string m_time: number m_user_id: string } export interface IAliMyFollowingResp { items: IAliMyFollowingModel[] itemsKey: Set next_marker: string m_time: number m_user_id: string } export default class AliFollowing { static async ApiOtherFollowingListAll(user_id: string): Promise { const dir: IAliOtherFollowingResp = { items: [], itemsKey: new Set(), next_marker: '', m_time: 0, m_user_id: user_id } do { const isGet = await AliFollowing.ApiOtherFollowingListOnePage(dir) if (isGet != true) { break } } while (dir.next_marker) return dir } static async ApiOtherFollowingListOnePage(dir: IAliOtherFollowingResp): Promise { const url = 'adrive/v1/timeline/user/recommend' let postData = { user_id: dir.m_user_id, limit: 100, order_by: 'updated_at', order_direction: 'DESC' } if (dir.next_marker) postData = Object.assign(postData, { marker: dir.next_marker }) const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliFollowing._OtherFollowingListOnePage(dir, resp) } private static _OtherFollowingListOnePage(dir: IAliOtherFollowingResp, resp: IUrlRespData): boolean { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker || '' for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliOtherFollowingModel if (dir.itemsKey.has(item.user_id)) continue const add = Object.assign({}, item) dir.items.push(add) dir.itemsKey.add(add.user_id) } return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出官方推荐列表出错' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_OtherFollowingListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_OtherFollowingListOnePage', err) } dir.next_marker = 'error ' + resp.code return false } static async ApiMyFollowingListAll(user_id: string): Promise { const dir: IAliMyFollowingResp = { items: [], itemsKey: new Set(), next_marker: '', m_time: 0, m_user_id: user_id } do { const isGet = await AliFollowing.ApiMyFollowingListOnePage(dir) if (isGet != true) { break } } while (dir.next_marker) return dir } static async ApiMyFollowingListOnePage(dir: IAliMyFollowingResp): Promise { const url = 'adrive/v1/member/list_following' const postData = { marker: dir.next_marker, limit: 100, order_by: 'updated_at', order_direction: 'DESC' } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliFollowing._MyFollowingListOnePage(dir, resp) } private static _MyFollowingListOnePage(dir: IAliMyFollowingResp, resp: IUrlRespData): boolean { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker || '' for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliMyFollowingModel if (dir.itemsKey.has(item.user_id)) continue const add = Object.assign({}, item) if (add.latest_messages && add.latest_messages.length > 0) { for (let j = 0; j < add.latest_messages.length; j++) { add.latest_messages[j].createdstr = humanTimeAgo(add.latest_messages[j].created) } } else { add.latest_messages = [ { action: '', content: { file_id_list: [], share: { popularity: 0, popularity_emoji: '', popularity_str: '', share_id: '', share_pwd: '' } }, created: 0, createdstr: '', creator: { avatar: '', description: '', is_following: false, nick_name: '', phone: '', user_id: '', follower_count: 0 }, creator_id: '', display_action: '', sequence_id: 0 } ] } dir.items.push(add) dir.itemsKey.add(add.user_id) } return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出订阅列表出错' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_MyFollowingListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_MyFollowingListOnePage', err) } dir.next_marker = 'error ' + resp.code return false } static async ApiSetFollowing(user_id: string, followingid: string, isFollowing: boolean, tip: boolean): Promise { if (!user_id || !followingid || !followingid) return let url = 'adrive/v1/member/follow_user' if (!isFollowing) url = 'adrive/v1/member/unfollow_user' const postData = JSON.stringify({ user_id: followingid }) const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { if (tip) message.success(isFollowing ? '订阅成功' : '取消订阅成功') } else { DebugLog.mSaveWarning('ApiSetFollowing err=' + followingid + ' ' + (resp.code || '')) message.error((isFollowing ? '订阅' : '取消订阅') + ' 操作失败,请稍后重试') } } static async ApiSetFollowingMarkRead(user_id: string, followingid: string): Promise { if (!user_id || !followingid) return false const url = 'adrive/v1/member/mark_read' const postData = JSON.stringify({ user_id: followingid }) const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return true } else { DebugLog.mSaveWarning('ApiSetFollowingMarkRead err=' + followingid + ' ' + (resp.code || '')) return false } } static async ApiOtherFollowingClassListAll() { const url = 'https://gitee.com/liupanxiaobaiyang/aliyunpan/raw/master/follow.json' const resp = await AliHttp.Get(url, '') return resp.body?.FollowList || [] } } ================================================ FILE: src/renderer/aliapi/models.ts ================================================ export interface IDownloadUrl { drive_id: string file_id: string expire_sec: number url: string size: number } export interface IVideoPreviewUrl { drive_id: string file_id: string expire_sec: number url: string duration: number width: number height: number urlFHD: string urlHD: string urlSD: string urlLD: string subtitles: { language: string url: string }[] } export interface IOfficePreViewUrl { drive_id: string file_id: string access_token: string preview_url: string } export interface IVideoXBTUrl { time: string url: string } export interface IUploadCreat { user_id: string drive_id: string file_id: string israpid: boolean isexist: boolean upload_id: string part_info_list: { upload_url: string part_number: number part_size: number isupload: boolean }[] errormsg: string } export interface IUploadInfo { token_type: string access_token: string sha1: string israpid: boolean isexist: boolean part_info_list: { upload_url: string part_number: number part_size: number isupload: boolean }[] } export interface IAliBatchResult { count: number async_task: { drive_id: string file_id: string task_id: string newdrive_id: string newfile_id: string }[] reslut: { id: string file_id?: string name?: string type?: string parent_file_id?: string share_id?: string share_pwd?: string share_url?: string expiration?: string share_name?: string body?: any }[] error: { id: string code: string message: string }[] } export interface IBatchResult { count: number task: { file_id: string task_id: string newdrive_id: string newfile_id: string }[] reslut: { id: string file_id: string }[] error: { id: string code: string message: string }[] } export interface IAliGetAlbumModel { album_id: string created_at: number description: string file_count: number image_count: number name: string owner: string updated_at: number video_count: number } export interface IAliUserDriveDetails { drive_used_size: number drive_total_size: number default_drive_used_size: number album_drive_used_size: number note_drive_used_size: number sbox_drive_used_size: number share_album_drive_used_size: number } export interface IAliUserDriveCapacity { type: string size: number sizeStr: string expired: string expiredstr: string description: string latest_receive_time: string /* "2022-05-02T00:50:51.379Z" */ } export interface IStateUploadFile { UploadID: string Info: { user_id: string localFilePath: string parent_file_id: string drive_id: string path: string name: string size: number sizeStr: string icon: string isDir: boolean isMiaoChuan: boolean sha1: string crc64: string } Upload: { DownState: string DownTime: number DownSize: number DownSpeed: number DownSpeedStr: string DownProcess: number IsStop: boolean IsDowning: boolean IsCompleted: boolean IsFailed: boolean failedCode: number failedMessage: string AutoTry: number upload_id: string file_id: string IsBreakExist: boolean } } ================================================ FILE: src/renderer/aliapi/server.tsx ================================================ import { B64decode, b64decode } from '../utils/format' import axios, { AxiosResponse } from 'axios' import Config from '../utils/config' import message from '../utils/message' import { IShareSiteModel, useServerStore } from '../store' import { Modal } from '@arco-design/web-vue' import { h } from 'vue' import { getAppNewPath, openExternal } from '../utils/electronhelper' import ShareDAL from '../share/share/ShareDAL' import DebugLog from '../utils/debuglog' const { writeFileSync, rmSync } = window.require('fs') export interface IServerRespData { state: string msg: string [k: string]: any } export default class ServerHttp { static baseapi = b64decode('aHR0cDovLzEyMS41LjE0NC44NDo1MjgyLw==') static async PostToServer(postData: any): Promise { postData.appVersion = Config.appVersion const str = JSON.stringify(postData) if (window.postdataFunc) { let enstr = '' try { enstr = window.postdataFunc(str) console.log(enstr) } catch { return { state: 'error', msg: '联网失败' } } return ServerHttp.Post(enstr).catch(() => { return { state: 'error', msg: '网络错误' } }) } else { return { state: 'error', msg: '程序错误' } } } static async Post(postData: any, isfirst = true): Promise { const url = ServerHttp.baseapi + 'xby2' // const url = "http://192.168.31.74:2018/" + 'xby2' return axios .post(url, postData, { responseType: 'arraybuffer', timeout: 30000, headers: {} }) .then((response: AxiosResponse) => { if (response.status != 200) return { state: 'error', msg: '网络错误' } const buff = response.data as ArrayBuffer const uint8array = new Uint8Array(buff) for (let i = 0, maxi = uint8array.byteLength; i < maxi; i++) { uint8array[i] ^= 9 + (i % 200) } const str = new TextDecoder().decode(uint8array) return JSON.parse(str) as IServerRespData }) .catch(() => { return { state: 'error', msg: '网络错误' } }) .then((resp) => { if (resp.state == 'error' && resp.msg == '网络错误' && isfirst == true) { return ServerHttp.Sleep(2000).then(() => { return ServerHttp.Post(postData, false) }) } else return resp }) } static Sleep(msTime: number) { return new Promise((resolve) => setTimeout( () => resolve({ success: true, time: msTime }), msTime ) ) } static configUrl = b64decode('aHR0cHM6Ly9naXRlZS5jb20vbGl1cGFueGlhb2JhaXlhbmcvYWxpeXVucGFuL3Jhdy9tYXN0ZXIvY29uZmlnMy4xLmpzb24=') static showVer = false static async CheckUpgrade(showUpgred: boolean): Promise { axios .get(ServerHttp.configUrl, { withCredentials: false, responseType: 'json', timeout: 30000 }) .then(async (response: AxiosResponse) => { console.log('CheckUpgrade', showUpgred, response) if (response.data.SIP) { const SIP = B64decode(response.data.SIP) if (SIP.length > 0) ServerHttp.baseapi = SIP } if (response.data.SSList) { const list: IShareSiteModel[] = [] for (let i = 0, maxi = response.data.SSList.length; i < maxi; i++) { const item = response.data.SSList[i] const add = { title: item.title, url: item.url, tip: item.tip } if (add.url.length > 0) list.push(add) } ShareDAL.SaveShareSite(list) } if (response.data.HELP) { useServerStore().mSaveHelpUrl(response.data.HELP) } if (showUpgred && response.data.ExeVer) { const v1 = Config.appVersion.replaceAll('v', '').replaceAll('.', '').trim() const v2 = response.data.ExeVer.replaceAll('v', '').replaceAll('.', '').trim() const info = response.data.VerInfo as string const verUrl = response.data.VerUrl || '' const appNewUrl = response.data.AppNewUrl || '' if (parseInt(v2) > parseInt(v1)) { if (appNewUrl) { message.info('检测到新版本 ' + response.data.ExeVer) const isDownloaed = await this.AutoDownload(B64decode(appNewUrl)) if (isDownloaed) return } if (ServerHttp.showVer == false) { ServerHttp.showVer = true Modal.confirm({ okText: '确认', cancelText: '取消', title: () => h('div', { innerHTML: '有新版可以升级' + response.data.ExeVer + '', class: { vermodalhead: true }, style: { minWidth: '540px' } }), mask: true, maskClosable: false, escToClose: false, alignCenter: true, simple: true, onOk: () => { if (verUrl.length > 0) openExternal(B64decode(verUrl)) }, onClose: () => { ServerHttp.showVer = false }, content: () => h('div', { innerHTML: info, class: { vermodal: true }, style: { minWidth: '540px' } }) }) } } else { message.info('已经是最新版 ' + response.data.ExeVer + ' 一般每周日晚8-10点发布新版') } } }) .catch((err: any) => { DebugLog.mSaveDanger('CheckUpgrade', err) }) } static async AutoDownload(appNewUrl: string): Promise { const appnew = getAppNewPath() return axios .get(appNewUrl, { withCredentials: false, responseType: 'arraybuffer', timeout: 60000, headers: { 'Cache-Control': 'no-cache', Pragma: 'no-cache', Expires: '0' } }) .then((response: AxiosResponse) => { writeFileSync(appnew, Buffer.from(response.data)) return true }) .catch(() => { rmSync(appnew, { force: true }) return false }) } } ================================================ FILE: src/renderer/aliapi/share.ts ================================================ import DebugLog from '../utils/debuglog' import { humanDateTime, humanExpiration, humanSize } from '../utils/format' import message from '../utils/message' import AliHttp, { IUrlRespData } from './alihttp' import ServerHttp from './server' import { ApiBatch, ApiBatchMaker, ApiBatchSuccess } from './utils' import { useSettingStore } from '../store' import { IAliShareItem, IAliShareAnonymous, IAliShareFileItem } from './alimodels' import getFileIcon from './fileicon' import { IAliBatchResult } from './models' export interface IAliShareFileResp { items: IAliShareFileItem[] itemsKey: Set punished_file_count: number next_marker: string m_user_id: string m_share_id: string dirID: string dirName: string } export interface UpdateShareModel { share_id: string share_pwd: string expiration: string share_name: string } export default class AliShare { static async ApiGetShareAnonymous(share_id: string): Promise { const share: IAliShareAnonymous = { shareinfo: { share_id: share_id, creator_id: '', creator_name: '', creator_phone: '', display_name: '', expiration: '', file_count: 0, share_name: '', created_at: '', updated_at: '', vip: '', is_photo_collection: false, album_id: '' }, shareinfojson: '', error: '解析分享链接失败' } if (!share_id) return share const url = 'adrive/v2/share_link/get_share_by_anonymous?share_id=' + share_id const postData = { share_id: share_id } const resp = await AliHttp.Post(url, postData, '', '') if (AliHttp.IsSuccess(resp.code)) { if (resp.body.creator_id) { share.shareinfo.share_id = share_id share.shareinfo.creator_id = resp.body.creator_id || '' share.shareinfo.creator_name = resp.body.creator_name || '' share.shareinfo.creator_phone = resp.body.creator_phone || '' share.shareinfo.display_name = resp.body.display_name || '' share.shareinfo.expiration = resp.body.expiration || '' share.shareinfo.file_count = resp.body.file_count || 0 share.shareinfo.share_name = resp.body.share_name || '' share.shareinfo.created_at = resp.body.created_at || '' share.shareinfo.updated_at = resp.body.updated_at || '' share.shareinfo.vip = resp.body.vip || '' share.shareinfo.is_photo_collection = resp.body.is_photo_collection || false share.shareinfo.album_id = resp.body.album_id || '' share.shareinfojson = JSON.stringify(resp.body) share.error = '' return share } } else { DebugLog.mSaveWarning('ApiGetShareAnonymous err=' + share_id + ' ' + (resp.code || '')) } if (resp.body?.code == 'ShareLink.Cancelled') share.error = '分享链接被取消分享了' else if (resp.body?.code == 'ShareLink.Expired') share.error = '分享链接过期失效了' else if (resp.body?.code == 'ShareLink.Forbidden') share.error = '分享链接违规禁止访问' else if (resp.body?.code) share.error = resp.body.code else share.error = '解析分享链接失败' return share } static async ApisSubscription(user_id: string, share_id: string): Promise { if (!user_id || !share_id) return false const url = 'adrive/v1/share_link/subscription/update' const postData = { share_id: share_id, update_last_seen: true } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return true } else { DebugLog.mSaveWarning('ApisSubscription err=' + share_id + ' ' + (resp.code || '')) } return false } static async ApiGetShareToken(share_id: string, pwd: string): Promise { if (!share_id) return ',分享链接错误' const url = 'v2/share_link/get_share_token' const postData = { share_id: share_id, share_pwd: pwd } let resp = await AliHttp.Post(url, postData, '', '') let isgetpwd = false if (resp.body?.code == 'InvalidResource.SharePwd') { if (useSettingStore().yinsiLinkPassword) { const serdata = await ServerHttp.PostToServer({ cmd: 'GetAliSharePwd', shareid: share_id }) if (serdata.password) { isgetpwd = true postData.share_pwd = serdata.password resp = await AliHttp.Post(url, postData, '', '') } } } if (resp.body?.code == 'InvalidResource.SharePwd') return ',提取码错误' if (resp.body?.code == 'ShareLink.Cancelled') return ',分享链接被取消分享了' if (resp.body?.code == 'ShareLink.Expired') return ',分享链接过期失效了' if (resp.body?.code == 'ShareLink.Forbidden') return ',分享链接违规禁止访问' if (resp.body?.code) return ',' + resp.body.code if (AliHttp.IsSuccess(resp.code)) { if (useSettingStore().yinsiLinkPassword && isgetpwd == false) ServerHttp.PostToServer({ cmd: 'PostAliShare', shareid: share_id, password: postData.share_pwd }) return (resp.body.share_token as string | undefined) || ',share_token错误' } else { DebugLog.mSaveWarning('ApiGetShareToken err=' + share_id + ' ' + (resp.code || '')) } return ',网络错误请重试' } static async ApiShareFileList(share_id: string, share_token: string, dirID: string): Promise { const dir: IAliShareFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: '', m_user_id: '', m_share_id: share_id, dirID: dirID, dirName: '' } do { const isGet = await AliShare.ApiShareFileListOnePage(dir, share_token) if (isGet != true) { break } } while (dir.next_marker) return dir } static async ApiShareFileListOnePage(dir: IAliShareFileResp, share_token: string): Promise { const url = 'adrive/v3/file/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)' let postData = { share_id: dir.m_share_id, parent_file_id: dir.dirID, limit: 100, url_expire_sec: 14400, fields: 'thumbnail', order_by: 'name', order_direction: 'DESC' } if (dir.next_marker) postData = Object.assign(postData, { marker: dir.next_marker }) const resp = await AliHttp.Post(url, postData, '', share_token) return AliShare._ShareFileListOnePage(dir, resp) } private static _ShareFileListOnePage(dir: IAliShareFileResp, resp: IUrlRespData): boolean { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliShareFileItem if (dir.itemsKey.has(item.file_id)) continue const add: IAliShareFileItem = { drive_id: item.drive_id, file_id: item.file_id, name: item.name, type: item.type, parent_file_id: item.parent_file_id, file_extension: item.file_extension || '', mime_extension: item.mime_extension || '', mime_type: item.mime_type || '', size: item.size || 0, category: item.category || '', punish_flag: item.punish_flag || 0, isDir: item.type == 'folder', sizeStr: item.type == 'folder' ? '' : humanSize(item.size), icon: getFileIcon(item.category, item.file_extension, item.mime_extension, item.mime_type, item.size)[1] } dir.items.push(add) dir.itemsKey.add(add.file_id) } dir.punished_file_count += resp.body.punished_file_count || 0 return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出分享链接内文件出错 ' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_ShareFileListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ShareFileListOnePage ' + dir.dirID, err) } dir.next_marker = 'error ' + resp.code return false } static async ApiCreatShare(user_id: string, drive_id: string, expiration: string, share_pwd: string, share_name: string, file_id_list: string[]): Promise { if (!user_id || !drive_id || file_id_list.length == 0) return '创建分享链接失败数据错误' const url = 'adrive/v2/share_link/create' const postData = JSON.stringify({ drive_id, expiration, share_pwd: share_pwd, share_name: share_name, file_id_list }) const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const item = resp.body as IAliShareItem const add: IAliShareItem = Object.assign({}, item, { first_file: undefined, icon: 'iconwenjian' }) if (item.created_at) add.created_at = humanDateTime(item.created_at) if (item.updated_at) add.updated_at = humanDateTime(item.updated_at) add.share_msg = humanExpiration(item.expiration) return add } else { DebugLog.mSaveWarning('ApiCreatShare err=' + (resp.code || '')) } if (resp.body?.code.startsWith('UserPunished')) return '账号分享行为异常,无法分享' else if (resp.body?.code == 'InvalidParameter.FileIdList') return '选择文件过多,无法分享' else if (resp.body?.message && resp.body.message.indexOf('size of file_id_list') >= 0) return '选择文件过多,无法分享' else if (resp.body?.code == 'FileShareNotAllowed') return '这个文件禁止分享' else if (resp.body?.code == 'FeatureTemporaryDisabled') return '分享功能维护中' else if (resp.body?.code) return resp.body.code.toString() else return '创建分享链接失败' } static async ApiCreatShareBatch(user_id: string, drive_id: string, expiration: string, share_pwd: string, file_id_list: string[]): Promise { const batchList: string[] = [] for (let i = 0, maxi = file_id_list.length; i < maxi; i++) { const postData: any = { body: { drive_id, expiration, share_pwd: share_pwd, file_id_list: [file_id_list[i]] }, headers: { 'Content-Type': 'application/json' }, id: file_id_list[i], method: 'POST', url: '/share_link/create' } batchList.push(JSON.stringify(postData)) } const result = await ApiBatch('', batchList, user_id, '') return result } static async ApiCancelShareBatch(user_id: string, share_idList: string[]): Promise { const batchList = ApiBatchMaker('/share_link/cancel', share_idList, (share_id: string) => { return { share_id: share_id } }) return ApiBatchSuccess(share_idList.length > 1 ? '批量取消分享' : '取消分享', batchList, user_id, '') } static async ApiUpdateShareBatch(user_id: string, share_idList: string[], expirationList: string[], share_pwdList: string[], share_nameList: string[] | undefined): Promise { if (!share_idList || share_idList.length == 0) return [] const batchList: string[] = [] if (share_nameList) { for (let i = 0, maxi = share_idList.length; i < maxi; i++) { batchList.push( JSON.stringify({ body: { share_id: share_idList[i], share_pwd: share_pwdList[i], expiration: expirationList[i], share_name: share_nameList[i] }, headers: { 'Content-Type': 'application/json' }, id: share_idList[i], method: 'POST', url: '/share_link/update' }) ) } } else { for (let i = 0, maxi = share_idList.length; i < maxi; i++) { batchList.push(JSON.stringify({ body: { share_id: share_idList[i], share_pwd: share_pwdList[i], expiration: expirationList[i] }, headers: { 'Content-Type': 'application/json' }, id: share_idList[i], method: 'POST', url: '/share_link/update' })) } } const successList: UpdateShareModel[] = [] const result = await ApiBatch(share_idList.length > 1 ? '批量更新分享链接' : '更新分享链接', batchList, user_id, '') result.reslut.map((t) => successList.push({ share_id: t.share_id!, share_pwd: t.share_pwd!, expiration: t.expiration!, share_name: t.share_name! } as UpdateShareModel)) return successList } static async ApiSaveShareFilesBatch(share_id: string, share_token: string, user_id: string, drive_id: string, parent_file_id: string, file_idList: string[]): Promise { if (!share_id || !share_token || !user_id || !drive_id || !parent_file_id) return 'error' if (!file_idList || file_idList.length == 0) return 'success' const batchList: string[] = [] for (let i = 0, maxi = file_idList.length; i < maxi; i++) { const postData = '{"body":{"share_id":"' + share_id + '","file_id_list":["' + // files[i] + '"],"file_id":"' + file_idList[i] + '","to_drive_id":"' + drive_id + '","to_parent_file_id":"' + parent_file_id + '","auto_rename":true},"headers":{"Content-Type":"application/json"},"id":"' + file_idList[i] + '","method":"POST","url":"/file/copy"}' batchList.push(postData) } const result = await ApiBatch('', batchList, user_id, share_token) if (result.count == file_idList.length) { if (result.async_task.length > 0) return 'async' else return 'success' } else { if (result.error.length > 0) { if (result.error[0].code == 'QuotaExhausted.Drive') return '网盘空间已满' else return result.error[0].code } return 'error' } } } ================================================ FILE: src/renderer/aliapi/sharelist.ts ================================================ import DebugLog from '../utils/debuglog' import { humanDateTime, humanExpiration, Sleep } from '../utils/format' import message from '../utils/message' import AliHttp, { IUrlRespData } from './alihttp' import { IAliShareItem } from './alimodels' import AliDirFileList from './dirfilelist' export interface IAliShareResp { items: IAliShareItem[] itemsKey: Set next_marker: string m_time: number m_user_id: string } export default class AliShareList { static async ApiShareListAll(user_id: string): Promise { const dir: IAliShareResp = { items: [], itemsKey: new Set(), next_marker: '', m_time: 0, m_user_id: user_id } do { const isGet = await AliShareList.ApiShareListOnePage(dir) if (isGet != true) { break } } while (dir.next_marker) return dir } static async ApiShareListOnePage(dir: IAliShareResp): Promise { const url = 'adrive/v3/share_link/list' const postData = { marker: dir.next_marker, creator: dir.m_user_id, include_canceled: false, order_by: 'created_at', order_direction: 'DESC' } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliShareList._ShareListOnePage(dir, resp) } static _ShareListOnePage(dir: IAliShareResp, resp: IUrlRespData): boolean { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker const downUrl = 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString() const timeNow = new Date().getTime() for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliShareItem if (dir.itemsKey.has(item.share_id)) continue let icon = 'iconwenjian' let first_file if (item.first_file) { first_file = AliDirFileList.getFileInfo(item.first_file, downUrl) icon = first_file.icon || 'iconwenjian' } const add = Object.assign({}, item, { first_file, icon }) as IAliShareItem if (!add.share_msg) add.share_msg = '' if (!add.share_name) add.share_name = 'share_name' if (!add.share_pwd) add.share_pwd = '' if (!add.preview_count) add.preview_count = 0 if (!add.download_count) add.download_count = 0 if (!add.save_count) add.save_count = 0 if (!add.expired) add.expired = false if (item.created_at) { add.created_at = humanDateTime(new Date(item.created_at).getTime()) } else { add.created_at = '' } add.share_msg = humanExpiration(item.expiration, timeNow) if (item.status == 'forbidden') add.share_msg = '分享违规' dir.items.push(add) dir.itemsKey.add(add.share_id) } return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出分享列表出错' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_ShareListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_ShareListOnePage', err) } dir.next_marker = 'error ' + resp.code return false } static async ApiShareListUntilShareID(user_id: string, share_id: string): Promise { const url = 'adrive/v3/share_link/list' const postData = { marker: '', creator: user_id, include_canceled: false, order_by: 'created_at', order_direction: 'DESC' } for (let j = 0; j < 10; j++) { const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliShareItem if (item.share_id == share_id) return true } } } catch {} await Sleep(500) } return false } } ================================================ FILE: src/renderer/aliapi/trash.ts ================================================ import DebugLog from '../utils/debuglog' import message from '../utils/message' import AliHttp, { IUrlRespData } from './alihttp' import { IAliFileItem } from './alimodels' import AliDirFileList, { IAliFileResp } from './dirfilelist' export default class AliTrash { static async ApiTrashFileListOnePageForClean(orderby: string, order: string, dir: IAliFileResp): Promise { const url = 'v2/recyclebin/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)' const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 100, all: false, url_expire_sec: 14400, fields: 'thumbnail', order_by: orderby, order_direction: order.toUpperCase() } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliTrash._FileListOnePage(dir, resp) } static async ApiFavorFileListOnePageForClean(orderby: string, order: string, dir: IAliFileResp): Promise { const url = 'v2/file/list_by_custom_index_key?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)' const postData = { drive_id: dir.m_drive_id, marker: dir.next_marker, limit: 100, url_expire_sec: 14400, fields: '*', order_by: orderby, order_direction: order.toUpperCase(), custom_index_key: 'starred_yes', parent_file_id: 'root' } const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliTrash._FileListOnePage(dir, resp) } static async ApiDirFileListNoLock(user_id: string, drive_id: string, dirID: string, dirName: string, order: string, type: string = '', max: number = 3000): Promise { const dir: IAliFileResp = { items: [], itemsKey: new Set(), punished_file_count: 0, next_marker: '', m_user_id: user_id, m_drive_id: drive_id, dirID: dirID, dirName: dirName } if (!order) order = 'updated_at desc' const orders = order.split(' ') do { const isGet = await AliTrash._ApiDirFileListOnePage(orders[0], orders[1], dir, type) if (isGet != true) { break } if (dir.items.length >= max && max > 0) { dir.next_marker = '' break } } while (dir.next_marker != '') return dir } static async _ApiDirFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string = ''): Promise { const url = 'adrive/v3/file/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)' let postData = { drive_id: dir.m_drive_id, parent_file_id: dir.dirID, marker: dir.next_marker, limit: 100, all: false, url_expire_sec: 14400, fields: '*', order_by: orderby, order_direction: order.toUpperCase() } if (type) postData = Object.assign(postData, { type }) const resp = await AliHttp.Post(url, postData, dir.m_user_id, '') return AliTrash._FileListOnePage(dir, resp) } static _FileListOnePage(dir: IAliFileResp, resp: IUrlRespData): boolean { try { if (AliHttp.IsSuccess(resp.code)) { dir.next_marker = resp.body.next_marker const isrecover = dir.dirID == 'recover' const downurl = isrecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString() for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const item = resp.body.items[i] as IAliFileItem if (dir.itemsKey.has(item.file_id)) continue const add = AliDirFileList.getFileInfo(item, downurl) if (isrecover) add.description = item.content_hash dir.items.push(add) dir.itemsKey.add(item.file_id) } dir.punished_file_count = resp.body.punished_file_count || 0 return true } else if (resp.code == 404) { dir.items.length = 0 dir.next_marker = '' return true } else if (resp.body && resp.body.code) { dir.items.length = 0 dir.next_marker = resp.body.code message.warning('列出文件出错 ' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err) } dir.next_marker = 'error ' + resp.code return false } } ================================================ FILE: src/renderer/aliapi/upload.ts ================================================ import DebugLog from '../utils/debuglog' import AliHttp from './alihttp' import { IUploadCreat, IUploadInfo } from './models' export default class AliUpload { static async UploadCreatFileWithPreHash(user_id: string, drive_id: string, parent_file_id: string, name: string, fileSize: number, prehash: string, check_name_mode: string): Promise { const result: IUploadCreat = { user_id, drive_id, israpid: false, isexist: false, upload_id: '', file_id: '', part_info_list: [], errormsg: '' } if (!user_id || !drive_id || !parent_file_id || !name) { result.errormsg = '创建文件失败(数据错误)' return result } const url = 'adrive/v2/file/createWithFolders' const postData: { drive_id: string parent_file_id: string name: string type: string check_name_mode: string size: number pre_hash: string part_info_list: { part_number: number; part_size: number }[] ignore_rapid?: boolean } = { drive_id, parent_file_id: parent_file_id, name: name, type: 'file', check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode, size: fileSize, pre_hash: prehash, part_info_list: [] } let partSize = 10485760 if (fileSize > 0) { let partIndex = 0 while (fileSize > partSize * 8000) partSize = partSize + 10485760 while (partIndex * partSize < fileSize) { postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize }) partIndex++ } postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize } const resp = await AliHttp.Post(url, postData, user_id, '') if (typeof resp.body === 'object' && JSON.stringify(resp.body).indexOf('file size is exceed') > 0) { result.errormsg = '创建文件失败(单文件最大100GB/2TB)' return result } if (resp.body && resp.body.code) { if (resp.body?.code == 'PreHashMatched') { result.errormsg = 'PreHashMatched' } else if (resp.body?.code == 'QuotaExhausted.Drive') { result.errormsg = '出错暂停,网盘空间已满' } else { result.errormsg = resp.body?.code || '创建失败,网络错误' DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name) } return result } if (AliHttp.IsSuccess(resp.code)) { result.file_id = resp.body.file_id if (resp.body.exist) { if (check_name_mode == 'ignore') { await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {}) return await AliUpload.UploadCreatFileWithPreHash(user_id, drive_id, parent_file_id, name, fileSize, prehash, check_name_mode) } else { result.errormsg = '出错暂停,网盘内有重名文件' } } result.isexist = resp.body.exist || false result.israpid = false result.upload_id = resp.body.upload_id || '' if (resp.body.part_info_list && resp.body.part_info_list.length > 0) { const part_info_list = resp.body.part_info_list for (let i = 0, maxi = part_info_list.length; i < maxi; i++) { const item = part_info_list[i] result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false }) } } return result } else { DebugLog.mSaveWarning('UploadCreatFileWithFolders err=' + (resp.code || '')) result.errormsg = '创建文件失败' + resp.code.toString() return result } } static async UploadCreatFileWithFolders(user_id: string, drive_id: string, parent_file_id: string, name: string, fileSize: number, hash: string, proof_code: string, check_name_mode: string): Promise { const result: IUploadCreat = { user_id, drive_id, israpid: false, isexist: false, upload_id: '', file_id: '', part_info_list: [], errormsg: '' } if (!user_id || !drive_id || !parent_file_id || !name) { result.errormsg = '创建文件失败(数据错误)' return result } const url = 'adrive/v2/file/createWithFolders' const postData: { drive_id: string parent_file_id: string name: string type: string check_name_mode: string size: number content_hash?: string content_hash_name?: string proof_code?: string proof_version?: string part_info_list: { part_number: number; part_size: number }[] ignore_rapid?: boolean } = { drive_id, parent_file_id: parent_file_id, name: name, type: 'file', check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode, size: fileSize, part_info_list: [] } if (hash) { postData.content_hash = hash.toUpperCase() postData.content_hash_name = 'sha1' postData.proof_version = 'v1' postData.proof_code = proof_code } let partSize = 10485760 if (fileSize > 0) { let partIndex = 0 while (fileSize > partSize * 8000) partSize = partSize + 10485760 while (partIndex * partSize < fileSize) { postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize }) partIndex++ } postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize } const resp = await AliHttp.Post(url, postData, user_id, '') if (typeof resp.body === 'object' && JSON.stringify(resp.body).indexOf('file size is exceed') > 0) { result.errormsg = '创建文件失败(单文件最大100GB/2TB)' return result } if (resp.body && resp.body.code) { if (resp.body?.code == 'QuotaExhausted.Drive') { result.errormsg = '出错暂停,网盘空间已满' } else if (resp.body?.code == 'InvalidRapidProof') { result.errormsg = resp.body.code DebugLog.mSaveDanger('InvalidRapidProof', name) } else { result.errormsg = resp.body?.code || '创建失败,网络错误' DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name) } return result } if (AliHttp.IsSuccess(resp.code)) { result.file_id = resp.body.file_id if (resp.body.exist) { const issame = await AliUpload.UploadFileCheckHash(user_id, drive_id, result.file_id, hash) if (issame) { result.errormsg = '' } else { if (check_name_mode == 'ignore') { await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {}) return await AliUpload.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, name, fileSize, hash, proof_code, check_name_mode) } else { result.errormsg = '出错暂停,网盘内有重名文件' } } } result.isexist = resp.body.exist || false result.israpid = result.israpid || resp.body.rapid_upload || false result.upload_id = resp.body.upload_id || '' if (resp.body.part_info_list && resp.body.part_info_list.length > 0) { const part_info_list = resp.body.part_info_list for (let i = 0, maxi = part_info_list.length; i < maxi; i++) { const item = part_info_list[i] result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false }) } } return result } else { DebugLog.mSaveWarning('UploadCreatFileWithFolders err=' + (resp.code || '')) result.errormsg = '创建文件失败' + resp.code.toString() return result } } static async UploadFileCheckHash(user_id: string, drive_id: string, file_id: string, hash: string): Promise { if (!user_id || !drive_id || !file_id) return false const url = 'v2/file/get?jsonmask=content_hash' const postData = { drive_id: drive_id, file_id: file_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code) && resp.body.content_hash) { const content_hash = resp.body.content_hash.toUpperCase() hash = hash.toUpperCase() return hash === content_hash } else { DebugLog.mSaveWarning('UploadFileCheckHash err=' + (resp.code || '')) return false } } static async UploadFileDelete(user_id: string, drive_id: string, file_id: string, permanently: boolean = false): Promise { if (!user_id || !drive_id || !file_id) return false const url = 'v2/recyclebin/trash' const postData = { drive_id: drive_id, file_id: file_id, permanently } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { return true } else { DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || '')) return false } } static async UploadFileComplete(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, fileSha1: string): Promise { if (!user_id || !drive_id || !file_id || !upload_id) return false const url = 'v2/file/complete' const postData = { drive_id: drive_id, upload_id: upload_id, file_id: file_id } let resp = await AliHttp.Post(url, postData, user_id, '') if (resp.code == 400 || resp.code == 429) { resp = await AliHttp.Post(url, postData, user_id, '') } if (AliHttp.IsSuccess(resp.code)) { if (resp.body.size == fileSize) { if (fileSha1) { if (resp.body.content_hash && resp.body.content_hash == fileSha1) { return true } else { await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {}) DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现SHA1不一致,删除已上传的文件,重新上传') return false } } else if (fileSize < 10485760) { return true } else { return true } } else { await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {}) DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现大小不一致,删除已上传的文件,重新上传') return false } } else { DebugLog.mSaveDanger('UploadFileComplete', '合并文件时出错' + resp.code + ' ' + JSON.stringify(resp.header || {}) + ' ' + JSON.stringify(resp.body || {})) return false } } static async UploadFilePartUrl(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> { const url = 'v2/file/get_upload_url' const postData: { drive_id: string upload_id: string file_id: string part_info_list: { part_number: number; part_size: number }[] } = { drive_id: drive_id, upload_id: upload_id, file_id: file_id, part_info_list: [] } let partIndex = 0 let partSize = 10485760 while (fileSize > partSize * 8000) partSize = partSize + 10485760 while (partIndex * partSize < fileSize) { postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize }) partIndex++ } postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize const resp = await AliHttp.Post(url, postData, user_id, '') if (resp.code >= 600 && resp.code <= 610) { return 'neterror' } if (AliHttp.IsSuccess(resp.code)) { if (resp.body.part_info_list && resp.body.part_info_list.length > 0) { const part_info_list = resp.body.part_info_list if (uploadInfo.part_info_list.length == 0) { for (let i = 0, maxi = part_info_list.length; i < maxi; i++) { const item = part_info_list[i] uploadInfo.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false }) } } else { for (let i = 0, maxi = part_info_list.length; i < maxi; i++) { const item = part_info_list[i] uploadInfo.part_info_list[item.part_number - 1].upload_url = item.upload_url } } } return 'success' } else { uploadInfo.part_info_list = [] DebugLog.mSaveWarning('UploadFilePartUrl err=' + upload_id + ' ' + (resp.code || '')) return 'error' } } static async UploadFileListUploadedParts(user_id: string, drive_id: string, file_id: string, upload_id: string, part_number_marker: number, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> { if (!user_id || !drive_id || !file_id || !upload_id) return 'error' const url = 'v2/file/list_uploaded_parts' const postData = { drive_id: drive_id, upload_id: upload_id, file_id: file_id, part_number_marker /* 1开始 */ } const resp = await AliHttp.Post(url, postData, user_id, '') if (resp.code >= 600 && resp.code <= 610) { return 'neterror' } if (AliHttp.IsSuccess(resp.code)) { if (resp.body.uploaded_parts && resp.body.uploaded_parts.length > 0) { const uploaded_parts = resp.body.uploaded_parts for (let i = 0, maxi = uploaded_parts.length; i < maxi; i++) { const item = uploaded_parts[i] const part_number = item.part_number const uploadpart = uploadInfo.part_info_list[part_number - 1] if (uploadpart.part_size != item.part_size) { DebugLog.mSaveDanger('list_uploaded_parts', '分片数据错误 uploadpart=' + uploadpart.part_size + ' item=' + item.part_size) return 'error' } uploadInfo.part_info_list[part_number - 1].isupload = true } } if (resp.body.next_part_number_marker && parseInt(resp.body.next_part_number_marker) > 0) { const next = parseInt(resp.body.next_part_number_marker) await AliUpload.UploadFileListUploadedParts(user_id, drive_id, file_id, upload_id, next, uploadInfo).catch(() => {}) } return 'success' } else { DebugLog.mSaveWarning('UploadFileListUploadedParts err=' + upload_id + ' ' + (resp.code || '')) return 'error' } } static isNetworkError(e: Error): boolean { return e.message == 'Network Error' || e.message.includes('socket hang up') || e.message.includes('getaddrinfo ENOTFOUND') || e.message.includes('timeout of') || e.message.includes('connect ECONNRESET') || e.message.includes('connect ETIMEDOUT') || e.message.includes('EPIPE') } } ================================================ FILE: src/renderer/aliapi/uploaddisk.ts ================================================ import { IUploadingUI } from '../utils/dbupload' import DebugLog from '../utils/debuglog' import { OpenFileHandle } from '../utils/filehelper' import { FileHandle, FileReadResult } from 'fs/promises' import { IUploadInfo } from './models' import AliUpload from './upload' import HttpsProxyAgent from 'https-proxy-agent' import { SocksProxyAgent } from 'socks-proxy-agent' import { useSettingStore } from '../store' import DBCache from '../utils/dbcache' import UserDAL from '../user/userdal' import { Sleep } from '../utils/format' import AliUploadHashPool from './uploadhashpool' const nodehttps = window.require('https') const path = window.require('path') const filePosMap = new Map() let UploadSpeedTotal = 0 export default class AliUploadDisk { static async UploadOneFile(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise { if (uploadInfo.part_info_list.length > 1) return AliUploadDisk.UploadOneFileBig(uploadInfo, fileui) const upload_url = uploadInfo.part_info_list[0].upload_url const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileHandle.error) return fileHandle.error filePosMap.set(fileui.UploadID, 0) let isok = '' for (let i = 0; i < 3; i++) { isok = await AliUploadDisk.UploadOneFilePartNode(fileui.user_id, fileui.UploadID, fileHandle.handle, 0, fileui.File.size, upload_url) if (isok == 'success') { break } } if (fileHandle.handle) await fileHandle.handle.close() return AliUpload.UploadFileComplete(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo.sha1) .then((isSuccess) => { fileui.File.uploaded_file_id = fileui.Info.up_file_id fileui.File.uploaded_is_rapid = false fileui.Info.up_file_id = '' fileui.Info.up_upload_id = '' if (isSuccess) return 'success' else return '合并文件时出错,请重试' }) .catch((err: any) => { DebugLog.mSaveDanger('合并文件时出错', err) return '合并文件时出错,请重试' }) } static async UploadOneFileBig(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise { filePosMap.set(fileui.UploadID, 0) const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileHandle.error) return fileHandle.error const fileSize = fileui.File.size for (let i = 0, maxi = uploadInfo.part_info_list.length; i < maxi; i++) { let part = uploadInfo.part_info_list[i] const partStart = (part.part_number - 1) * part.part_size const partEnd = partStart + part.part_size const part_size = partEnd > fileSize ? fileSize - partStart : part.part_size if (part.isupload) { filePosMap.set(fileui.UploadID, partStart + part_size) } else { const url = part.upload_url let expires = url.substring(url.indexOf('x-oss-expires=') + 'x-oss-expires='.length) expires = expires.substring(0, expires.indexOf('&')) const lastTime = parseInt(expires) - Date.now() / 1000 if (lastTime < 5 * 60) { await AliUpload.UploadFilePartUrl(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo).catch(() => {}) if (uploadInfo.part_info_list.length == 0) return '获取分片信息失败,请重试' part = uploadInfo.part_info_list[i] } let isok = '' for (let j = 0; j < 3; j++) { isok = await AliUploadDisk.UploadOneFilePartNode(fileui.user_id, fileui.UploadID, fileHandle.handle, partStart, part_size, part.upload_url) // isok = await AliUploadDisk.UploadOneFilePartNodeXHR(file.File.user_id, file.UploadID, fileHandle.handle, partStart, part_size, part.upload_url) if (isok == 'success') { part.isupload = true break } if (!fileui.IsRunning) break } if (!fileui.IsRunning) break if (part.isupload == false) { if (fileHandle.handle) await fileHandle.handle.close() return isok } } } if (fileHandle.handle) await fileHandle.handle.close() if (!fileui.IsRunning) return '已暂停' for (let i = 0, maxi = uploadInfo.part_info_list.length; i < maxi; i++) { if (uploadInfo.part_info_list[i].isupload == false) { return '有分片上传失败,请重试' } } if (!uploadInfo.sha1) { if (fileui.File.size >= 1024000) { const prehash = await AliUploadHashPool.GetFilePreHash(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileui.File.size >= 10240000 && !prehash.startsWith('error')) { uploadInfo.sha1 = await DBCache.getFileHash(fileui.File.size, fileui.File.mtime, prehash, path.basename(fileui.File.name)) } } } return AliUpload.UploadFileComplete(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo.sha1) .then((isSuccess) => { if (isSuccess) return 'success' else return '合并文件时出错,请重试' }) .catch((err: any) => { DebugLog.mSaveDanger('合并文件时出错', err) return '合并文件时出错,请重试' }) } static UploadOneFilePartNode(user_id: string, UploadID: number, fileHandle: FileHandle, partStart: number, partSize: number, upload_url: string): Promise { return new Promise(async (resolve) => { const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { resolve('找不到上传token,请重试') return } let option = { method: 'PUT', strictSSL: false, rejectUnauthorized: false, timeout: 15000 , headers: { 'Content-Type': '' , 'Content-Length': partSize, 'Transfer-Encoding': 'chunked' , Authorization: token.token_type + ' ' + token.access_token, Connection: 'keep-alive' } } const settingStore = useSettingStore() const proxy = settingStore.proxyUseProxy ? settingStore.getProxy() : undefined if (proxy) { if (settingStore.proxyType.startsWith('http')) { const agenth = HttpsProxyAgent(proxy) option = Object.assign(option, { agent: agenth }) } else { const agents = new SocksProxyAgent(proxy) option = Object.assign(option, { agent: agents }) } } const winfo = { UploadID, isstop: false, partSize, partStart, buff: Buffer.alloc(40960) } const req = nodehttps.request(upload_url, option, function (res: any) { let _data = '' res.on('data', function (chunk: string) { _data += chunk }) res.on('end', function () { winfo.isstop = true if (res.statusCode == 200) { resolve('success') } else if (res.statusCode == 409 && _data.indexOf('PartAlreadyExist') > 0) { resolve('success') } else { DebugLog.mSaveDanger('分片上传失败,稍后重试' + res.statusCode) resolve('分片上传失败,稍后重试' + res.statusCode) } }) }) req.on('error', (error: any) => { DebugLog.mSaveWarning('分片上传失败,稍后重试', error) winfo.isstop = true let message = error.message || error.code || '网络错误' message = message.replace('A "socket" was not created for HTTP request before 15000ms', '网络连接超时失败') resolve('分片上传失败,稍后重试' + message) }) while (winfo.partSize > 0 && winfo.isstop == false) { const result = await AliUploadDisk._WriteToRequest(req, fileHandle, winfo) if (result != 'success') { resolve('读取文件数据失败,请重试') break } } req.end() }) } static async _WriteToRequest(req: any, fileHandle: FileHandle, winfo: { UploadID: number; isstop: boolean; partSize: number; partStart: number; buff: Buffer }): Promise { return new Promise((resolve) => { try { const redLen = Math.min(40960, winfo.partSize) if (redLen != winfo.buff.length) winfo.buff = Buffer.alloc(redLen) fileHandle .read(winfo.buff, 0, redLen, winfo.partStart) .then((rbuff: FileReadResult) => { if (redLen == rbuff.bytesRead) { winfo.partStart += redLen winfo.partSize -= redLen const uploadpos = winfo.partStart req.write(rbuff.buffer, async function () { filePosMap.set(winfo.UploadID, uploadpos) UploadSpeedTotal += redLen window.speedLimte -= redLen for (let i = 0; i < 10; i++) { if (window.speedLimte <= 0) await Sleep(100) else break } resolve('success') }) } else { winfo.isstop = true resolve('读取文件数据失败,请重试') } }) .catch(() => { winfo.isstop = true resolve('读取文件数据失败,请重试') }) } catch { winfo.isstop = true resolve('读取文件数据失败,请重试') } }) } static UploadOneFilePartNodeXHR(user_id: string, UploadID: number, fileHandle: FileHandle, partStart: number, partSize: number, upload_url: string): Promise { return new Promise(async (resolve) => { const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { resolve('找不到上传token,请重试') return } const winfo = { UploadID, isstop: false, partSize: partSize, partStart: partStart, buff: Buffer.alloc(40960) } const client = new XMLHttpRequest() client.open('PUT', upload_url) client.timeout = 15000 client.setRequestHeader('ContenpartSize', partSize.toString()) client.setRequestHeader('Content-Type', '') client.onreadystatechange = function () { switch (client.readyState) { case 1: // OPENED // do something break case 2: // HEADERS_RECEIVED // do something break case 3: // LOADING // do something break case 4: // DONE // do something break } } client.upload.onprogress = function updateProgress(event) { if (event.lengthComputable) { const completedPercent = event.loaded / event.total console.log('onprogress', event, completedPercent) filePosMap.set(winfo.UploadID, partStart + event.loaded) } } client.onabort = function () { resolve('用户暂停') } client.ontimeout = function () { resolve('网络超时') } client.onerror = function () { resolve('网络出错') } client.onloadend = function () { if ((client.status >= 200 && client.status < 300) || client.status == 409) { resolve('success') } else { resolve('分片上传失败,稍后重试' + client.status) DebugLog.mSaveDanger('分片上传失败,稍后重试' + client.status) } } const data = await this._ReadPartBuffer(fileHandle, winfo) if (data != 'success') resolve(data) else { try { client.send(winfo.buff) } catch (err: any) { console.log('send', err) resolve('联网发送失败,请重试') } } }) } static async _ReadPartBuffer(fileHandle: FileHandle, winfo: { UploadID: number; isstop: boolean; partSize: number; partStart: number; buff: Buffer }): Promise { return new Promise((resolve) => { try { const redLen = winfo.partSize if (redLen != winfo.buff.length) winfo.buff = Buffer.alloc(redLen) fileHandle .read(winfo.buff, 0, redLen, winfo.partStart) .then((rbuff: FileReadResult) => { if (redLen == rbuff.bytesRead) { resolve('success') } else { winfo.isstop = true resolve('读取文件数据失败,请重试') } }) .catch(() => { winfo.isstop = true resolve('读取文件数据失败,请重试') }) } catch { winfo.isstop = true resolve('读取文件数据失败,请重试') } }) } static GetFileUploadSpeed(UploadID: number): number { return filePosMap.get(UploadID) || 0 } static DelFileUploadSpeed(UploadID: number): void { filePosMap.delete(UploadID) } static GetFileUploadSpeedTotal(): number { const speed = UploadSpeedTotal + 0 UploadSpeedTotal = 0 return speed } } ================================================ FILE: src/renderer/aliapi/uploadhash.ts ================================================ import { Sleep } from '../utils/format' import { IUploadingUI } from '../utils/dbupload' import { OpenFileHandle } from '../utils/filehelper' import DBCache from '../utils/dbcache' const path = window.require('path') const crypto = window.require('crypto') const os = window.require('os') const CPU = Math.min(8, Math.max(4, os.cpus().length / 2)) const sha1PosMap = new Map() export default class AliUploadHash { static async GetBuffHashProof(access_token: string, buff: Buffer): Promise<{ sha1: string; proof_code: string }> { if (buff.length == 0) return { sha1: 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709', proof_code: '' } let hash = crypto.createHash('sha1').update(buff).digest('hex') hash = hash.toUpperCase() const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(buff.length)) const end = Math.min(start + 8, buff.length) const buffb = buff.slice(start, end) const proof_code = buffb.toString('base64') return { sha1: hash, proof_code } } static async GetFilePreHash(filePath: string): Promise { let hash = '' const fileHandle = await OpenFileHandle(filePath) if (fileHandle.error) return 'error' + fileHandle.error if (fileHandle.handle) { const buff = Buffer.alloc(1024) await fileHandle.handle.read(buff, 0, buff.length, null) hash = crypto.createHash('sha1').update(buff).digest('hex') hash = hash.toUpperCase() await fileHandle.handle.close() } else { hash = 'error读取文件失败' } return hash } static async GetFileHashProof(prehash: string, access_token: string, fileui: IUploadingUI): Promise<{ sha1: string; proof_code: string; error: string }> { let hash = '' let proof_code = '' let error = '' const size = fileui.File.size if (size == 0) return { sha1: 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709', proof_code: '', error: '' } if (size > 1024000) { return this.GetFileHashProofWorker(prehash, access_token, fileui, size > 1024 * 1024 * 300) } const sha1 = crypto.createHash('sha1') const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileHandle.error) { return { sha1: 'error', proof_code: '', error: fileHandle.error } } if (fileHandle.handle) { const buff = Buffer.alloc(1024 * 1024) while (true) { if (!fileui.IsRunning) break const len = await fileHandle.handle.read(buff, 0, buff.length, null) if (len.bytesRead > 0 && len.bytesRead == buff.length) { sha1.update(buff) } else if (len.bytesRead > 0) { sha1.update(buff.slice(0, len.bytesRead)) } if (len.bytesRead <= 0) break } if (fileui.IsRunning) { hash = sha1.digest('hex') hash = hash.toUpperCase() const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(size)) const end = Math.min(start + 8, size) const buffb = Buffer.alloc(end - start) await fileHandle.handle.read(buffb, 0, buffb.length, start) proof_code = buffb.toString('base64') error = '' } else { hash = 'error' proof_code = '' error = '' } await fileHandle.handle.close() return { sha1: hash, proof_code, error } } else { return { sha1: 'error', proof_code: '', error: '读取文件失败' } } } static async GetFileHashProofWorker(prehash: string, access_token: string, fileui: IUploadingUI, needSleep: boolean): Promise<{ sha1: string; proof_code: string; error: string }> { let hash = '' let proof_code = '' let error = '' const size = fileui.File.size if (size == 0) return { sha1: 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709', proof_code: '', error: '' } if (fileui.File.size >= 10240000 && !prehash.startsWith('error')) { const sha1 = await DBCache.getFileHash(fileui.File.size, fileui.File.mtime, prehash, path.basename(fileui.File.name)) if (sha1) { const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileHandle.error) { return { sha1: 'error', proof_code: '', error: fileHandle.error } } const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(size)) const end = Math.min(start + 8, size) const buffb = Buffer.alloc(end - start) await fileHandle.handle.read(buffb, 0, buffb.length, start) await fileHandle.handle.close() const proof_code = buffb.toString('base64') return { sha1, proof_code, error: '' } } } if (needSleep) { fileui.Info.failedMessage = '等待计算sha1' while (sha1PosMap.size >= CPU) { await Sleep(200) } fileui.Info.failedMessage = '' } sha1PosMap.set(fileui.UploadID, 0) fileui.Info.uploadSize = 0 const worker: any = new Worker('./sha1filework.js') await new Promise((resolve) => { worker.addEventListener('message', (event: any) => { if (event.data.hash == 'sha1') { if (event.data.readlen) { if (!fileui.IsRunning) worker.postMessage({ stop: true }) sha1PosMap.set(fileui.UploadID, event.data.readlen as number) fileui.File.size = event.data.size as number } if (event.data.sha1) { hash = event.data.sha1 proof_code = event.data.proof_code error = event.data.error resolve() } } }) worker.addEventListener('error', function (event: any) { hash = 'error' proof_code = '' error = event.data.error resolve() }) worker.postMessage({ hash: 'sha1', localFilePath: path.join(fileui.localFilePath, fileui.File.partPath), access_token }) }) .catch((err: any) => { error = err.message || 'workercatch' }) .then(() => { sha1PosMap.delete(fileui.UploadID) worker.postMessage({ close: true }) }) fileui.Info.uploadSize = 0 if (!fileui.IsRunning) return { sha1: 'error', proof_code: '', error: '' } if (hash != 'error' && prehash) { DBCache.saveFileHash({ size: fileui.File.size, mtime: fileui.File.mtime, presha1: prehash, sha1: hash, name: path.basename(fileui.File.name) }) } return { sha1: hash, proof_code, error } } static GetFileHashProofSpeed(UploadID: number): number { return sha1PosMap.get(UploadID) || 0 } } ================================================ FILE: src/renderer/aliapi/uploadhashpool.ts ================================================ import { IUploadingUI } from '../utils/dbupload' import { OpenFileHandle } from '../utils/filehelper' import DBCache from '../utils/dbcache' import Sha1WorkerPool from '../utils/sha1workerpool' const path = window.require('path') const crypto = window.require('crypto') const sha1PosMap = new Map() const sha1Pool = new Sha1WorkerPool() export default class AliUploadHashPool { static GetFileHashProofSpeed(UploadID: number) { return sha1PosMap.get(UploadID) || 0 } static async GetBuffHashProof(access_token: string, buff: Buffer): Promise<{ sha1: string; proof_code: string }> { if (buff.length == 0) return { sha1: 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709', proof_code: '' } let hash = crypto.createHash('sha1').update(buff).digest('hex') hash = hash.toUpperCase() const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(buff.length)) const end = Math.min(start + 8, buff.length) const buffb = buff.slice(start, end) const proof_code = buffb.toString('base64') return { sha1: hash, proof_code } } static async GetFilePreHash(filePath: string): Promise { let hash = '' const fileHandle = await OpenFileHandle(filePath) if (fileHandle.error) return 'error' + fileHandle.error if (fileHandle.handle) { const buff = Buffer.alloc(1024) await fileHandle.handle.read(buff, 0, buff.length, null) hash = crypto.createHash('sha1').update(buff).digest('hex') hash = hash.toUpperCase() await fileHandle.handle.close() } else { hash = 'error读取文件失败' } return hash } static async GetFileHashProofWorker(prehash: string, access_token: string, fileui: IUploadingUI): Promise<{ sha1: string; proof_code: string; error: string }> { let hash = '' let proof_code = '' let error = '' const size = fileui.File.size if (size == 0) return { sha1: 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709', proof_code: '', error: '' } if (fileui.File.size >= 10240000 && !prehash.startsWith('error')) { const sha1 = await DBCache.getFileHash(fileui.File.size, fileui.File.mtime, prehash, path.basename(fileui.File.name)) if (sha1) { const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath)) if (fileHandle.error) { return { sha1: 'error', proof_code: '', error: fileHandle.error } } const m = unescape(encodeURIComponent(access_token)) const buffa = Buffer.from(m) const md5a = crypto.createHash('md5').update(buffa).digest('hex') const start = Number(BigInt('0x' + md5a.substr(0, 16)) % BigInt(size)) const end = Math.min(start + 8, size) const buffb = Buffer.alloc(end - start) await fileHandle.handle.read(buffb, 0, buffb.length, start) await fileHandle.handle.close() const proof_code = buffb.toString('base64') return { sha1, proof_code, error: '' } } } sha1PosMap.set(fileui.UploadID, 0) fileui.Info.uploadSize = 0 await new Promise((resolve) => { sha1Pool.StartWithCallback( { hash: 'sha1', localFilePath: path.join(fileui.localFilePath, fileui.File.partPath), access_token }, (result: any, worker: Worker) => { if (result.hash == 'sha1') { if (result.readlen) { if (!fileui.IsRunning) worker.postMessage({ stop: true }) sha1PosMap.set(fileui.UploadID, result.readlen as number) fileui.File.size = result.size as number } if (result.sha1) { hash = result.sha1 proof_code = result.proof_code error = result.error sha1Pool.FinishWithCallback(worker) resolve() } } }, (err: any, worker: Worker) => { hash = 'error' proof_code = '' error = err.message || 'workererror' sha1Pool.FinishWithCallback(worker) resolve() } ) }).catch((err: any) => { error = err.message || 'workercatch' }) sha1PosMap.delete(fileui.UploadID) fileui.Info.uploadSize = 0 if (!fileui.IsRunning) return { sha1: 'error', proof_code: '', error: '' } if (hash != 'error' && prehash && fileui.File.size > 10240000) { DBCache.saveFileHash({ size: fileui.File.size, mtime: fileui.File.mtime, presha1: prehash, sha1: hash, name: path.basename(fileui.File.name) }) } return { sha1: hash, proof_code, error } } } ================================================ FILE: src/renderer/aliapi/uploadmem.ts ================================================ import UserDAL from '../user/userdal' import DebugLog from '../utils/debuglog' import axios from 'axios' import AliUpload from './upload' import AliUploadHashPool from './uploadhashpool' export default class AliUploadMem { static async UploadMem(user_id: string, drive_id: string, parent_file_id: string, CreatFileName: string, context: string) { const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) return '账号失效,操作取消' let hash = 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709' let proof = '' let buff = Buffer.from([]) if (context.length > 0) { buff = Buffer.from(context, 'utf-8') const dd = await AliUploadHashPool.GetBuffHashProof(token!.access_token, buff) hash = dd.sha1 proof = dd.proof_code } const size = buff.length const upinfo = await AliUpload.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, CreatFileName, size, hash, proof, 'refuse') if (upinfo.errormsg != '') { return upinfo.errormsg } if (upinfo.isexist) return '网盘中已存在同名文件' if (upinfo.israpid) return 'success' await axios .put(upinfo.part_info_list[0].upload_url, buff, { responseType: 'text', timeout: 30000, headers: { 'Content-Type': '', Authorization: token!.token_type + ' ' + token!.access_token } }) .catch(function (err: any) { DebugLog.mSaveDanger('UploadMemError', err) }) const result = await AliUpload.UploadFileComplete(user_id, drive_id, upinfo.file_id, upinfo.upload_id, size, hash) if (result) return 'success' else return '合并文件失败' } } ================================================ FILE: src/renderer/aliapi/user.ts ================================================ import UserDAL from '../user/userdal' import { humanDateTime, humanDateTimeDateStr, humanSize, Sleep } from '../utils/format' import { ITokenInfo } from '../user/userstore' import AliHttp from './alihttp' import message from '../utils/message' import DebugLog from '../utils/debuglog' import { IAliUserDriveCapacity, IAliUserDriveDetails } from './models' export const TokenReTimeMap = new Map() export const TokenLockMap = new Map() export default class AliUser { static async _ApiTokenRefresh(token: ITokenInfo, showMessage: boolean): Promise { if (!token.refresh_token) return false while (true) { const lock = TokenLockMap.has(token.user_id) if (lock) await Sleep(1000) else break } TokenLockMap.set(token.user_id, Date.now()) const time = TokenReTimeMap.get(token.user_id) || 0 if (Date.now() - time < 1000 * 60 * 5) { TokenLockMap.delete(token.user_id) return true } const url = 'token/refresh' const postData = { refresh_token: token.refresh_token } const resp = await AliHttp.Post(url, postData, '', '') TokenLockMap.delete(token.user_id) if (AliHttp.IsSuccess(resp.code)) { TokenReTimeMap.set(resp.body.user_id, Date.now()) token.tokenfrom = 'token' token.access_token = resp.body.access_token token.refresh_token = resp.body.refresh_token token.expires_in = resp.body.expires_in token.token_type = resp.body.token_type token.user_id = resp.body.user_id token.user_name = resp.body.user_name token.avatar = resp.body.avatar token.nick_name = resp.body.nick_name token.default_drive_id = resp.body.default_drive_id token.default_sbox_drive_id = resp.body.default_sbox_drive_id token.role = resp.body.role token.status = resp.body.status token.expire_time = resp.body.expire_time token.state = resp.body.state token.pin_setup = resp.body.pin_setup token.is_first_login = resp.body.is_first_login token.need_rp_verify = resp.body.need_rp_verify window.WebUserToken({ user_id: token.user_id, name: token.user_name, access_token: token.access_token, refresh: true }) UserDAL.SaveUserToken(token) return true } else { DebugLog.mSaveWarning('_ApiTokenRefresh err=' + (resp.code || '')) if (showMessage) { message.error('刷新账号[' + token.user_name + '] token 失败,需要重新登录') UserDAL.UserLogOff(token.user_id) } } return false } static async ApiTokenRefreshAccount(token: ITokenInfo, showMessage: boolean): Promise { if (!token.refresh_token) return false while (true) { const lock = TokenLockMap.has(token.user_id) if (lock) await Sleep(1000) else break } TokenLockMap.set(token.user_id, Date.now()) const time = TokenReTimeMap.get(token.user_id) || 0 if (Date.now() - time < 1000 * 60 * 5) { TokenLockMap.delete(token.user_id) return true } const url = 'https://auth.aliyundrive.com/v2/account/token' const postData = { refresh_token: token.refresh_token, grant_type: 'refresh_token' } const resp = await AliHttp.Post(url, postData, '', '') TokenLockMap.delete(token.user_id) if (AliHttp.IsSuccess(resp.code)) { TokenReTimeMap.set(resp.body.user_id, Date.now()) token.tokenfrom = 'account' token.access_token = resp.body.access_token token.refresh_token = resp.body.refresh_token token.expires_in = resp.body.expires_in token.token_type = resp.body.token_type token.user_id = resp.body.user_id token.user_name = resp.body.user_name token.avatar = resp.body.avatar token.nick_name = resp.body.nick_name token.default_drive_id = resp.body.default_drive_id token.default_sbox_drive_id = resp.body.default_sbox_drive_id token.role = resp.body.role token.status = resp.body.status token.expire_time = resp.body.expire_time token.state = resp.body.state token.pin_setup = resp.body.pin_setup token.is_first_login = resp.body.is_first_login token.need_rp_verify = resp.body.need_rp_verify window.WebUserToken({ user_id: token.user_id, name: token.user_name, access_token: token.access_token, refresh: true }) UserDAL.SaveUserToken(token) return true } else { if (resp.body?.code != 'InvalidParameter.RefreshToken') DebugLog.mSaveWarning('ApiTokenRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || '')) if (showMessage) { message.error('刷新账号[' + token.user_name + '] token 失败,需要重新登录') UserDAL.UserLogOff(token.user_id) } else { UserDAL.UserClearFromDB(token.user_id) } } return false } static async ApiUserInfo(token: ITokenInfo): Promise { if (!token.user_id) return false const url = 'v2/databox/get_personal_info' const postData = '' const resp = await AliHttp.Post(url, postData, token.user_id, '') if (AliHttp.IsSuccess(resp.code)) { token.used_size = resp.body.personal_space_info.used_size token.total_size = resp.body.personal_space_info.total_size token.spu_id = resp.body.personal_rights_info.spu_id token.is_expires = resp.body.personal_rights_info.is_expires token.name = resp.body.personal_rights_info.name token.spaceinfo = humanSize(token.used_size) + ' / ' + humanSize(token.total_size) return true } else { DebugLog.mSaveWarning('ApiUserInfo err=' + (resp.code || '')) } return false } static async ApiUserVip(token: ITokenInfo): Promise { if (!token.user_id) return false const url = 'business/v1.0/users/vip/info' const postData = {} const resp = await AliHttp.Post(url, postData, token.user_id, '') if (AliHttp.IsSuccess(resp.code)) { let vipList = resp.body.vipList || [] vipList = vipList.sort((a: any, b: any) => b.expire - a.expire) if (vipList.length > 0 && new Date(vipList[0].expire) > new Date()) { token.vipname = vipList[0].name token.vipexpire = humanDateTime(vipList[0].expire) } else { token.vipname = '免费用户' token.vipexpire = '' } return true } else { DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || '')) } return false } static async ApiUserPic(token: ITokenInfo): Promise { if (!token.user_id) return false const url = 'adrive/v1/user/albums_info' const postData = {} const resp = await AliHttp.Post(url, postData, token.user_id, '') if (AliHttp.IsSuccess(resp.code)) { token.pic_drive_id = resp.body.data.driveId return true } else { DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || '')) } return false } static async ApiUserDriveDetails(user_id: string): Promise { const detail: IAliUserDriveDetails = { drive_used_size: 0, drive_total_size: 0, default_drive_used_size: 0, album_drive_used_size: 0, note_drive_used_size: 0, sbox_drive_used_size: 0, share_album_drive_used_size: 0 } if (!user_id) return detail const url = 'adrive/v1/user/driveCapacityDetails' const postData = '{}' const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { detail.drive_used_size = resp.body.drive_used_size || 0 detail.drive_total_size = resp.body.drive_total_size || 0 detail.default_drive_used_size = resp.body.default_drive_used_size || 0 detail.album_drive_used_size = resp.body.album_drive_used_size || 0 detail.note_drive_used_size = resp.body.note_drive_used_size || 0 detail.sbox_drive_used_size = resp.body.sbox_drive_used_size || 0 detail.share_album_drive_used_size = resp.body.share_album_drive_used_size || 0 } else { DebugLog.mSaveWarning('ApiUserDriveDetails err=' + (resp.code || '')) } return detail } static async ApiUserDriveFileCount(user_id: string, category: string, type: string): Promise { if (!user_id) return 0 const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token) return 0 const url = 'adrive/v3/file/search' const postData = { drive_id_list: [token?.default_drive_id, token?.pic_drive_id], marker: '', limit: 1, all: false, url_expire_sec: 14400, fields: 'thumbnail', query: type ? 'type="' + type + '"' : 'category="' + category + '"', return_total_count: true } const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { return resp.body.total_count || 0 } else { DebugLog.mSaveWarning('ApiUserDriveFileCount err=' + category + ' ' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('ApiUserDriveFileCount' + category, err) } return 0 } static async ApiUserCapacityDetails(user_id: string): Promise { let result: IAliUserDriveCapacity[] = [] if (!user_id) return result const url = 'adrive/v1/user/capacityDetails' const postData = '{}' const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { const list = resp.body.capacity_details || [] const today = new Date() for (let i = 0, maxi = list.length; i < maxi; i++) { const item = list[i] let expiredstr = '' if (item.expired == 'permanent_condition') expiredstr = '永久有效,每年激活' else if (item.expired == 'permanent') expiredstr = '永久有效' else { const data = new Date(item.expired) if (data > today) expiredstr = humanDateTimeDateStr(item.expired) + ' 到期' else expiredstr = '已过期' } result.push({ type: item.type, size: item.size, sizeStr: humanSize(item.size), expired: item.expired, expiredstr: expiredstr, description: item.description, latest_receive_time: humanDateTimeDateStr(item.latest_receive_time) } as IAliUserDriveCapacity) } result = result.sort((a, b) => a.latest_receive_time.localeCompare(b.latest_receive_time)) } else { DebugLog.mSaveWarning('ApiUserCapacityDetails err=' + (resp.code || '')) } return result } } ================================================ FILE: src/renderer/aliapi/utils.ts ================================================ import { ITokenInfo, useFootStore } from '../store' import UserDAL from '../user/userdal' import DebugLog from '../utils/debuglog' import { Sleep } from '../utils/format' import message from '../utils/message' import AliHttp from './alihttp' import AliFile from './file' import { IAliBatchResult } from './models' export declare type Drive = 'pan' | 'pic' | 'safe' export function GetDriveID(user_id: string, drive: Drive): string { const token = UserDAL.GetUserToken(user_id) if (token) { switch (drive) { case 'pan': return token.default_drive_id case 'pic': return token.pic_drive_id case 'safe': return token.default_sbox_drive_id } } return '' } export function GetDriveID2(token: ITokenInfo, driveName: string): string { if (token) { switch (driveName) { case 'pan': return token.default_drive_id case 'pic': return token.pic_drive_id case 'safe': return token.default_sbox_drive_id } } return driveName } async function _ApiBatch(postData: string, user_id: string, share_token: string, result: IAliBatchResult): Promise { if (!user_id && !share_token) return const url = 'v2/batch' const resp = await AliHttp.Post(url, postData, user_id, share_token) if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let i = 0, maxi = responses.length; i < maxi; i++) { const status = responses[i].status as number if (status >= 200 && status <= 205) { result.count++ const respi = responses[i] if (respi.body && respi.body.async_task_id) { result.async_task.push({ drive_id: respi.body.drive_id || '', file_id: respi.id, task_id: respi.body.async_task_id, newdrive_id: respi.body.drive_id || '', newfile_id: respi.body.file_id || '' }) } else if (respi.body && respi.body.share_id && respi.body.share_msg) { result.reslut.push({ id: respi.id, share_id: respi.body.share_id, share_pwd: respi.body.share_pwd || '', share_url: respi.body.share_url, expiration: respi.body.expiration || '', share_name: respi.body.share_name || '' }) } else if (respi.body) { result.reslut.push({ id: respi.id, file_id: respi.body.file_id, name: respi.body.name || '', body: respi.body }) } else if (respi.id) { result.reslut.push({ id: respi.id, file_id: respi.id }) } } else { const respi = responses[i] const logmsg = (respi.body.code || '') + ' ' + (respi.body.message || '') if (logmsg.includes('File under sync control') == false) DebugLog.mSaveDanger(logmsg) if (respi.body && respi.body.code) result.error.push({ id: respi.body.id || respi.id, code: respi.body.code, message: respi.body.message }) } } } else { DebugLog.mSaveWarning('_ApiBatch err=' + (resp.code || '')) } } export declare type AsyncType = '解压' | '复制' | '导入分享' | '回收站还原' | '异步' | '放回收站' | '彻底删除' export async function ApiBatch(title: string, batchList: string[], user_id: string, share_token: string): Promise { const result: IAliBatchResult = { count: 0, async_task: [], reslut: [], error: [] } if (!user_id && !share_token) return result const loadingKey = 'filebatch' + Date.now().toString() if (title != '') message.loading(title + ' 执行中...', 60, loadingKey) let add = 0 let postData = '{"requests":[' let allTask: Promise[] = [] for (let i = 0, maxi = batchList.length; i < maxi; i++) { if (add > 0) postData = postData + ',' add++ postData = postData + batchList[i] if (add > 99) { postData += '],"resource":"file"}' allTask.push(_ApiBatch(postData, user_id, share_token, result)) postData = '{"requests":[' add = 0 } if (allTask.length >= 3) { await Promise.all(allTask).catch(() => {}) allTask = [] if (title != '') message.loading(title + ' 执行中...(' + result.count.toString() + ')', 60, loadingKey) } } if (add > 0) { postData += '],"resource":"file"}' allTask.push(_ApiBatch(postData, user_id, share_token, result)) } if (allTask.length > 0) await Promise.all(allTask).catch(() => {}) if (result.async_task.length > 0) { if (title != '' || share_token != '') message.warning(title + ' 异步执行中(' + result.async_task.length + ')', 2, loadingKey) let type: AsyncType = '异步' if (title == '放入回收站') type = '放回收站' if (title == '从回收站还原') type = '回收站还原' if (title == '彻底删除') type = '彻底删除' if (title == '批量复制') type = '复制' if (title == '复制') type = '复制' if (!title && share_token) type = '导入分享' const footStore = useFootStore() for (let i = 0, maxi = result.async_task.length; i < maxi; i++) { const task = result.async_task[i] if (type == '放回收站' || type == '彻底删除') { result.reslut.push({ id: task.file_id, file_id: task.newfile_id }) } if (task.newdrive_id && task.newfile_id) { const fileinfo = await AliFile.ApiGetFile(user_id, task.newdrive_id, task.newfile_id) if (fileinfo) { footStore.mAddTask(user_id, task.task_id, type, fileinfo.name, task.newdrive_id, task.newfile_id) continue } } footStore.mAddTask(user_id, task.task_id, type, task.task_id, '', '') } } if (title != '' || share_token != '') { if (result.error.length == 0) { if (result.async_task.length > 0) { message.warning(title + ' 异步执行中(' + result.async_task.length + ')', 2, loadingKey) } else { message.success(title + ' 成功', 0, loadingKey) message.success(title + ' 成功', 3) } } else { message.error(title + ' 成功(' + result.count.toString() + ')个 失败 (' + result.error.length.toString() + ')个', 3, loadingKey) let isSyncError = false result.error.map((t) => { if (t.message.includes('File under sync control')) isSyncError = true return true }) if (isSyncError) message.error('自动备份文件夹不支持移动/新建/删除/重命名等操作', 3) } } return result } export function ApiBatchMaker(url: string, idList: string[], bodymake: (file_id: string) => any): string[] { if (!idList || idList.length == 0) return [] const batchList: string[] = [] const batchSet = new Set() for (let i = 0, maxi = idList.length; i < maxi; i++) { const id = idList[i] if (batchSet.has(id)) continue batchSet.add(id) batchList.push(JSON.stringify({ body: bodymake(id), headers: { 'Content-Type': 'application/json' }, id: id, method: 'POST', url })) } batchSet.clear() return batchList } export function ApiBatchMaker2(url: string, idList: string[], namelist: string[], bodymake: (file_id: string, name: string) => any): string[] { if (!idList || idList.length == 0) return [] const batchList: string[] = [] const batchSet = new Set() for (let i = 0, maxi = idList.length; i < maxi; i++) { const id = idList[i] if (batchSet.has(id)) continue batchSet.add(id) batchList.push(JSON.stringify({ body: bodymake(id, namelist[i]), headers: { 'Content-Type': 'application/json' }, id: id, method: 'POST', url })) } batchSet.clear() return batchList } export async function ApiBatchSuccess(title: string, batchList: string[], user_id: string, share_token: string): Promise { if (batchList.length == 0) return Promise.resolve(batchList) const successList: string[] = [] const result = await ApiBatch(title, batchList, user_id, share_token) result.reslut.map((t) => successList.push(t.id)) return successList } export async function ApiWaitAsyncTask(title: string, user_id: string, taskList: IAliBatchResult['async_task']): Promise { for (let i = 0, maxi = taskList.length; i < maxi; i++) { const async_task_id = taskList[i].task_id if (!user_id || !async_task_id) continue for (let j = 0; j < 100; j++) { const url = 'v2/async_task/get' const postData = { async_task_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { if (resp.body.state == 'Succeed' || resp.body.state == 'succeed') break if (resp.body.state == 'done' || resp.body.state == 'done') break if (resp.body.state == 'Failed' || resp.body.state == 'failed') break if (resp.body.state == 'Running' || resp.body.state == 'running') continue } await Sleep(1000) } } } export async function ApiGetAsyncTask(user_id: string, async_task_id: string): Promise<'running' | 'error' | 'success'> { if (!user_id || !async_task_id) return 'error' const url = 'v2/async_task/get' const postData = { async_task_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { if (resp.body.state == 'Succeed' || resp.body.state == 'succeed') return 'success' if (resp.body.state == 'done' || resp.body.state == 'done') return 'success' if (resp.body.state == 'Failed' || resp.body.state == 'failed') return 'error' if (resp.body.state == 'Running' || resp.body.state == 'running') return 'running' if (resp.body.state == 'PartialSucceed') { message.warning('操作部分成功 ' + resp.body.message?.replace('ErrQuotaExhausted', '网盘空间已满') || '', 5) return 'error' } } else { DebugLog.mSaveWarning('ApiGetAsyncTask err=' + (resp.code || '')) } return 'error' } export async function ApiGetAsyncTaskUnzip(user_id: string, drive_id: string, file_id: string, domain_id: string, task_id: string): Promise { if (!user_id || !task_id) return 'error' const url = 'v2/archive/status' const postData = { drive_id, file_id, domain_id, task_id } const resp = await AliHttp.Post(url, postData, user_id, '') if (AliHttp.IsSuccess(resp.code)) { if (resp.body.state == 'Succeed' || resp.body.state == 'succeed') return 'success' if (resp.body.state == 'Failed' || resp.body.state == 'failed') return 'error' if (resp.body.state == 'Running' || resp.body.state == 'running') return 'running' if (resp.body.state == 'PartialSucceed') { message.warning('操作部分成功 ' + resp.body.message?.replace('ErrQuotaExhausted', '网盘空间已满') || '', 5) return 'error' } } else { DebugLog.mSaveWarning('ApiGetAsyncTaskUnzip err=' + (resp.code || '')) } return 'error' } ================================================ FILE: src/renderer/assets/antd.css ================================================ .ant-tree, .ant-tree-switcher, .ant-tree-show-line .ant-tree-switcher { background: transparent !important; } .ant-tree-checkbox { margin-right: 4px !important; } .ant-tree .ant-tree-node-content-wrapper { padding-left: 2px !important; } .ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected { background: rgba(var(--primary-6), 0.15) !important; } body[arco-theme='dark'] .ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected { background: rgba(var(--primary-6), 0.5) !important; } .ant-tree .ant-tree-node-content-wrapper:hover { background-color: var(--color-fill-2); } .ant-checkbox-checked .ant-checkbox-inner, .ant-tree-checkbox-checked .ant-tree-checkbox-inner { background-color: rgb(var(--primary-6)); border-color: rgb(var(--primary-6)); } .ant-tree, .ant-checkbox-wrapper { color: var(--color-text-1); } .ant-checkbox-disabled + span { color: var(--color-text-4); } .ant-tree-show-line .ant-tree-indent-unit::before { border-right: 1px solid var(--color-neutral-3); } .ant-tree-switcher-leaf-line::after { border-bottom: 1px solid var(--color-neutral-3); } .ant-tree-switcher-leaf-line::before { border-right: 1px solid var(--color-neutral-3); } .ant-tree-switcher_open .ant-tree-switcher-icon.iconfont.Arrow:before { content: '\e740'; font-size: 20px; } .ant-tree-switcher_close .ant-tree-switcher-icon.iconfont.Arrow:before { content: '\e742'; font-size: 18px; } .ant-tree-switcher_close .ant-tree-switcher-icon { color: rgba(0, 0, 0, 0.4); height: 24px; width: 24px; display: inline-block; } .ant-tree-treenode { min-height: 30px; } .ant-tree-treenode:hover .ant-tree-switcher_close .ant-tree-switcher-icon { color: rgba(0, 0, 0, 0.6); } .ant-tree-switcher_open .ant-tree-switcher-icon { color: rgba(0, 0, 0, 0.6); height: 24px; width: 24px; display: inline-block; } /*tree*/ .ant-tree.ant-tree-directory .ant-tree-treenode-selected:hover::before, .ant-tree.ant-tree-directory .ant-tree-treenode-selected::before { background: rgb(var(--primary-6)); } .ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-inner, .ant-tree-checkbox:hover .ant-tree-checkbox-inner, .ant-tree-checkbox-input:focus + .ant-tree-checkbox-inner { border-color: rgb(var(--primary-6)); } .ant-tree-checkbox-checked::after { border: 1px solid rgb(var(--primary-6)); } .ant-tree-checkbox-checked .ant-tree-checkbox-inner { background-color: rgb(var(--primary-6)); border-color: rgb(var(--primary-6)); } .ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner::after { background-color: rgb(var(--primary-6)); } .ant-tree.ant-tree-block-node .ant-tree-list-holder-inner .ant-tree-treenode.dragging::after { border: 1px solid rgb(var(--primary-6)); } .ant-tree-switcher-loading-icon { color: rgb(var(--primary-6)); } .ant-tree-node-content-wrapper .ant-tree-drop-indicator { background-color: rgb(var(--primary-6)); } .ant-tree-node-content-wrapper .ant-tree-drop-indicator::after { border: 2px solid rgb(var(--primary-6)); } .ant-tree .ant-tree-treenode.drop-container > [draggable] { box-shadow: 0 0 0 2px rgb(var(--primary-6)); } body[arco-theme='dark'] .ant-tree-switcher_close .ant-tree-switcher-icon { color: rgba(255, 255, 255, 0.4); } body[arco-theme='dark'] .ant-tree-treenode:hover .ant-tree-switcher_close .ant-tree-switcher-icon { color: rgba(255, 255, 255, 0.6); } body[arco-theme='dark'] .ant-tree-switcher_open .ant-tree-switcher-icon { color: rgba(255, 255, 255, 0.6); } .ant-tree-list-scrollbar[style] { width: 10px !important; } .ant-tree-list-scrollbar-thumb[style], body[arco-theme='dark'] .ant-tree-list-scrollbar-thumb[style] { background: rgb(201, 201, 202) !important; } .ant-tree-list-scrollbar-thumb:hover[style], body[arco-theme='dark'] .ant-tree-list-scrollbar-thumb:hover[style] { background: rgb(162, 162, 163) !important; } .ant-tree-checkbox-inner::after, .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after, .ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner::after { transition: none !important; } .ant-tree-title { white-space: pre-wrap; word-break: break-all; word-wrap: break-word; } .ant-tree .ant-tree-node-content-wrapper .ant-tree-iconEle { flex-shrink: 0; } /*checkbox*/ .ant-checkbox-wrapper:hover .ant-checkbox-inner, .ant-checkbox:hover .ant-checkbox-inner, .ant-checkbox-input:focus + .ant-checkbox-inner { border-color: rgb(var(--primary-6)); } .ant-checkbox-checked::after { border: 1px solid rgb(var(--primary-6)); } .ant-checkbox-checked .ant-checkbox-inner { background-color: rgb(var(--primary-6)); border-color: rgb(var(--primary-6)); } .ant-checkbox-indeterminate .ant-checkbox-inner::after { background-color: rgb(var(--primary-6)); } .ant-checkbox-wrapper { flex-shrink: 0; flex-grow: 0; } /*tooltip*/ .ant-tooltip .ant-tooltip-inner { padding: 2px 4px !important; min-height: 24px !important; font-size: 12px; } .ant-tabs { color: var(--color-text-2); } ================================================ FILE: src/renderer/assets/fileitem.css ================================================ .fileitem { display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; height: 50px; overflow: hidden; word-break: break-all; word-wrap: break-word; text-overflow: ellipsis; border: 1px dotted transparent; border-radius: 2px; border-bottom: 1px solid #e5e8ed99; margin-right: 2px; } body[arco-theme='dark'] .fileitem { border-bottom: 1px solid #e5e8ed22; } .fileitem.grid { width: 200px; } .fileitem:hover { background-color: var(--listhoverbg); } .fileitem.focus, .griditem.focus { border: rgba(var(--primary-6), 0.6) dotted 1px; } body[arco-theme='dark'] .fileitem.focus { border: rgba(var(--primary-6), 0.9) dotted 1px; border-bottom: rgba(var(--primary-6), 0.9) dotted 1px; } .fileitem.selected { background-color: var(--listselectbg); } .fileicon { width: 26px; padding-right: 4px; } .fileicon i { color: var(--color-neutral-7); font-size: 22px; position: relative; } .fileicon .iconfile-folder { color: #ffb74d !important; } .iconfile_video, .iconfile-video, .iconfile-mkv, .iconfile-avi, .iconfile-flv, .iconfile-mp4, .iconfile-mov, .iconfile-asf, .iconfile-wmv, .iconfile-ts, .iconfile-rmvb { color: #3482f0 !important; } .iconfile-audio, .iconfile-flac, .iconfile-ape, .iconfile-wav, .iconfile-cue, .iconfile-ogg, .iconfile-mp3 { color: #565bf5 !important; } .iconfile-image { color: #b6aea0 !important; } .iconfile-img, .iconfile-ai, .iconfile-bmp, .iconfile-eps, .iconfile-gif, .iconfile-png, .iconfile-jpg, .iconfile-psd, .iconfile-svg, .iconfile-tif { color: #fa8d11 !important; } .iconfile_txt2, .iconfile-txt, .iconfile-pdf, .iconfile-wps { color: #8bc755 !important; } .iconfile-doc { color: #282698 !important; } .iconfile-xsl { color: #269840 !important; } .iconfile-ppt { color: #d84a25 !important; } .iconfile-rar, .iconfile-zip, .iconfile-tar { color: #7c5bf3 !important; } .iconweifa { color: #d81e06 !important; } .ant-layout-content .iconweixiang { color: #d81e06 !important; } .iconnoshareaf::after { display: inline-block; width: 22px; height: 16px; content: '\e670'; position: absolute; left: 0px; top: 2px; color: #d81e06 !important; font-size: 12px; text-align: center; } .fileicon .iconwenjian, .iconfile-apk, .iconfile-exe, .iconfile-xci, .iconfile-nsp, .iconfile-bin, .iconfile-dmg, .iconfile-vmdk, .iconfile-iso, .iconfile-gho, .iconfile-mds, .iconfile-vhd, .iconfile-god, .iconfile-7z, .iconfile-swf, .iconfile-ssa, .iconfile-ass, .iconfile-srt, .iconfile-stl, .iconfile-scc, .iconfile-html, .iconfile-bt { color: #999999 !important; } .filename { display: block; flex-grow: 1; max-width: 100%; max-height: 36px; min-width: 240px; overflow: hidden; color: var(--color-text-1); font-size: 14px; } .filename > div { display: -webkit-box; width: fit-content; min-width: 50px; max-height: 36px; overflow: hidden; line-height: 18px; letter-spacing: 0.4px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word; text-overflow: ellipsis; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .filename > div { cursor: pointer; } .filename > div:hover { color: rgb(var(--primary-6)); } .filebtn { flex-grow: 0; flex-shrink: 0; } .filetime, .filesize { flex-grow: 0; flex-shrink: 0; color: var(--color-text-3); word-wrap: break-word; word-break: keep-all; } .filesize { width: 78px; font-size: 14px; line-height: 16px; text-align: right; } .filesize > span { display: block; font-size: 12px; line-height: 14px; text-align: right; } .filetime { width: 80px; padding-right: 2px; font-size: 12px; line-height: 14px; text-align: right; } .filesizetime { flex-grow: 0; flex-shrink: 0; color: var(--color-text-3); width: 120px; padding-right: 2px; font-size: 12px; line-height: 14px; text-align: right; } .filesizetime .fsize { font-size: 14px; padding-bottom: 6px; } .preimgp .ant-tooltip-inner { padding: 2px !important; background: transparent !important; box-shadow: none !important; } .preimg { display: table-cell; max-width: 240px; max-height: 220px; min-width: 100px; min-height: 100px; } .preimg img { display: block; min-width: 50%; max-width: 240px; max-height: 220px; width: auto; height: auto; margin: auto; border: 1px solid rgb(0 0 0 / 12%); border-radius: 5px; box-shadow: 0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%); background: #ffffff; } .ca760ef { color: #a760ef; } .cdf5659 { color: #df5659; } .c9c27b0 { color: #9c27b0; } .c3f51b5 { color: #3f51b5; } .c42a5f5 { color: #42a5f5; } .c00bc99 { color: #00bc99; } .c4caf50 { color: #8bc755; } .cff9800 { color: #ff9800; } .cff5722 { color: #ff5722; } .c5b89b8 { color: #5b89b8; } .cvideo { color: #5b89b8; } .griditemparent { padding: 6px 12px; } .gridrow { display: grid; justify-content: space-between; align-content: flex-start; padding: 4px 3px 16px 3px; overflow: hidden; } .griditem.image { width: 150px; height: 180px; flex-shrink: 0; flex-grow: 0; } .griditem.bigimage { width: 200px; height: 240px; flex-shrink: 0; flex-grow: 0; } .griditem { border-radius: 8px; position: relative; height: 100%; border: 1px dotted transparent; border-bottom: 1px solid #e5e8ed99; } body[arco-theme='dark'] .griditem { border-bottom: 1px solid #e5e8ed22; } .griditem:hover { background-color: var(--listhoverbg); } .griditem.selected { background-color: var(--listselectbg); } .griditem .select { left: 5px; position: absolute; top: 4px; color: #bcb3b366 !important; background: #ffffffcc; } .griditem .select:hover { background: #fff !important; color: #637dff !important; border-radius: 8px; } body[arco-theme='dark'] .griditem .select:hover { background: rgba(155, 155, 155, 0.2) !important; } .griditem.selected .select i { color: #637dff !important; } .griditem .select, .griditem .select > button { width: 24px !important; min-width: 24px !important; height: 24px !important; min-height: 24px !important; padding: 0px !important; font-size: 14px; line-height: 24px !important; border: none !important; } .griditem .select .iconfont { line-height: 24px !important; } .griditem .label { display: inline-block; right: 8px; position: absolute; top: 4px; } .gridicon { left: 6px; right: 6px; top: 10px; position: absolute; text-align: center; height: 62%; display: flex; justify-content: center; align-items: center; flex-shrink: 0; flex-grow: 0; } .gridicon i { font-size: 56px; opacity: 0.75; } .gridicon .iconfile-folder { color: #ffb74d !important; } .gridicon img { display: block; max-width: 100%; max-height: 100%; border-radius: 5px; position: relative; border: 1px solid rgba(132, 133, 141, 0.16); } .gridicon .playicon { cursor: pointer; font-size: 20px; height: 28px; width: 28px; background: rgba(37, 38, 43, 0.36); backdrop-filter: blur(10px); border-radius: 50%; color: rgb(255, 255, 255); } .gridicon .playicon svg { width: 1em; height: 1em; fill: currentColor; overflow: hidden; } .gridname { width: 100%; text-align: center; font-size: 14px; line-height: 18px; max-width: 100%; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; -o-text-overflow: ellipsis; text-overflow: ellipsis; overflow-wrap: break-word; margin-bottom: 2px; color: var(--color-text-1); padding: 0 8px; position: absolute; bottom: 26px; } .gridname > div { cursor: pointer; text-align: center; word-break: break-all; } .gridname > div:hover { color: #3482f0; } .gridinfo { width: 100%; text-align: center; font-size: 12px; color: var(--color-text-3); position: absolute; bottom: 10px; } .griditem .rangselect { height: 100% !important; margin: 0 !important; padding: 0 !important; } .griditem .rangselect.rang { background: rgba(25, 118, 210, 0.1); border: 1px dashed #637dff; margin: 0 !important; padding: 0 !important; border-radius: 8px !important; } .griditem .rangselect.rangstart { background: rgba(99, 125, 255, 0.1); border: 1px dashed #637dff; margin: 0 !important; padding: 0 !important; border-radius: 8px !important; } .griditem .rangselect.rangend { background: rgba(99, 125, 255, 0.1); border: 1px dashed #637dff; margin: 0 !important; padding: 0 !important; border-radius: 8px !important; } .rangselect { height: 49px; margin: 2px 2px 2px 1px; padding-top: 7px; border: 1px dashed transparent; } .rangselect.rang { background: rgba(25, 118, 210, 0.1); border-right: 1px dashed #637dff; border-left: 1px dashed #637dff; } .fileitem .rangselect.rangstart { height: 42px !important; margin-top: 9px !important; padding-top: 0px !important; background: rgba(99, 125, 255, 0.1); border-top: 1px dashed #637dff; border-right: 1px dashed #637dff; border-left: 1px dashed #637dff; border-top-left-radius: 28px; border-top-right-radius: 28px; } .fileitem .rangselect.rangend { height: 42px !important; margin-bottom: 9px !important; background: rgba(99, 125, 255, 0.1); border-right: 1px dashed #637dff; border-bottom: 1px dashed #637dff; border-left: 1px dashed #637dff; border-bottom-right-radius: 28px; border-bottom-left-radius: 28px; } .rangselect.rang, .rangselect.rangstart, .rangselect.rangend { background: transparent; } .rangselect.rang i, .rangselect.rangstart i, .rangselect.rangend i { color: #637dff; } .toppanarea .qujian { height: 28px !important; min-height: 28px !important; padding: 0px 6px !important; color: #637dff !important; font-size: 14px; line-height: 28px !important; border: none !important; } .toppanarea .qujian:hover { background: rgba(99, 125, 255, 0.1) !important; } .toppanarea .qujian.arco-btn-status-danger { color: #ffffff !important; background: #ff4d4f !important; } .toppanarea .qujian.arco-btn-status-danger:hover { color: #ffffff !important; background: #ff4d4f !important; } .dragrowitem { padding: 10px 8px 10px 2px; color: rgba(255, 255, 255); border: 1px solid rgba(99, 125, 255, 0.8); outline-offset: -1px; background-color: rgb(187, 197, 248); min-width: 260px; max-width: 300px; width: fit-content; overflow: hidden; text-overflow: ellipsis; white-space: nowrap !important; word-break: keep-all !important; border-radius: 4px; position: fixed; } .dragrowitem > a { margin: 0 8px; color: #637dff; font-weight: bold; } .dark .dragrowitem { color: rgba(0, 0, 0); background-color: rgb(214, 219, 247); } ================================================ FILE: src/renderer/assets/global.css ================================================ html { min-width: 100vw; min-height: 100vh; overflow: hidden; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif; min-width: 100vw; min-height: 100vh; overflow: hidden; background-color: transparent !important; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } ::-webkit-scrollbar { width: 10px; height: 10px; cursor: pointer; } ::-webkit-scrollbar-thumb { background: rgb(201, 201, 202); border-radius: 5px; cursor: default; } ::-webkit-scrollbar-thumb:vertical { width: 9px; } ::-webkit-scrollbar-thumb:horizontal { height: 9px; } ::-webkit-scrollbar-thumb:hover { background: rgb(162, 162, 163); } ::-webkit-scrollbar-track { background-color: transparent; } ::-webkit-scrollbar-corner { background: transparent !important; } ::-webkit-resizer { background: transparent !important; } ::-webkit-scrollbar-button { display: none; } .flex { display: flex; flex: 100% 1 1; flex-direction: row; } .flexauto { flex-grow: 1 !important; } .flexnoauto { flex-grow: 0 !important; flex-shrink: 0 !important; flex-basis: unset !important; } .q-electron-drag { user-select: none; -webkit-app-region: drag; } .q-electron-drag--exception, .q-electron-drag button, .q-electron-drag ul, .q-electron-drag li, .q-electron-drag .arco-menu-item, .q-electron-drag .arco-avatar { -webkit-app-region: no-drag; } * { user-select: none; -webkit-user-drag: none; box-sizing: border-box; letter-spacing: 0.1px; -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; font-feature-settings: 'tnum', 'zero', 'liga' 0; } #app { height: 100vh; position: fixed; top: 0; left: 0; right: 0; bottom: 0; } body { --arcoblue-1: 232, 240, 255 !important; --arcoblue-2: 205, 220, 255 !important; --arcoblue-3: 179, 199, 255 !important; --arcoblue-4: 152, 176, 255 !important; --arcoblue-5: 126, 151, 255 !important; --arcoblue-6: 99, 125, 255 !important; --arcoblue-7: 61, 81, 210 !important; --arcoblue-8: 32, 46, 166 !important; --arcoblue-9: 12, 19, 121 !important; --arcoblue-10: 0, 3, 77 !important; --foot-bg: #3c86f5; --foot-txt: rgb(245, 245, 246); --topshadow: rgba(0, 0, 0, 0.1); --leftshadow: rgba(29, 35, 41, 0.05); --rightbg2: #f2f3f5; --listhoverbg: rgba(247, 248, 250, 0.6); --listselectbg: rgb(240, 245, 255); --color-text-1: var(--color-neutral-9) !important; --color-mask-bg: rgba(29, 33, 41, 0.3) !important; } body[arco-theme='dark'] { color-scheme: dark; caret-color: rgba(255, 255, 255, 0.65); background: #23232e !important; --color-text-2: rgba(255, 255, 255, 0.8) !important; color: var(--color-text-2) !important; --color-menu-light-bg: #30303d !important; --color-bg-1: #23232e !important; --color-bg-popup: #2d2d3b !important; --color-spin-layer-bg: rgba(51, 51, 51, 0.3) !important; --foot-bg: #17171f; --foot-txt: rgb(210, 210, 211); --topshadow: rgba(0, 0, 0, 0.5); --leftshadow: rgba(0, 0, 0, 0.2); --rightbg2: rgba(255, 255, 255, 0.05); --listhoverbg: rgba(76, 77, 97, 0.3); --listselectbg: rgba(85, 86, 109, 0.7); --color-text-1: rgba(255, 255, 255, 0.8) !important; --color-mask-bg: rgba(29, 33, 41, 0.5) !important; } .arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected { background: #f0f5ff; color: var(--color-text-2); } .arco-layout-sider .arco-menu-light .arco-menu-item .arco-menu-icon, .arco-layout-sider .arco-menu-light .arco-menu-item:hover .arco-menu-icon, .arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected .arco-menu-icon { color: var(--color-text-2); } body[arco-theme='dark'] .arco-layout-sider, body[arco-theme='dark'] .arco-layout-sider-light, body[arco-theme='dark'] .arco-layout-sider .arco-menu-light, body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item, body[arco-theme='dark'] .arco-card { background: #23232e; } body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item:hover { background: var(--color-fill-2); } body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected { background: #444457; } .arco-alert-error { background-color: rgb(253, 237, 237) !important; } .arco-alert-error .arco-alert-icon svg { color: rgb(239, 83, 80) !important; } .arco-alert-error .arco-alert-content { color: rgb(112, 40, 39) !important; } .arco-alert-warning { background-color: rgb(255, 244, 229) !important; } .arco-alert-warning .arco-alert-icon svg { color: rgb(255, 152, 0) !important; } .arco-alert-warning .arco-alert-content { color: rgb(117, 69, 1) !important; } .arco-alert-success { background-color: rgb(237, 247, 237) !important; } .arco-alert-success .arco-alert-icon svg { color: rgb(76, 175, 80) !important; } .arco-alert-success .arco-alert-content { color: rgb(38, 87, 40) !important; } .arco-alert-info .arco-alert-content { color: rgb(14, 22, 136) !important; } body[arco-theme='dark'] .arco-alert-error { background-color: rgb(63, 32, 32) !important; } body[arco-theme='dark'] .arco-alert-error .arco-alert-icon svg { color: rgb(244, 67, 54) !important; } body[arco-theme='dark'] .arco-alert-error .arco-alert-content { color: rgb(244, 199, 199) !important; } body[arco-theme='dark'] .arco-alert-warning { background-color: rgb(66, 49, 20) !important; } body[arco-theme='dark'] .arco-alert-warning .arco-alert-icon svg { color: rgb(255, 167, 38) !important; } body[arco-theme='dark'] .arco-alert-warning .arco-alert-content { color: rgb(255, 226, 183) !important; } body[arco-theme='dark'] .arco-alert-success { background-color: rgb(39, 61, 42) !important; } body[arco-theme='dark'] .arco-alert-success .arco-alert-icon svg { color: rgb(102, 187, 106) !important; } body[arco-theme='dark'] .arco-alert-success .arco-alert-content { color: rgb(204, 232, 205) !important; } body[arco-theme='dark'] .arco-alert-info .arco-alert-content { color: rgb(205, 220, 255) !important; } .arco-select, .arco-menu, .arco-radio-group-button { user-select: none; -webkit-user-drag: none; } .arco-spin:focus, .arco-list:focus { outline: none; } button1.arco-btn:focus, button1:focus { outline-style: dotted !important; outline-width: 1px !important; outline-color: rgb(var(--primary-6)) !important; outline-offset: 2px !important; } .arco-modal { width: auto !important; } .arco-modal.arco-modal-fullscreen { width: 100vw !important; height: 100vh !important; border-radius: 0 !important; } .arco-modal-wrapper { overflow: hidden !important; } body[arco-theme='dark'] .arco-modal { background: #2d2d3b !important; box-shadow: 0 2px 20px 0 rgb(0 0 0 / 45%) !important; } body[arco-theme='dark'] .arco-dropdown, body[arco-theme='dark'] .arco-select-dropdown, body[arco-theme='dark'] .arco-popover-popup-content { box-shadow: 0 4px 20px rgb(0 0 0 / 45%) !important; border: 1px solid transparent !important; } .arco-radio-button.arco-radio-checked { background-color: rgb(var(--primary-6)) !important; color: var(--color-white) !important; } .arco-dropdown-option { line-height: 32px !important; width: calc(100% - 8px) !important; margin: 0 4px !important; border-radius: 3px !important; } .arco-dropdown-option.danger { color: rgb(255, 77, 79) !important; } .arco-dropdown-option.danger:hover, .arco-dropdown-option.danger:active { color: #fff !important; background: rgba(255, 77, 79, 0.85) !important; } .toppanbtn .arco-btn.danger:hover, .toppanbtn .arco-btn.danger:active, body[arco-theme='dark'] .toppanbtn .arco-btn.danger:hover, body[arco-theme='dark'] .toppanbtn .arco-btn.danger:active { color: #fff !important; background: rgba(255, 77, 79, 0.85) !important; border-color: rgba(255, 77, 79, 0.2) !important; } .arco-dropdown-option-suffix { color: var(--color-text-3); font-size: 12px; user-select: none; } .arco-list .arco-empty { margin-top: 15%; } .arco-modal { z-index: 1001; } .arco-modal-close-btn { -webkit-app-region: no-drag; position: absolute; right: 20px; } .arco-modal-close-btn .arco-icon-hover { width: 24px; height: 24px; line-height: 24px; border-radius: 50%; } .arco-modal-close-btn .arco-icon-hover .arco-icon { left: 6px; } .arco-modal-close-btn .arco-icon-hover::before { display: none; } .arco-modal-close-btn .arco-icon-hover:hover { background-color: var(--color-fill-2); } .toppanbtns { display: flex; flex-direction: row; flex-wrap: nowrap; padding: 0; max-width: 100%; min-width: 440px; user-select: none; padding-left: 6px; } .toppanbtn { display: flex; flex-direction: row; flex-grow: 0; flex-shrink: 0; flex-wrap: nowrap; border-radius: 4px; margin-right: 12px; user-select: none; } .toppanbtn:last-child { margin-right: 0; } .toppanbtn .arco-btn { display: inline-flex; align-items: center; height: 26px !important; min-height: 26px !important; padding: 0px 6px !important; font-size: 14px !important; line-height: 18px !important; white-space: nowrap !important; word-break: keep-all !important; color: rgb(var(--primary-6)); border-color: rgba(var(--primary-6), 0.6) !important; border-radius: 4px !important; } .toppanbtn .arco-btn.iconbtn > .arco-btn-icon { padding-right: 4px; } .toppanbtn .arco-btn:hover, .toppanbtn .arco-btn:active { background: rgba(var(--primary-6), 0.1) !important; } .toppanbtn .searchpan { border: 1px solid rgb(var(--primary-6)) !important; border-right: none !important; border-radius: 4px !important; } .toppanbtn .searchpan .arco-btn.arco-input-search-btn { border-radius: 4px !important; } .toppanbtn .arco-input-search .arco-input-wrapper { background: var(--color-bg-2); border: none !important; } .toppanbtn .arco-btn.arco-btn-primary { border-radius: 0 !important; } .toppanbtn .arco-btn.arco-btn-primary:hover { background: rgb(var(--primary-5)) !important; } .toppanbtn .arco-btn.arco-btn-primary:active { background: rgb(var(--primary-7)) !important; } .toppanbtn > .arco-btn + .arco-btn { border-left: 0 !important; } .toppanbtn > .arco-btn:not(:last-child) { border-right: 0 !important; } .toppanbtn > .arco-btn:not(:first-child) { border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important; } .toppanbtn > .arco-btn:not(:last-child) { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; } .toppanbtn .iconfont { font-size: 18px; line-height: 24px; } .toppanbtn .arco-btn > span { line-height: 24px; } .toppanbtn .arco-btn > .arco-btn-icon { min-width: 18px; margin-right: 0 !important; } .toppanbtn .arco-btn.arco-btn-dangerous:hover, .toppanbtn .arco-btn.arco-btn-dangerous:focus { color: #fff !important; border-color: rgb(255, 77, 79) !important; background: rgb(255, 77, 79) !important; } .toppanbtn .arco-input-search { width: 130px; transition: width 0.3s; } @media only screen and (max-width: 859px) { .arco-input-wrapper { padding-right: 6px !important; padding-left: 6px !important; } } @media only screen and (min-width: 820px) { .toppanbtn .arco-input-search { width: 140px; } } @media only screen and (min-width: 860px) { .toppanbtn .arco-input-search { width: 160px; } } @media only screen and (min-width: 960px) { .toppanbtn .arco-input-search { width: 180px; } .toppanbtn .arco-input-search.arco-input-focus { width: 200px; } } @media only screen and (min-width: 1000px) { .toppanbtn .arco-input-search.arco-input-focus { width: 220px; } } @media only screen and (min-width: 1200px) { .toppanbtn .arco-input-search { width: 200px; } .toppanbtn .arco-input-search.arco-input-focus { width: 240px; } } body[arco-theme='dark'] .toppanbtn .arco-btn { background: none !important; } body[arco-theme='dark'] .toppanbtn .arco-btn:hover, body[arco-theme='dark'] .toppanbtn .arco-btn:active { background: #4c4c61 !important; } body[arco-theme='dark'] .toppanbtn .arco-btn { color: #ffffffd9; background: #353544; border: 1px solid #444457; border-color: #444457 !important; box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 12%) !important; } .toppanarea { box-sizing: border-box; display: flex; flex-direction: row; flex-wrap: nowrap; height: 40px; color: var(--color-text-3); line-height: 38px; border-top: 1px solid #e5e8ed99; border-bottom: 1px solid #e5e8ed99; } body[arco-theme='dark'] .toppanarea { border-top: 1px solid #e5e8ed22; border-bottom: 1px solid #e5e8ed22; } .toppanarea > div { display: flex; align-items: center; height: 38px; } .toppanarea .selectInfo { height: 38px; line-height: 38px; font-size: 14px; overflow: hidden; white-space: nowrap; word-break: keep-all; } .toppanarea .cell { font-size: 12px; } .toppanarea .cell.active, .toppanarea .cell.active .iconxia { color: rgb(var(--primary-6)); } .select, .select > button { min-width: 34px !important; height: 34px !important; min-height: 34px !important; padding: 0px !important; color: rgb(var(--primary-6)) !important; font-size: 14px; line-height: 34px !important; border: none !important; } .select:hover, .select:active, .select.active { background: rgba(99, 125, 255, 0.1) !important; color: rgb(var(--primary-6)) !important; } .select .iconfont { font-size: 24px; line-height: 34px; color: rgb(var(--primary-6)) !important; } .select .iconfont.iconrpic { opacity: 0.8; } .vermodalhead { display: flex; align-items: center; line-height: 48px; } .verupdate { width: 48px; height: 48px; display: inline-block; background-size: contain; background-image: url(data:image/png;base64,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MSJbtyrnpukiR4/anoPIQkBghz7rEmnYUJSzT2T5cttzwpZypol06iQiBATljktYAAAjBAQAYISAAACM8BwIgJAR/Kt+PFh70SKnr+Q4B95555IfWF8GB1sWF8trto8gshAQACEjWOejvLu2rlgRFGkoW22vwX/DJSwAgBECAgAwQkAAAEYICADACAEBABghIAAAIwQEAGCEgAAAjBAQAIARAgIAMEJAAABGCAgAwAgBAQAYISAAACMEBABghIAAAIwQEACAEQICADDCLW1hiT4nUlAgIj6Rt96yvSZs6WAbkfx82zMQmQgIrFDOzSNFvv76wkc9e9reE8b+YnsAIheXsAAARggIAMAIAQEAGCEgAAAjBAQAYISAAACMEBAAgBECAgAwQkAAAEYICADACAEBABghIAAAIwQEAGCEgAAAjBAQAIARAgIAMEJAAABG/h+9SX6edMAaRQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMi0xNlQxODo0ODozOCswODowMJ6ZayIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDItMTZUMTg6NDg6MzgrMDg6MDDvxNOeAAAASnRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9ob21lL2FkbWluL2ljb24tZm9udC90bXAvaWNvbl94bjhrYnQ4OHZkai9jcy1zai0xLnN2Z7EpmJkAAAAASUVORK5CYII=); } .vertip { padding-left: 12px; color: rgb(40, 104, 240); flex-grow: 1; } .arco-tree-node-custom-icon { margin-right: 4px !important; } .xbyleft { box-shadow: 2px 0 8px 0 var(--leftshadow) !important; } .xbyright { padding-left: 16px; } .headdesc { box-sizing: border-box; height: 40px; padding: 0 0 0 12px; color: #8a9ca5; line-height: 40px; user-select: none; -webkit-user-drag: none; white-space: nowrap; word-break: keep-all; overflow: hidden; } .xbyleftmenu.arco-menu .arco-menu-inner { padding: 0 2px 0 0 !important; } .xbyleftmenu.arco-menu .arco-menu-item { padding: 0 8px; margin-bottom: 2px; line-height: 40px; height: 40px; } .xbyleftmenu.arco-menu .arco-menu-item::after { position: absolute; top: 0; left: 0; bottom: 0; transform: scaleY(0.0001); opacity: 0; transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1); content: ''; } .xbyleftmenu.arco-menu .arco-menu-item.arco-menu-selected::after { transform: scaleY(1); opacity: 1; transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1); border-right: 2px solid #637dff; } .xbyleftmenu.arco-menu .arco-menu-item .arco-menu-icon { width: 30px; text-align: left; margin-right: 0; padding-left: 2px; display: inline-block; flex-shrink: 0; flex-grow: 0; } .xbyleftmenu.arco-menu .arco-menu-item .arco-menu-icon .iconfont { font-size: 20px; } .arco-select-dropdown .arco-select-option, .arco-autocomplete-popup .arco-select-popup .arco-select-option { line-height: 28px !important; height: 28px !important; } .arco-tabs { position: static !important; } .messagebadge { background-color: #86909c; line-height: 14px; height: 14px; position: static; margin: 0 6px; min-width: 20px; padding: 0 6px; color: var(--color-white); font-weight: 500; font-size: 12px; box-shadow: 0 0 0 2px var(--color-bg-2); box-sizing: border-box; overflow: hidden; text-align: center; border-radius: 20px; transform: translate(50%, -50%); transform-origin: 100% 0%; } .arco-modal { border-radius: 0.75rem !important; box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 0.3) !important; } .shortcut-key { display: inline-flex; font-family: 'Inter', sans-serif; font-size: 12px; background-color: #f3f4f6; border-radius: 0.25rem; margin-left: 0.5rem; padding-left: 0.25rem; padding-right: 0.25rem; } .arco-btn-text.arco-btn-status-warning:hover { color: rgb(var(--warning-6)) !important; background-color: var(--color-warning-light-1) !important; border-color: var(--color-warning-light-2) !important; } .arco-modal-header { border-bottom: 1px solid transparent !important; } .arco-card { border-radius: 6px !important; } .arco-divider-text { border-radius: 4px !important; } .workertitle { margin-top: 64px; color: rgb(var(--primary-6)); } .arco-scrollbar { height: 100%; } ================================================ FILE: src/renderer/down/DownDowned.vue ================================================ ================================================ FILE: src/renderer/down/DownDowning.vue ================================================ ================================================ FILE: src/renderer/down/DownM3U8.vue ================================================ ================================================ FILE: src/renderer/down/DownSync.vue ================================================ ================================================ FILE: src/renderer/down/DownUploaded.vue ================================================ ================================================ FILE: src/renderer/down/DownUploading.vue ================================================ ================================================ FILE: src/renderer/down/downdal.ts ================================================ import { IAliGetFileModel } from '../aliapi/alimodels' declare type DownloadState = | '排队中' // 排队中, 等待下载 | 'running' // 下载中 | 'hashing' // 计算hash,校验完整性 | '已暂停' // 已暂停 | 'success' // 下载成功 | 'error' // 下载失败 export interface IStateDownFile { DownID: string __v_skip: true user_id: string file_id: string drive_id: string DownSavePath: string name: string size: number sizeStr: string icon: string isDir: boolean crc64: string download_url: string DownState: DownloadState } export interface IStateDownProgress { DownTime: number DownSize: number DownSpeed: number DownSpeedStr: string DownProcess: number failedCode: number failedMessage: string AutoTry: number } export interface IAriaDownProgress { gid: string status: string totalLength: string completedLength: string downloadSpeed: string errorCode: string errorMessage: string } export const DowningList = new Map() export const DownedList: IStateDownFile[] = [] export default class DownDAL { static aAddDownload(fileList: IAliGetFileModel[], savepath: string, needPanPath: boolean, tip: boolean) {} static async aSpeedEvent() {} static mSpeedEvent(list: IAriaDownProgress[]) {} static QueryIsDowning() { return false } static QuerySelectedIsDowning() { return false } static async aReloadDowning() {} static async aReloadDowned() {} static async aClearDowned() { // const max = useSettingStore().debugDownedListMax // return DBDown.deleteDownedOutCount(max) } static DowningState(all: boolean, start: boolean) {} static DowningOrder() {} static DowningDelete(all: boolean) {} static DownedDelete(all: boolean) {} } ================================================ FILE: src/renderer/down/downingstore.ts ================================================ import { GetFocusNext, GetSelectedList, KeyboardSelectOne, MouseSelectOne, SelectAll } from '../utils/selecthelper' import { defineStore } from 'pinia' import { IStateDownFile } from './downdal' type Item = IStateDownFile export interface DownState { ListDataRaw: Item[] ListDataShow: Item[] ListSelected: Set ListFocusKey: string ListSelectKey: string } type State = DownState const KEY = 'DownID' const useDownStore = defineStore('downing', { state: (): DownState => ({ ListDataRaw: [], ListDataShow: [], ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '' }), getters: { ListDataCount(state: State): number { return state.ListDataShow.length }, IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length }, ListStats(state: State) { const stats = { preview: 0, download: 0, save: 0, previewMax: 0, forbidden: 0, expired: 0, expir2day: 0 } return stats } }, actions: { aLoadListData(list: Item[]) { const oldSelected = this.ListSelected const newSelected = new Set() let key = '' let findFocusKey = false let findSelectKey = false let listFocusKey = this.ListFocusKey let listSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == listFocusKey) findFocusKey = true if (key == listSelectKey) findSelectKey = true } if (!findFocusKey) listFocusKey = '' if (!findSelectKey) listSelectKey = '' this.$patch({ ListSelected: newSelected, ListFocusKey: listFocusKey, ListSelectKey: listSelectKey }) this.mRefreshListDataShow(true) }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow return } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = '' for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: '', ListSelectKey: '' }) this.mRefreshListDataShow(false) }, mMouseSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: string) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (!this.ListFocusKey && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, '') } } }) export default useDownStore ================================================ FILE: src/renderer/down/downmenu.ts ================================================ import DownDAL from './downdal' import UploadDAL from '../transfer/uploaddal' import UploadingDAL from '../transfer/uploadingdal' export function topStartDown(isdown: boolean) { if (isdown) { DownDAL.DowningState(false, true) } else { } } export function topStartDownAll(isdown: boolean) { if (isdown) { DownDAL.DowningState(true, true) } else { } } export function topStopDown(isdown: boolean) { if (isdown) { DownDAL.DowningState(false, false) } else { } } export function topStopDownAll(isdown: boolean) { if (isdown) { DownDAL.DowningState(true, false) } else { } } export function topDeleteDown(isdown: boolean) { if (isdown) { DownDAL.DowningDelete(false) } else { UploadingDAL.aUploadingDelete(false) } } export function topDeleteDownAll(isdown: boolean) { if (isdown) { DownDAL.DowningDelete(true) } else { UploadingDAL.aUploadingDelete(true) } } export function topDeleteDowned(isdown: boolean) { if (isdown) { DownDAL.DownedDelete(false) } else { UploadDAL.UploadedDelete(false) } } export function topDeleteDownedAll(isdown: boolean) { if (isdown) { DownDAL.DownedDelete(true) } else { UploadDAL.UploadedDelete(true) } } ================================================ FILE: src/renderer/down/index.vue ================================================ ================================================ FILE: src/renderer/down/uploadedstore.ts ================================================ import { defineStore } from 'pinia' import { GetSelectedList, GetFocusNext, SelectAll, MouseSelectOne, KeyboardSelectOne } from '../utils/selecthelper' import { IStateUploadTask } from '../utils/dbupload' type Item = IStateUploadTask export interface UploadedState { ListLoading: boolean ListDataShow: Item[] ListSelected: Set ListFocusKey: number ListSelectKey: number ListDataCount: number } type State = UploadedState const KEY = 'TaskID' const useUploadedStore = defineStore('uploaded', { state: (): UploadedState => ({ ListLoading: false, ListDataShow: [], ListSelected: new Set(), ListFocusKey: 0, ListSelectKey: 0, ListDataCount: 0 }), getters: { IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length } }, actions: { aLoadListData(list: Item[], count: number) { this.ListDataShow = list const oldSelected = this.ListSelected const newSelected = new Set() let key = 0 let findFocusKey = false let findSelectKey = false let listFocusKey = this.ListFocusKey let listSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == listFocusKey) findFocusKey = true if (key == listSelectKey) findSelectKey = true } if (!findFocusKey) listFocusKey = 0 if (!findSelectKey) listSelectKey = 0 this.$patch({ ListSelected: newSelected, ListFocusKey: listFocusKey, ListSelectKey: listSelectKey, ListDataCount: count }) this.mRefreshListDataShow(true) }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow return } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = 0 for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: 0, ListSelectKey: 0 }) this.mRefreshListDataShow(false) }, mMouseSelect(key: number, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, 0) this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: number, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, 0) this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: number) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (this.ListFocusKey > 0 && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, 0) }, mDeleteFiles(taskidlist: number[]) { const fileMap = new Set(taskidlist) const listDataRaw = this.ListDataShow const newDataList: Item[] = [] for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (!fileMap.has(item.TaskID)) { newDataList.push(item) } } this.ListDataShow = newDataList this.mRefreshListDataShow(true) } } }) export default useUploadedStore ================================================ FILE: src/renderer/down/uploadingstore.ts ================================================ import { defineStore } from 'pinia' import { GetSelectedList, GetFocusNext, SelectAll, MouseSelectOne, KeyboardSelectOne } from '../utils/selecthelper' export interface IUploadingModel { UploadID: number TaskID: number localFilePath: string name: string sizeStr: string icon: string isDir: boolean uploadState: string speedStr: string Progress: number ProgressStr: string errorMessage: string } type Item = IUploadingModel export interface UploadingState { ListLoading: boolean ListDataShow: Item[] ListSelected: Set ListFocusKey: number ListSelectKey: number ListDataCount: number showTaskID: number ShowTaskName: string } type State = UploadingState let KEY: 'UploadID' | 'TaskID' = 'UploadID' const useUploadingStore = defineStore('uploading', { state: (): UploadingState => ({ ListLoading: false, ListDataShow: [], ListSelected: new Set(), ListFocusKey: 0, ListSelectKey: 0, ListDataCount: 0, showTaskID: 0, ShowTaskName: '' }), getters: { IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length } }, actions: { aLoadListData(TaskID: number, TaskName: string, list: Item[], count: number) { KEY = TaskID ? 'UploadID' : 'TaskID' this.ListDataShow = list if (this.showTaskID == TaskID) { const oldSelected = this.ListSelected const newSelected = new Set() let findFocusKey = false let findSelectKey = false let key = 0 let listFocusKey = this.ListFocusKey let listSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == listFocusKey) findFocusKey = true if (key == listSelectKey) findSelectKey = true } if (!findFocusKey) listFocusKey = 0 if (!findSelectKey) listSelectKey = 0 this.$patch({ ListSelected: newSelected, ListFocusKey: listFocusKey, ListSelectKey: listSelectKey, ListDataCount: count }) } else { this.$patch({ showTaskID: TaskID, ShowTaskName: TaskName, ListSelected: new Set(), ListFocusKey: 0, ListSelectKey: 0, ListDataCount: count }) } this.mRefreshListDataShow(true) }, mShowTask(TaskID: number, TaskName: string) { KEY = TaskID ? 'UploadID' : 'TaskID' this.$patch({ showTaskID: TaskID, ShowTaskName: TaskName, ListSelected: new Set(), ListFocusKey: 0, ListSelectKey: 0, ListDataShow: [] }) }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow return } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = 0 for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: 0, ListSelectKey: 0 }) this.mRefreshListDataShow(false) }, mMouseSelect(key: number, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, 0) this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: number, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, 0) this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: number) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (this.ListFocusKey > 0 && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, 0) }, mDeleteFiles(idList: number[]) { const fileMap = new Set(idList) const listDataRaw = this.ListDataShow const newDataList: Item[] = [] for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (!fileMap.has(item.UploadID)) { newDataList.push(item) } } this.ListDataShow = newDataList this.mRefreshListDataShow(true) } } }) export default useUploadingStore ================================================ FILE: src/renderer/env.d.ts ================================================ /* eslint-disable no-unused-vars */ /// declare module '*.vue' { import { DefineComponent } from 'vue' // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types const component: DefineComponent<{ tabindex: string; id: string }, {}, any> export default component } declare enum TaskState { Success, // 已成功 Error, // 出错停止 Running, // 上传中 Stoped, // 已暂停 Waiting, // 排队中 Autotry // 稍后自动重试 } declare type CheckNameMode = | 'overwrite' // overwrite (直接覆盖,以后多版本有用) | 'auto_rename' // auto_rename (自动换一个随机名称) | 'refuse' // refuse (不会创建,告诉你已经存在) | 'ignore' // ignore (会创建重名的) declare type FileType = | 'file' // 文件 | 'folder' // 文件夹(目录) declare type UploadStates = | 'waiting' // 排队中, 等待上传 | 'start' // 开始 | 'computing_hash' // 计算hash,预秒传,秒传 | 'created' // 创建成功 | 'running' // 上传中 | 'stopped' // 暂停 | 'complete' // 上传完成 | 'checking' // 校验中, 检查 crc64 是否一致 | 'success' // 上传成功 | 'rapid_success' // 秒传成功 | 'error' // 上传失败 | 'cancelled' // 已取消 // DownloadState 没有 computing_hash & rapid_success declare type DownloadStates = | 'waiting' // 排队中, 等待下载 | 'start' // 开始 | 'created' // 创建成功 | 'running' // 下载中 | 'stopped' // 暂停 | 'complete' // 下载完成 | 'checking' // 校验中, 检查 crc64 是否一致 | 'success' // 下载成功 | 'error' // 下载失败 | 'cancelled' // 已取消 declare module 'Go' declare module 'dom-to-image' declare module 'jschardet' declare function pinyinlite(text: string, config: any): any declare function videojs(ref: any, options: any, cb: any): any ================================================ FILE: src/renderer/global.d.ts ================================================ export {} declare global { // eslint-disable-next-line no-unused-vars interface Window { Go: any require: any Electron: any openDatabase: any WebRelaunchAria: any platform: string WinMsg: any postdataFunc: any Prism: any WebUserToken: any WebToElectron: any WebClearCache: any WebRelaunch: any WebClearCookies: any WebShutDown: any WebOpenWindow: any WebOpenUrl: any WebShowOpenDialogSync: any WebExecSync: any WebPlatformSync: any UploadPort: any DownloadPort: any MainPort: any WinMsgToUpload: any WinMsgToDownload: any WinMsgToMain: any IsMainPage: boolean WebSetProxy: any speedLimte: number } } ================================================ FILE: src/renderer/layout/MyLoading.vue ================================================ ================================================ FILE: src/renderer/layout/MyModal.vue ================================================ ================================================ FILE: src/renderer/layout/MySplit.vue ================================================ ================================================ FILE: src/renderer/layout/MySwitch.vue ================================================ ================================================ FILE: src/renderer/layout/MySwitchTab.vue ================================================ ================================================ FILE: src/renderer/layout/MyTags.vue ================================================ ================================================ FILE: src/renderer/layout/PageCode.vue ================================================ ================================================ FILE: src/renderer/layout/PageHelp.vue ================================================ ================================================ FILE: src/renderer/layout/PageImage.vue ================================================ ================================================ FILE: src/renderer/layout/PageLoading.vue ================================================ ================================================ FILE: src/renderer/layout/PageMain.vue ================================================ ================================================ FILE: src/renderer/layout/PageOffice.vue ================================================ ================================================ FILE: src/renderer/layout/PageVideo.vue ================================================ ================================================ FILE: src/renderer/layout/PageVideoXBT.vue ================================================ ================================================ FILE: src/renderer/layout/PageWorker.vue ================================================ ================================================ FILE: src/renderer/layout/pagemain.ts ================================================ import ServerHttp from '../aliapi/server' import { useAppStore, useFootStore, useSettingStore } from '../store' import AppCache from '../utils/appcache' import DownDAL from '../down/downdal' import UploadDAL from '../transfer/uploaddal' import ShareDAL from '../share/share/ShareDAL' import UserDAL from '../user/userdal' import DebugLog from '../utils/debuglog' import PanDAL from '../pan/pandal' import UploadingDAL from '../transfer/uploadingdal' import { Sleep } from '../utils/format' export function PageMain() { if (window.WinMsg) return window.WinMsg = WinMsg useSettingStore().WebSetProxy() Promise.resolve() .then(async () => { DebugLog.mSaveSuccess('小白羊启动') await ShareDAL.aLoadFromDB().catch((err: any) => { DebugLog.mSaveDanger('ShareDALLDB', err) }) await UserDAL.aLoadFromDB().catch((err: any) => { DebugLog.mSaveDanger('UserDALLDB', err) }) }) .then(async () => { await Sleep(500) await DownDAL.aReloadDowning().catch((err: any) => { DebugLog.mSaveDanger('aReloadDowning', err) }) await UploadingDAL.aReloadUploading().catch((err: any) => { DebugLog.mSaveDanger('aReloadUploading', err) }) await DownDAL.aReloadDowned().catch((err: any) => { DebugLog.mSaveDanger('aReloadDowned', err) }) await UploadDAL.aReloadUploaded().catch((err: any) => { DebugLog.mSaveDanger('aReloadUploaded', err) }) await Sleep(500) await AppCache.aLoadCacheSize().catch((err: any) => { DebugLog.mSaveDanger('AppCacheDALDB', err) }) setTimeout(timeEvent, 1000) }) .catch((err: any) => { DebugLog.mSaveDanger('LoadSettingFromDB', err) }) } export const WinMsg = function (arg: any) { if (arg.cmd == 'MainUploadEvent') { if (arg.ReportList.length > 0 && arg.ReportList.length != arg.RunningKeys.length) console.log('RunningKeys', arg) if (arg.StopKeys.length > 0) console.log('StopKeys', arg) UploadingDAL.aUploadingEvent(arg.ReportList, arg.ErrorList, arg.SuccessList, arg.RunningKeys, arg.StopKeys, arg.LoadingKeys, arg.SpeedTotal) } else if (arg.cmd == 'MainUploadAppendFiles') { UploadingDAL.aUploadingAppendFiles(arg.TaskID, arg.UploadID, arg.CreatedDirID, arg.AppendList) } else if (arg.cmd == 'MainSaveAllDir') { PanDAL.aReLoadDriveSave(arg.OneDriver, arg.ErrorMessage) } else if (arg.cmd == 'MainShowAllDirProgress') { useFootStore().mSaveLoading('加载全部文件夹(' + Math.floor((arg.index * 100) / (arg.total + 1)) + '%)') } } let runTime = Math.floor(Date.now() / 1000) let chkUpgradeTime1 = Math.floor(Date.now() / 1000) let chkUpgradeTime2 = Math.floor(Date.now() / 1000) let chkDirSizeTime = 0 let lockDirSizeTime = false let chkClearDownLogTime = 0 let chkTokenTime = 0 let chkTaskTime = 0 function timeEvent() { const settingStore = useSettingStore() const nowTime = Math.floor(Date.now() / 1000) if (nowTime - runTime > 60 * 60 * 24) { runTime = nowTime chkDirSizeTime = 0 } if (chkUpgradeTime1 > 0 && nowTime - chkUpgradeTime1 > 360) { chkUpgradeTime1 = -1 ServerHttp.CheckUpgrade(false).catch((err: any) => { DebugLog.mSaveDanger('CheckUpgrade', err) }) } if (nowTime - chkUpgradeTime2 > 14300) { chkUpgradeTime2 = nowTime ServerHttp.CheckUpgrade(false).catch((err: any) => { DebugLog.mSaveDanger('CheckUpgrade', err) }) } if (settingStore.uiFolderSize == true && lockDirSizeTime == false && nowTime - runTime > 50 && chkDirSizeTime >= 10) { lockDirSizeTime = true PanDAL.aUpdateDirFileSize() .catch((err: any) => { DebugLog.mSaveDanger('aUpdateDirFileSize', err) }) .then(() => { chkDirSizeTime = 0 lockDirSizeTime = false }) } else chkDirSizeTime++ chkClearDownLogTime++ if (nowTime - runTime > 60 && chkClearDownLogTime >= 540) { chkClearDownLogTime = 0 UploadDAL.aClearUploaded().catch((err: any) => { DebugLog.mSaveDanger('aClearUploaded ', err) }) DownDAL.aClearDowned().catch((err: any) => { DebugLog.mSaveDanger('aClearDowned ', err) }) } chkTokenTime++ if (nowTime - runTime > 10 && chkTokenTime >= 600) { chkTokenTime = 0 UserDAL.aRefreshAllUserToken().catch((err: any) => { DebugLog.mSaveDanger('aRefreshAllUserToken', err) }) } chkTaskTime++ if (nowTime - runTime > 6 && chkTaskTime >= 2) { chkTaskTime = 0 useFootStore().aUpdateTask() } DownDAL.aSpeedEvent().catch((err: any) => { DebugLog.mSaveDanger('aSpeedEvent', err) }) if (settingStore.downAutoShutDown == 2) { if (DownDAL.QueryIsDowning() == false && UploadingDAL.QueryIsUploading() == false) { settingStore.downAutoShutDown = 0 useAppStore().appShutDown = true } } setTimeout(timeEvent, 1000) } ================================================ FILE: src/renderer/main.ts ================================================ import { createApp } from 'vue' import App from './App.vue' import ArcoVue from '@arco-design/web-vue' import store, { useAppStore, useSettingStore } from './store' import '@arco-design/web-vue/dist/arco.css' import message from './utils/message' import DebugLog from './utils/debuglog' import { PageMain } from './layout/pagemain' import { WorkerPage } from './workerpage/workercmd' window.onerror = function (errorMessage, scriptURI, lineNo, columnNo, error) { try { if (errorMessage && typeof errorMessage === 'string' && errorMessage.indexOf('ResizeObserver loop limit exceeded') >= 0) return true DebugLog.mSaveDanger('onerror') if (typeof errorMessage === 'string') { DebugLog.mSaveDanger(errorMessage) message.error('onerror ' + errorMessage, 8) } if (error) { DebugLog.mSaveDanger('onerror', error) message.error('onerror ' + error.message, 8) } } catch {} return true } window.addEventListener('unhandledrejection', function (event) { try { if (event.reason && event.reason.message && event.reason.message.indexOf('oauth/authorize?') > 0) { event.stopPropagation() event.preventDefault() return } DebugLog.mSaveDanger('unhandledrejection') const reason = event.reason if (reason && reason.message) { DebugLog.mSaveDanger('unhandledrejection', reason) message.error('rejection ' + reason.message, 8) } if (!reason) DebugLog.mSaveDanger('unhandledrejection', JSON.stringify(event)) } catch {} event.stopPropagation() event.preventDefault() }) const app = createApp(App) app.config.errorHandler = function (err: any, vm, info) { try { if (typeof err === 'string') { DebugLog.mSaveDanger('errorHandler', err) message.error('errorHandler ' + err, 8) } else { DebugLog.mSaveDanger('errorHandler', err) if (err && err.message) message.error('errorHandler ' + err.message, 8) } } catch {} return true } app.use(ArcoVue, {}) app.use(store) app.mount('#app') window.WinMsgToMain = function (event: any) { if (window.MainPort) window.MainPort.postMessage(event) } window.WinMsgToUpload = function (event: any) { if (window.UploadPort) window.UploadPort.postMessage(event) } window.WinMsgToDownload = function (event: any) { if (window.DownloadPort) window.DownloadPort.postMessage(event) } window.Electron.ipcRenderer.on('setPort', (_event: any, args: any) => { const [port] = _event.ports window.MainPort = port port.onmessage = (event: any) => { Promise.resolve().then(() => { try { if (window.WinMsg) window.WinMsg(event.data) } catch {} }) } }) window.Electron.ipcRenderer.on('setUploadPort', (_event: any, args: any) => { const [port] = _event.ports window.UploadPort = port port.onmessage = (event: any) => { Promise.resolve().then(() => { try { if (window.WinMsg) window.WinMsg(event.data) } catch {} }) } }) window.Electron.ipcRenderer.on('setDownloadPort', (_event: any, args: any) => { const [port] = _event.ports window.DownloadPort = port port.onmessage = (event: any) => { Promise.resolve().then(() => { try { if (window.WinMsg) window.WinMsg(event.data) } catch {} }) } }) window.Electron.ipcRenderer.on('setPage', (_event: any, args: any) => { console.log('setPage', args.page, args) const appStore = useAppStore() const settingStore = useSettingStore() if (args.theme && settingStore) appStore.toggleTheme(args.theme) if (args.page == 'PageMain') { PageMain() window.IsMainPage = true } else if (args.page == 'PageWorker') { WorkerPage(args.data.type) } else if (args.page == 'PageCode') { appStore.pageCode = args.data } else if (args.page == 'PageOffice') { appStore.pageOffice = args.data } else if (args.page == 'PageImage') { appStore.pageImage = args.data } else if (args.page == 'PageVideoXBT') { appStore.pageVideoXBT = args.data } else if (args.page == 'PageVideo') { appStore.pageVideo = args.data } if (args.page) appStore.togglePage(args.page) }) window.Electron.ipcRenderer.on('setTheme', (_event: any, args: any) => { const appStore = useAppStore() appStore.toggleDark(args.dark) }) try { process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' } catch {} ================================================ FILE: src/renderer/pan/PanLeft.vue ================================================ ================================================ FILE: src/renderer/pan/PanRight.vue ================================================ ================================================ FILE: src/renderer/pan/index.vue ================================================ ================================================ FILE: src/renderer/pan/menus/DirLeftMenu.vue ================================================ ================================================ FILE: src/renderer/pan/menus/DirTopPath.vue ================================================ ================================================ FILE: src/renderer/pan/menus/FileRightMenu.vue ================================================ ================================================ FILE: src/renderer/pan/menus/FileTopbtn.vue ================================================ ================================================ FILE: src/renderer/pan/menus/PanTopbtn.vue ================================================ ================================================ FILE: src/renderer/pan/menus/TrashRightMenu.vue ================================================ ================================================ FILE: src/renderer/pan/menus/TrashTopbtn.vue ================================================ ================================================ FILE: src/renderer/pan/pandal.ts ================================================ import { IAliGetDirModel } from '../aliapi/alimodels' import AliFile from '../aliapi/file' import AliDirFileList from '../aliapi/dirfilelist' import { useFootStore, usePanFileStore } from '../store' import TreeStore, { IDriverModel, TreeNodeData } from '../store/treestore' import DB from '../utils/db' import DebugLog from '../utils/debuglog' import message from '../utils/message' import usePanTreeStore from './pantreestore' export interface PanSelectedData { isError: boolean isErrorSelected: boolean user_id: string drive_id: string dirID: string parentDirID: string selectedKeys: string[] selectedParentKeys: string[] } const RefreshLock = new Set() export default class PanDAL { static async aReLoadDrive(user_id: string, drive_id: string): Promise { const pantreeStore = usePanTreeStore() pantreeStore.mSaveUser(user_id, drive_id) if (!user_id || !drive_id) return const cache = await DB.getValueObject('AllDir_' + drive_id) if (cache) { console.log('aReLoadDrive cache') await TreeStore.ConvertToOneDriver(drive_id, cache as IAliGetDirModel[], false, true) // PanDAL.RefreshPanTreeAllNode(drive_id) } await PanDAL.aReLoadOneDirToShow(drive_id, 'root', true) if (cache) { const dt = await DB.getValueNumber('AllDir_' + drive_id) if (Date.now() - dt < 1000 * 60 * 60) { return } } useFootStore().mSaveLoading('加载全部文件夹...') window.WinMsgToUpload({ cmd: 'AllDirList', user_id, drive_id }) } static async aReLoadDriveSave(OneDriver: IDriverModel, error: string): Promise { if (error == 'time') return if (!error) { TreeStore.SaveOneDriver(OneDriver) PanDAL.RefreshPanTreeAllNode(OneDriver.drive_id) } else { message.error('列出全盘文件夹失败' + error) } useFootStore().mSaveLoading('') } static RefreshPanTreeAllNode(drive_id: string) { const OneDriver = TreeStore.GetDriver(drive_id) if (!OneDriver) return console.log('RefreshPanTreeAllNode') const pantreeStore = usePanTreeStore() const expandedKeys = new Set(pantreeStore.treeExpandedKeys) const dir: TreeNodeData = { __v_skip: true, title: '根目录', namesearch: '', key: 'root', children: [] } const map = new Map() TreeStore.GetTreeDataToShow(OneDriver, dir, expandedKeys, map, true) map.set(dir.key, dir) pantreeStore.mSaveTreeAllNode(OneDriver.drive_id, dir, map) } static GetPanTreeAllNode(drive_id: string, treeExpandedKeys: string[]): TreeNodeData[] { const OneDriver = TreeStore.GetDriver(drive_id) if (!OneDriver) return [] console.log('GetPanTreeAllNode') const expandedKeys = new Set(treeExpandedKeys) const dir: TreeNodeData = { __v_skip: true, title: '根目录', namesearch: '', key: 'root', children: [] } const map = new Map() TreeStore.GetTreeDataToShow(OneDriver, dir, expandedKeys, map, true) map.set(dir.key, dir) return [dir] } static aTreeScrollToDir(dirID: string) { usePanTreeStore().mSaveTreeScrollTo(dirID) } static async aReLoadOneDirToShow(drive_id: string, file_id: string, selfExpand: boolean): Promise { const pantreeStore = usePanTreeStore() if (!drive_id) drive_id = pantreeStore.drive_id if (!drive_id) return false if (file_id == 'refresh') file_id = pantreeStore.selectDir.file_id const isBack = file_id == 'back' if (isBack) { if (pantreeStore.History.length > 0) { pantreeStore.History.splice(0, 1) if (pantreeStore.History.length > 0) { drive_id = pantreeStore.History[0].drive_id file_id = pantreeStore.History[0].file_id } } if (file_id == 'back') { pantreeStore.History = [] file_id = 'root' } } let dir = TreeStore.GetDir(drive_id, file_id) let dirPath = TreeStore.GetDirPath(drive_id, file_id) if (!dir || (dirPath.length == 0 && file_id != 'root')) { const findPath = await AliFile.ApiFileGetPath(pantreeStore.user_id, drive_id, file_id) if (findPath.length > 0) { dirPath = findPath dir = { ...dirPath[dirPath.length - 1] } } } if (!dir || (dirPath.length == 0 && file_id != 'root')) { message.error('出错,找不到指定的文件夹 ' + file_id) return false } if (!isBack && pantreeStore.selectDir.file_id != dir.file_id) { const history: IAliGetDirModel[] = [dir] for (let i = 0, maxi = pantreeStore.History.length; i < maxi; i++) { const his = pantreeStore.History[i] history.push(his) if (history.length >= 50) break } pantreeStore.History = history } const treeExpandedKeys = new Set(pantreeStore.treeExpandedKeys) treeExpandedKeys.add('root') for (let i = 0, maxi = dirPath.length - 1; i < maxi; i++) { treeExpandedKeys.add(dirPath[i].file_id) } if (selfExpand) treeExpandedKeys.add(dir.file_id) pantreeStore.mShowDir(dir, dirPath, [dir.file_id], Array.from(treeExpandedKeys)) PanDAL.RefreshPanTreeAllNode(drive_id) const panfileStore = usePanFileStore() if (panfileStore.ListLoading && panfileStore.DriveID == drive_id && panfileStore.DirID == dir.file_id) return false panfileStore.mSaveDirFileLoading(drive_id, dir.file_id, dir.name) return PanDAL.GetDirFileList(pantreeStore.user_id, dir.drive_id, dir.file_id, dir.name) } static GetDirFileList(user_id: string, drive_id: string, dirID: string, dirName: string, hasFiles: boolean = true): Promise { return new Promise((resolve) => { if (dirID == 'search') { if (hasFiles) usePanFileStore().mSaveDirFileLoadingFinish(drive_id, dirID, []) resolve(true) return } const order = TreeStore.GetDirOrder(drive_id, dirID).replace('ext ', 'updated_at ') AliDirFileList.ApiDirFileList(user_id, drive_id, dirID, dirName, order, hasFiles ? '' : 'folder') .then((dir) => { if (!dir.next_marker) { TreeStore.SaveOneDirFileList(dir, hasFiles).then(() => { if (hasFiles) usePanFileStore().mSaveDirFileLoadingFinish(drive_id, dirID, dir.items, dir.itemsTotal || 0) PanDAL.RefreshPanTreeAllNode(drive_id) resolve(true) }) } else if (dir.next_marker == 'cancel') { resolve(false) } else { message.warning('列出文件夹失败 ' + dir.next_marker) if (hasFiles) usePanFileStore().mSaveDirFileLoadingFinish(drive_id, dirID, []) resolve(false) } }) .catch((err: any) => { if (hasFiles) usePanFileStore().mSaveDirFileLoadingFinish(drive_id, dirID, []) message.warning('列出文件夹失败 ' + (err.message || '')) DebugLog.mSaveWarning('列出文件夹失败file_id=' + dirID, err) resolve(false) }) }) } static aReLoadOneDirToRefreshTree(user_id: string, drive_id: string, dirID: string): Promise { return new Promise((resolve) => { if (dirID == 'favorite' || dirID.startsWith('color') || dirID.startsWith('search') || dirID.startsWith('video')) { resolve(true) return } if (RefreshLock.has(dirID)) { resolve(true) return } RefreshLock.add(dirID) const order = TreeStore.GetDirOrder(drive_id, dirID).replace('ext ', 'updated_at ') AliDirFileList.ApiDirFileList(user_id, drive_id, dirID, '', order, 'folder') .then((dir) => { if (!dir.next_marker) { TreeStore.SaveOneDirFileList(dir, false).then(() => { PanDAL.RefreshPanTreeAllNode(drive_id) const pantreeStore = usePanTreeStore() if (pantreeStore.selectDir.drive_id == drive_id && pantreeStore.selectDir.file_id == dirID) { PanDAL.aReLoadOneDirToShow(drive_id, dirID, false).then(() => { RefreshLock.delete(dirID) resolve(true) }) } else { RefreshLock.delete(dirID) resolve(true) } }) } else if (dir.next_marker == 'cancel') { RefreshLock.delete(dirID) resolve(false) } else { RefreshLock.delete(dirID) resolve(false) } }) .catch((err: any) => { DebugLog.mSaveWarning('列出文件夹失败file_id=' + dirID, err) RefreshLock.delete(dirID) resolve(false) }) }) } static GetPanSelectedData(istree: boolean): PanSelectedData { const pantreeStore = usePanTreeStore() const data: PanSelectedData = { isError: false, isErrorSelected: false, user_id: pantreeStore.user_id, drive_id: pantreeStore.drive_id, dirID: pantreeStore.selectDir.file_id, parentDirID: pantreeStore.selectDir.parent_file_id, selectedKeys: istree ? [pantreeStore.selectDir.file_id] : usePanFileStore().GetSelectedID(), selectedParentKeys: istree ? [pantreeStore.selectDir.parent_file_id] : usePanFileStore().GetSelectedParentDirID() } data.isError = !data.user_id || !data.drive_id || !data.dirID data.isErrorSelected = data.selectedKeys.length == 0 return data } static updateQuickFile(list: { key: string; title: string }[]) { if (list.length == 0) return const pantreeStore = usePanTreeStore() const jsonstr = localStorage.getItem('FileQuick-' + pantreeStore.user_id) const arr = jsonstr ? JSON.parse(jsonstr) : [] list.map((t) => { let find = false for (let i = 0; i < arr.length; i++) { if (arr[i].key == t.key) { arr[i].title = t.title find = true } } if (find == false) arr.push({ key: t.key, title: t.title }) return true }) localStorage.setItem('FileQuick-' + pantreeStore.user_id, JSON.stringify(arr)) pantreeStore.mSaveQuick(arr) } static deleteQuickFile(key: string) { if (!key) return const pantreeStore = usePanTreeStore() const jsonstr = localStorage.getItem('FileQuick-' + pantreeStore.user_id) const arr = jsonstr ? JSON.parse(jsonstr) : [] const newArray: { key: string; title: string }[] = [] for (let i = 0; i < arr.length; i++) { if (arr[i].key != key) newArray.push(arr[i]) } localStorage.setItem('FileQuick-' + pantreeStore.user_id, JSON.stringify(newArray)) pantreeStore.mSaveQuick(newArray) } static getQuickFileList() { const pantreeStore = usePanTreeStore() const jsonstr = localStorage.getItem('FileQuick-' + pantreeStore.user_id) const arr = jsonstr ? JSON.parse(jsonstr) : [] return arr } static aReLoadQuickFile(user_id: string) { const jsonstr = localStorage.getItem('FileQuick-' + user_id) const arr = jsonstr ? JSON.parse(jsonstr) : [] usePanTreeStore().mSaveQuick(arr) } static async aUpdateDirFileSize(): Promise { const pantreeStore = usePanTreeStore() const user_id = pantreeStore.user_id const drive_id = pantreeStore.drive_id const diridList = TreeStore.GetDirSizeNeedRefresh(drive_id, 604800) const partList: string[] = [] for (let i = 0, maxi = diridList.length; i < maxi; i++) { partList.push(diridList[i]) if (partList.length >= 30) { const partResult = await AliDirFileList.ApiDirFileSize(user_id, drive_id, partList) if (!partResult) return if (partResult) TreeStore.SaveDirSizeNeedRefresh(drive_id, partResult) partList.length = 0 } } if (partList.length > 0) { const partResult = await AliDirFileList.ApiDirFileSize(user_id, drive_id, partList) if (partResult) TreeStore.SaveDirSizeNeedRefresh(drive_id, partResult) partList.length = 0 } } } ================================================ FILE: src/renderer/pan/panfilestore.ts ================================================ import { defineStore } from 'pinia' import { IAliGetFileModel } from '../aliapi/alimodels' import { ArrayToMap } from '../utils/utils' import fuzzysort from 'fuzzysort' import { GetFocusNext, GetSelectedList, GetSelectedListID, KeyboardSelectOne, MouseSelectOne, SelectAll } from '../utils/selecthelper' import { IAliFileResp } from '../aliapi/dirfilelist' import PanDAL from './pandal' import TreeStore from '../store/treestore' import { useFootStore } from '../store' type Item = IAliGetFileModel export interface GridItem { file_id: string files: IAliGetFileModel[] } export interface PanFileState { DriveID: string DirID: string DirName: string ListLoading: boolean ListLoadingIndex: number ListDataRaw: Item[] ListDataShow: Item[] ListDataGrid: GridItem[] ListSelected: Set ListOrderKey: string ListFocusKey: string ListSelectKey: string ListSearchKey: string ListShowMode: string ListShowColumn: number scrollToFile: string } type State = PanFileState const KEY = 'file_id' const usePanFileStore = defineStore('panfile', { state: (): State => ({ DriveID: '', DirID: '', DirName: '', ListLoading: false, ListLoadingIndex: 0, ListDataRaw: [], ListDataShow: [], ListDataGrid: [], ListSelected: new Set(), ListOrderKey: 'name desc', ListFocusKey: '', ListSelectKey: '', ListSearchKey: '', ListShowMode: 'list', ListShowColumn: 1, scrollToFile: '' }), getters: { ListDataCount(state: State): number { return state.ListDataShow.length }, IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, IsListSelectedMulti(state: State): boolean { return state.ListSelected.size > 1 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length }, IsListSelectedFavAll(state: State): boolean { const list = state.ListDataShow const len = list.length let isAllFav = true for (let i = 0, maxi = len; i < maxi; i++) { if (state.ListSelected.has(list[i].file_id)) { if (!list[i].starred) { isAllFav = false break } } } return isAllFav }, SelectDirType(state: State): string { const file_id = state.DirID if (file_id == 'recover') return 'recover' if (file_id == 'trash') return 'trash' if (file_id == 'favorite') return 'favorite' if (file_id.startsWith('search')) return 'search' if (file_id.startsWith('color')) return 'color' if (file_id.startsWith('video')) return 'video' return 'pan' }, FileOrderDesc(state: State): string { switch (state.ListOrderKey) { case 'name desc': return '名称 · 降' case 'name asc': return '名称 · 升' case 'updated_at desc': return '时间 · 降' case 'updated_at asc': return '时间 · 升' case 'size desc': return '大小 · 降' case 'size asc': return '大小 · 升' } return '选择文件排序' } }, actions: { mSaveDirFileLoading(drive_id: string, dirID: string, dirName: string) { const order = TreeStore.GetDirOrder(drive_id, dirID) if (this.DirID != dirID || this.DriveID != drive_id) { this.$patch({ DriveID: drive_id, DirID: dirID, DirName: dirName, ListOrderKey: order, ListLoading: true, ListLoadingIndex: 0, ListSearchKey: '', ListDataRaw: [], ListDataShow: [], ListDataGrid: [], ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '' }) } else { this.$patch({ DriveID: drive_id, DirID: dirID, DirName: dirName, ListOrderKey: order, ListLoading: true, ListLoadingIndex: 0, ListSearchKey: '', ListDataRaw: [], ListDataShow: [], ListDataGrid: [] }) } useFootStore().mSaveDirInfo('pan', '文件列表加载中...') }, mSaveDirFileLoadingPart(pageIndex: number, partDir: IAliFileResp, itemsTotal: number = 0) { if (pageIndex != this.ListLoadingIndex || partDir.m_drive_id != this.DriveID || partDir.dirID != this.DirID) { partDir.next_marker = 'cancel' } else { this.ListLoadingIndex++ this.ListDataRaw = this.ListDataRaw.concat(partDir.items) this.mRefreshListDataShow(true) if (itemsTotal > 0) useFootStore().mSaveDirInfo('pan', '文件列表加载中... 总:' + itemsTotal) } }, mSaveDirFileLoadingFinish(drive_id: string, dirID: string, list: Item[], itemsTotal: number = 0) { if (this.DirID && (drive_id != this.DriveID || dirID != this.DirID)) return if (list.length == 0) { this.ListDataRaw = [] this.mRefreshListDataShow(true) } this.$patch({ ListLoading: false, ListLoadingIndex: 0 }) this.mRefreshListDataShow(true) let panInfo = '' if (itemsTotal == -1) panInfo = '' else if (list.length == 0 && itemsTotal == 0) panInfo = '空文件夹' else { let dirCount = 0 let fileCount = 0 list.map((t) => { if (t.isDir) dirCount++ else fileCount++ return true }) panInfo = '文件夹:' + dirCount + ' 文件:' + fileCount + ' 总:' + itemsTotal } useFootStore().mSaveDirInfo('pan', panInfo) }, mSearchListData(value: string) { this.$patch({ ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '', ListSearchKey: value }) this.mRefreshListDataShow(true) }, mOrderListData(value: string) { if (!value || value == this.ListOrderKey) return TreeStore.SaveDirOrder(this.DriveID, this.DirID, value) this.$patch({ ListOrderKey: value, ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '' }) PanDAL.aReLoadOneDirToShow('', 'refresh', false) }, mGridListData(value: string, column: number) { if (this.ListShowMode == value && this.ListShowColumn == column) return this.$patch({ ListShowMode: value == 'list' ? 'list' : 'grid', ListShowColumn: value == 'list' ? 1 : column }) this.mRefreshListDataShow(true) }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) const listDataGrid = this.ListDataGrid.concat() Object.freeze(listDataGrid) this.$patch({ ListDataShow: listDataShow, ListDataGrid: listDataGrid }) return } let showList: Item[] = [] if (this.ListSearchKey) { const results = fuzzysort.go(this.ListSearchKey, this.ListDataRaw, { threshold: -200000, keys: ['name', 'namesearch'], scoreFn: (a) => Math.max(a[0] ? a[0].score : -200000, a[1] ? a[1].score : -200000) }) for (let i = 0, maxi = results.length; i < maxi; i++) { if (results[i].score > -200000) showList.push(results[i].obj) } } else { showList = this.ListDataRaw.concat() } Object.freeze(showList) const gridList: GridItem[] = [] const column = this.ListShowColumn for (let i = 0, maxi = showList.length; i < maxi; i += column) { const grid: GridItem = { file_id: showList[i].file_id, files: [showList[i]] } for (let j = 1; j < column && i + j < maxi; j++) { grid.files.push(showList[i + j]) } gridList.push(grid) } Object.freeze(gridList) const oldSelected = this.ListSelected const newSelected = new Set() let key = '' for (let i = 0, maxi = showList.length; i < maxi; i++) { key = showList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.$patch({ ListDataShow: showList, ListDataGrid: gridList, ListSelected: newSelected }) }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: '', ListSelectKey: '' }) this.mRefreshListDataShow(false) }, mMouseSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mRangSelect(lastkey: string, file_idList: string[]) { if (this.ListDataShow.length == 0) return const selectedNew = new Set(this.ListSelected) for (let i = 0, maxi = file_idList.length; i < maxi; i++) { selectedNew.add(file_idList[i]) } this.$patch({ ListSelected: selectedNew, ListFocusKey: lastkey, ListSelectKey: lastkey }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedID() { return GetSelectedListID(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedParentDirID() { return GetSelectedListID(this.ListDataShow, 'parent_file_id', this.ListSelected) }, GetSelectedFirst(): Item | undefined { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: string) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus(): string { if (!this.ListFocusKey && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string): string { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, '') }, mDeleteFiles(dirID: string, file_idList: string[], needDelDir: boolean) { if (this.DirID == dirID || dirID == 'any') { const fileMap = new Set(file_idList) const listDataRaw = this.ListDataRaw const newDataList: Item[] = [] const diridList: string[] = [] let deleteCount = 0 for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (fileMap.has(item.file_id)) { deleteCount++ if (item.isDir) diridList.push(item.file_id) } else { newDataList.push(item) } } if (deleteCount > 0) { this.ListDataRaw = newDataList this.mRefreshListDataShow(true) } } if (needDelDir) { TreeStore.DeleteDirs(this.DriveID, file_idList) PanDAL.RefreshPanTreeAllNode(this.DriveID) } }, mFavorFiles(isfavor: boolean, file_idList: string[]) { const listDataRaw = this.ListDataRaw let isChange = false const fileMap = new Set(file_idList) for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (fileMap.has(item.file_id)) { item.starred = isfavor isChange = true } } if (isChange) this.mRefreshListDataShow(false) }, mColorFiles(color: string, file_idList: string[]) { const listDataRaw = this.ListDataRaw let isChange = false const fileMap = new Set(file_idList) for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (fileMap.has(item.file_id)) { item.description = color isChange = true } } if (isChange) this.mRefreshListDataShow(false) }, mRenameFiles(fileList: { file_id: string; parent_file_id: string; name: string; isDir: boolean }[]) { const listDataRaw = this.ListDataRaw let isChange = false const fileMap = ArrayToMap('file_id', fileList) for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] const newFile = fileMap.get(item.file_id) if (newFile) { item.name = newFile.name isChange = true } } if (isChange) this.mRefreshListDataShow(false) }, mSaveFileScrollTo(file_id: string) { this.scrollToFile = file_id } } }) export default usePanFileStore ================================================ FILE: src/renderer/pan/pantreestore.ts ================================================ import { defineStore } from 'pinia' import { IAliGetDirModel } from '../aliapi/alimodels' import { h } from 'vue' import PanDAL from './pandal' import TreeStore, { TreeNodeData } from '../store/treestore' export interface PanTreeState { user_id: string drive_id: string History: IAliGetDirModel[] selectDir: IAliGetDirModel selectDirPath: IAliGetDirModel[] treeData: TreeNodeData[] treeExpandedKeys: string[] treeSelectedKeys: string[] quickData: TreeNodeData[] scrollToDir: string } let treeDataMap = new Map() type State = PanTreeState export const fileiconfn = (icon: string) => h('i', { class: 'iconfont ' + icon }) const usePanTreeStore = defineStore('pantree', { state: (): State => ({ user_id: '', drive_id: '', History: [], selectDir: { __v_skip: true, drive_id: '', file_id: '', parent_file_id: '', name: '', namesearch: '', size: 0, time: 0, description: '' }, selectDirPath: [], treeData: [ { __v_skip: true, title: '文件恢复', namesearch: '', key: 'recover', icon: () => fileiconfn('iconrecover'), isLeaf: true, children: [] }, { __v_skip: true, title: '回收站', namesearch: '', key: 'trash', icon: () => fileiconfn('icondelete'), isLeaf: true, children: [] }, { __v_skip: true, title: '收藏夹', namesearch: '', key: 'favorite', icon: () => fileiconfn('iconcrown'), isLeaf: true, children: [] }, { __v_skip: true, title: '全盘搜索', namesearch: '', key: 'search', icon: () => fileiconfn('iconsearch'), isLeaf: true, children: [] }, { __v_skip: true, title: '根目录', namesearch: '', key: 'root', children: [] } ], treeExpandedKeys: ['root'], treeSelectedKeys: [], quickData: [], scrollToDir: '' }), getters: {}, actions: { mTreeSelected(key: string) { console.log('mTreeSelected', key) PanDAL.aReLoadOneDirToShow('', key, true) }, mTreeExpand(key: string) { console.log('mTreeExpand', key) const arr = this.treeExpandedKeys if (arr.includes(key)) { const dirPath = TreeStore.GetDirPath(this.drive_id, this.selectDir.file_id) const needSelectNew = dirPath.filter((t) => t.parent_file_id == key).length > 0 this.treeExpandedKeys = arr.filter((t) => t != key) if (needSelectNew) PanDAL.aReLoadOneDirToShow('', key, false) } else { this.treeExpandedKeys = arr.concat([key]) PanDAL.RefreshPanTreeAllNode(this.drive_id) } }, mTreeExpandAll(keyList: string[], isExpaned: boolean) { const arr = new Set(this.treeExpandedKeys) if (isExpaned) { for (let i = 0, maxi = keyList.length; i < maxi; i++) { arr.add(keyList[i]) } } else { for (let i = 0, maxi = keyList.length; i < maxi; i++) { arr.delete(keyList[i]) } } this.treeExpandedKeys = Array.from(arr) if (isExpaned) PanDAL.RefreshPanTreeAllNode(this.drive_id) }, mSaveUser(user_id: string, drive_id: string) { this.$reset() this.$patch({ user_id, drive_id }) }, mShowDir(dir: IAliGetDirModel, dirPath: IAliGetDirModel[], treeSelectedKeys: string[], treeExpandedKeys: string[]) { this.$patch({ selectDir: dir, selectDirPath: dirPath, treeSelectedKeys: treeSelectedKeys, treeExpandedKeys: treeExpandedKeys }) }, mSaveTreeAllNode(drive_id: string, root: TreeNodeData, rootMap: Map) { if (this.drive_id !== drive_id) return const list: TreeNodeData[] = [] for (let i = 0, maxi = this.treeData.length; i < maxi; i++) { if (this.treeData[i].key == root.key) { list.push(root) } else list.push(this.treeData[i]) } this.treeData = list treeDataMap = rootMap }, mSaveTreeOneDirNode(drive_id: string, dirID: string, dirNode: TreeNodeData, dirMap: Map) { console.log('刷新Tree', dirNode) if (this.drive_id !== drive_id) return const findDir = treeDataMap.get(dirID) if (findDir) { findDir.children = dirNode.children const keys = dirMap.entries() for (let i = 0, maxi = dirMap.size; i < maxi; i++) { const key = keys.next().value treeDataMap.set(key[0], key[1]) } this.treeData = this.treeData.concat() } }, mRenameFiles(fileList: { file_id: string; parent_file_id: string; name: string; isDir: boolean }[]) { let isChange = false let isPath = false const diridList: string[] = [] for (let i = 0, maxi = fileList.length; i < maxi; i++) { const item = fileList[i] if (!item.isDir) continue diridList.push(item.file_id) const findNode = treeDataMap.get(item.file_id) if (findNode) { findNode.title = item.name isChange = true } if (this.selectDir.file_id == item.file_id) { this.selectDir = Object.assign({}, this.selectDir, { name: item.name }) as IAliGetDirModel isChange = true } this.selectDirPath.map((t) => { if (t.file_id == item.file_id) { t.name = item.name isPath = true } return true }) } if (isChange) this.treeData = this.treeData.concat() if (isPath) this.selectDirPath = this.selectDirPath.concat() TreeStore.RenameDirs(this.drive_id, fileList) }, mSaveQuick(list: { key: string; title: string }[]) { const nodeList: TreeNodeData[] = [] for (let i = 0; i < list.length; i++) { nodeList.push({ __v_skip: true, key: list[i].key, title: list[i].title || list[i].key, namesearch: i < 9 ? '快捷键 Ctrl+' + (i + 1) : '', children: [], isLeaf: true } as TreeNodeData) } Object.freeze(nodeList) this.quickData = nodeList }, mSaveTreeScrollTo(dirID: string) { if (dirID == 'refresh') dirID = this.selectDir.file_id this.scrollToDir = dirID } } }) export default usePanTreeStore ================================================ FILE: src/renderer/pan/topbtns/AlphaModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/ArchiveModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/ArchivePasswordModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/CopyFileTreeModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/CreatNewDirModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/CreatNewDirMultiModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/CreatNewFileModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/CreatNewShareLinkModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/DLNAPlayerModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/DaoRuShareLinkModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/DaoRuShareLinkMultiModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/DownloadModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/M3U8DownloadModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/RenameModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/RenameMultiModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/SearchPanModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/SelectPanDirModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/ShuXingModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/ShuXingMultiModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/UploadModal.vue ================================================ ================================================ FILE: src/renderer/pan/topbtns/renamemulti.ts ================================================ export interface TreeNodeData { key: string title: string rawtitle: string newtitle: string isLeaf: boolean children: TreeNodeData[] icon: any isDir: boolean isMatch: boolean } export function NewRenameConfigData() { return { show: false, replace: { enable: true, search: '', newword: '', chkCase: true, chkAll: true, chkReg: false, applyto: 'name' }, delete: { enable: false, type: 'search', search: '', chkCase: true, chkAll: true, chkReg: false, applyto: 'name', beginlen: 0, endlen: 0, beginword: '', endword: '' }, add: { enable: false, type: 'position', search: '', before: '', after: '', beginword: '', endword: '', applyto: 'name' }, index: { enable: false, type: 'begin', format: '', minlen: 1, beginindex: 1, minnum: 1 }, others: { enable: false, nameformat: '', extformat: '', randomformat: '', randomlen: 4 } } } export function RunAllNode(nodeList: TreeNodeData[], func: (node: TreeNodeData) => boolean) { for (let i = 0, maxi = nodeList.length; i < maxi; i++) { const node = nodeList[i] if (!func(node)) return false if (node.children && node.children.length > 0) { if (!RunAllNode(node.children, func)) return false } } return true } function Split(text: string, search: string) { const textLow = text.toLowerCase() search = search.toLowerCase() const listLow = textLow.split(search) const searchLen = search.length let pos = 0 const list: string[] = [] for (let i = 0, maxi = listLow.length; i < maxi; i++) { const low = listLow[i] if (low) { list.push(text.substring(pos, pos + low.length)) pos = pos + searchLen + low.length } else { list.push('') pos = pos + searchLen } } return list } function Replace(text: string, search: string, newtext: string) { const textLow = text.toLowerCase() search = search.toLowerCase() const index = textLow.indexOf(search) if (index >= 0) { return text.substring(0, index) + newtext + text.substring(index + search.length) } else return text } function fixext(ext: string) { return ext ? '.' + ext : '' } function RunReplace(isDir: boolean, title: string, config: any) { const search = config.search as string if (!search) return [title, title] let name = title let ext = '' const exti = name.lastIndexOf('.') if (!isDir && exti >= 0) { ext = name.substring(exti + 1) name = name.substring(0, exti) } if (config.chkReg) { let reg: RegExp try { reg = RegExp(search) } catch { return [title, title] } reg = RegExp(search) if (config.chkCase) reg = RegExp(search, 'i') if (config.chkAll) reg = RegExp(search, 'g') if (config.chkCase && config.chkAll) reg = RegExp(search, 'ig') if (config.applyto == 'full') { return [title.replace(reg, config.newword), title.replace(reg, '' + config.newword + '')] } if (config.applyto == 'name') { return [name.replace(reg, config.newword) + fixext(ext), name.replace(reg, '' + config.newword + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(ext.replace(reg, config.newword)), name + fixext(ext.replace(reg, '' + config.newword + ''))] } } else if (config.chkCase) { if (config.chkAll) { if (config.applyto == 'full') { const slist = Split(title, search) return [slist.join(config.newword), slist.join('' + config.newword + '')] } if (config.applyto == 'name') { const slist = Split(name, search) return [slist.join(config.newword) + fixext(ext), slist.join('' + config.newword + '') + fixext(ext)] } if (config.applyto == 'ext') { const slist = Split(ext, search) return [name + fixext(slist.join(config.newword)), name + fixext(slist.join('' + config.newword + ''))] } } else { if (config.applyto == 'full') { return [Replace(title, search, config.newword), Replace(title, search, '' + config.newword + '')] } if (config.applyto == 'name') { return [Replace(name, search, config.newword) + fixext(ext), Replace(name, search, '' + config.newword + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(Replace(ext, search, config.newword)), name + fixext(Replace(ext, search, '' + config.newword + ''))] } } } else { if (config.chkAll) { if (config.applyto == 'full') { return [title.replaceAll(search, config.newword), title.replaceAll(search, '' + config.newword + '')] } if (config.applyto == 'name') { return [name.replaceAll(search, config.newword) + fixext(ext), name.replaceAll(search, '' + config.newword + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(ext.replaceAll(search, config.newword)), name + fixext(ext.replaceAll(search, '' + config.newword + ''))] } } else { if (config.applyto == 'full') { return [title.replace(search, config.newword), title.replace(search, '' + config.newword + '')] } if (config.applyto == 'name') { return [name.replace(search, config.newword) + fixext(ext), name.replace(search, '' + config.newword + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(ext.replace(search, config.newword)), name + fixext(ext.replace(search, '' + config.newword + ''))] } } } return [title, title] } function RunDelete(isDir: boolean, title: string, config: any) { let name = title let ext = '' const exti = name.lastIndexOf('.') if (!isDir && exti >= 0) { ext = name.substring(exti + 1) name = name.substring(0, exti) } if (config.type == 'search' && config.search) { const search = config.search as string if (config.chkReg) { let reg: RegExp try { reg = RegExp(search) } catch { return [title, title] } reg = RegExp(search) if (config.chkCase) reg = RegExp(search, 'i') if (config.chkAll) reg = RegExp(search, 'g') if (config.chkCase && config.chkAll) reg = RegExp(search, 'ig') if (config.applyto == 'full') { return [title.replace(reg, ''), title.replace(reg, (L) => (L ? '' + L + '' : ''))] } if (config.applyto == 'name') { return [name.replace(reg, '') + fixext(ext), name.replace(reg, (L) => (L ? '' + L + '' : '')) + fixext(ext)] } if (config.applyto === 'ext') { return [name + fixext(ext.replace(reg, '')), name + fixext(ext.replace(reg, (L) => (L ? '' + L + '' : '')))] } } else if (config.chkCase) { if (config.chkAll) { if (config.applyto == 'full') { const slist = Split(title, search) return [slist.join(''), slist.join('' + search + '')] } if (config.applyto == 'name') { const slist = Split(name, search) return [slist.join('') + fixext(ext), slist.join('' + search + '') + fixext(ext)] } if (config.applyto == 'ext') { const slist = Split(ext, search) return [name + fixext(slist.join('')), name + fixext(slist.join('' + search + ''))] } } else { if (config.applyto == 'full') { return [Replace(title, search, ''), Replace(title, search, '' + search + '')] } if (config.applyto == 'name') { return [Replace(name, search, '') + fixext(ext), Replace(name, search, '' + search + '') + fixext(ext)] } if (config.applyto === 'ext') { return [name + fixext(Replace(ext, search, '')), name + fixext(Replace(ext, search, '' + search + ''))] } } } else { if (config.chkAll) { if (config.applyto == 'full') { return [title.replaceAll(search, ''), title.replaceAll(search, '' + search + '')] } if (config.applyto == 'name') { return [name.replaceAll(search, '') + fixext(ext), name.replaceAll(search, '' + search + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(ext.replaceAll(search, '')), name + fixext(ext.replaceAll(search, '' + search + ''))] } } else { if (config.applyto == 'full') { return [title.replace(search, ''), title.replace(search, '' + search + '')] } if (config.applyto == 'name') { return [name.replace(search, '') + fixext(ext), name.replace(search, '' + search + '') + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(ext.replace(search, '')), name + fixext(ext.replace(search, '' + search + ''))] } } } } if (config.type == 'position' && config.beginlen >= 0 && config.endlen >= 0) { let title1 = title let title2 = title if (config.applyto == 'full') { title1 = title title2 = title } else if (config.applyto == 'name') { title1 = name title2 = name } else if (config.applyto == 'ext') { title1 = ext title2 = ext } if (config.applyto == 'ext' && (config.beginlen > title1.length || config.endlen > title1.length || config.beginlen + config.endlen > title1.length)) return [title, title] if (config.applyto !== 'ext' && (config.beginlen >= title1.length || config.endlen >= title1.length || config.beginlen + config.endlen >= title1.length)) return [title, title] if (config.beginlen > 0 && config.endlen > 0) { const del1 = title1.substring(0, config.beginlen) const del2 = title1.substring(title1.length - config.endlen) let str = title1.substring(config.beginlen) str = str.substring(0, str.length - config.endlen) title1 = str title2 = '' + del1 + '' + str + '' + del2 + '' } else if (config.beginlen > 0) { const del = title1.substring(0, config.beginlen) const str = title1.substring(config.beginlen) title1 = str title2 = '' + del + '' + str } else if (config.endlen > 0) { const str1 = title1.substring(0, title1.length - config.endlen) const str2 = title1.substring(0, title1.length - config.endlen) const del = title1.substring(title1.length - config.endlen) title1 = str1 title2 = str2 + '' + del + '' } else { return [title, title] } if (config.applyto == 'full') { return [title1, title2] } if (config.applyto == 'name') { return [title1 + fixext(ext), title2 + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(title1), name + fixext(title2)] } } if (config.type == 'range' && config.beginword && config.endword) { if (config.applyto == 'full') { const start = title.indexOf(config.beginword) const end = title.indexOf(config.endword, start + 1) if (start >= 0 && end >= 0 && start < end - 1) { const title1 = title.substring(0, start + 1) + title.substring(end) const title2 = title.substring(0, start + 1) + '' + title.substring(start + 1, end) + '' + title.substring(end) return [title1, title2] } } else if (config.applyto == 'name') { const start = name.indexOf(config.beginword) const end = name.indexOf(config.endword, start + 1) if (start >= 0 && end >= 0 && start < end - 1) { const name1 = name.substring(0, start + 1) + name.substring(end) const name2 = name.substring(0, start + 1) + '' + name.substring(start + 1, end) + '' + name.substring(end) return [name1 + fixext(ext), name2 + fixext(ext)] } } else if (config.applyto == 'ext') { const start = ext.indexOf(config.beginword) const end = ext.indexOf(config.endword, start + 1) if (start >= 0 && end >= 0 && start < end - 1) { const ext1 = ext.substring(0, start + 1) + ext.substring(end) const ext2 = ext.substring(0, start + 1) + '' + ext.substring(start + 1, end) + '' + ext.substring(end) return [name + fixext(ext1), name + fixext(ext2)] } } } return [title, title] } function RunAdd(isDir: boolean, title: string, config: any) { let name = title let ext = '' const exti = name.lastIndexOf('.') if (!isDir && exti >= 0) { ext = name.substring(exti + 1) name = name.substring(0, exti) } let title1 = title if (config.applyto == 'full') { title1 = title } else if (config.applyto == 'name') { title1 = name } else if (config.applyto == 'ext') { title1 = ext } if (config.type == 'search' && config.search) { const index = title1.indexOf(config.search) if (index >= 0) { let title2 = '' const start = title1.substring(0, index) const mid = title1.substring(index, index + config.search.length) const end = title1.substring(index + config.search.length) if (config.before && config.after) { title1 = start + config.before + mid + config.after + end title2 = start + '' + config.before + '' + mid + '' + config.after + '' + end } else if (config.before) { title1 = start + config.before + mid + end title2 = start + '' + config.before + '' + mid + end } else if (config.after) { title1 = start + mid + config.after + end title2 = start + mid + '' + config.after + '' + end } else { return [title, title] } if (config.applyto == 'full') { return [title1, title2] } if (config.applyto == 'name') { return [title1 + fixext(ext), title2 + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(title1), name + fixext(title2)] } } } if (config.type == 'position' && (config.beginword || config.endword)) { if (title1) { let title2 = title1 if (config.beginword) { title1 = config.beginword + title1 title2 = '' + config.beginword + '' + title2 } if (config.endword) { title1 = title1 + config.endword title2 = title2 + '' + config.endword + '' } if (config.applyto == 'full') { return [title1, title2] } if (config.applyto == 'name') { return [title1 + fixext(ext), title2 + fixext(ext)] } if (config.applyto == 'ext') { return [name + fixext(title1), name + fixext(title2)] } } } return [title, title] } function RunIndex(isDir: boolean, title: string, config: any, nodeIndex: number) { if (!config.format) return [title, title] let name = title let ext = '' const exti = name.lastIndexOf('.') if (!isDir && exti >= 0) { ext = name.substring(exti) name = name.substring(0, exti) } const bianhao = config.beginindex + config.minnum * nodeIndex const formate = config.format.replace('#', bianhao.toString().padStart(config.minlen, '0')) if (config.type == 'begin') { const title1 = formate + name const title2 = '' + formate + '' + name return [title1 + ext, title2 + ext] } else if (config.type == 'end') { const title1 = name + formate const title2 = name + '' + formate + '' return [title1 + ext, title2 + ext] } return [title, title] } function RunOthers(isDir: boolean, title: string, config: any, sj1Base: string) { let name = title let ext = '' const exti = name.lastIndexOf('.') if (!isDir && exti >= 0) { ext = name.substring(exti) name = name.substring(0, exti) } if (config.nameformat == 'AA') { const title1 = name.replace(/[a-zA-Z]+/g, (L) => L.toUpperCase()) const title2 = name.replace(/[a-zA-Z]+/g, (L) => (L == L.toUpperCase() ? L : '' + L.toUpperCase() + '')) if (title1 + ext == title) return [title, title] return [title1 + ext, title2 + ext] } if (config.nameformat == 'aa') { const title1 = name.replace(/[a-zA-Z]+/g, (L) => L.toLowerCase()) const title2 = name.replace(/[a-zA-Z]+/g, (L) => (L == L.toLowerCase() ? L : '' + L.toLowerCase() + '')) if (title1 + ext == title) return [title, title] return [title1 + ext, title2 + ext] } if (config.nameformat == 'Aa') { name = name.toLowerCase() const title1 = name.replace(/[a-z]+/, (L) => (L.length > 1 ? L.substring(0, 1).toUpperCase() + L.substring(1) : L.toUpperCase())) const title2 = name.replace(/[a-z]+/, (L) => (L.length > 1 ? '' + L.substring(0, 1).toUpperCase() + '' + L.substring(1) : '' + L.toUpperCase() + '')) if (title1 + ext == title) return [title, title] return [title1 + ext, title2 + ext] } if (config.nameformat == 'Aa Aa') { name = name.toLowerCase() const title1 = name.replace(/[a-z]+/g, (L) => (L.length > 1 ? L.substring(0, 1).toUpperCase() + L.substring(1) : L.toUpperCase())) const title2 = name.replace(/[a-z]+/g, (L) => (L.length > 1 ? '' + L.substring(0, 1).toUpperCase() + '' + L.substring(1) : '' + L.toUpperCase() + '')) if (title1 + ext == title) return [title, title] return [title1 + ext, title2 + ext] } if (config.extformat == 'AA') { if (ext && ext != ext.toUpperCase()) { return [name + ext.toUpperCase(), name + '' + ext.toUpperCase() + ''] } else { return [title, title] } } if (config.extformat == 'aa') { if (ext && ext != ext.toLowerCase()) { return [name + ext.toLowerCase(), name + '' + ext.toLowerCase() + ''] } else { return [title, title] } } const randomLen = config.randomlen if (sj1Base && randomLen > 0) { let ranname = '' let ran = Math.random().toString() ran = ran + ran + ran + ran + ran let pos = name.length for (let i = 0; i < randomLen; i++) { pos = (pos ^ ran.charCodeAt(i)) % 300 ranname += sj1Base[pos] } return [ranname + ext, '' + ranname + '' + ext] } return [title, title] } export function RunReplaceName(renameConfig: any, treeData: TreeNodeData[], checkedKeys: string[]) { const show = renameConfig.show const replace = renameConfig.replace const checked = new Set(checkedKeys || []) if (replace.enable) { RunAllNode(treeData, (node) => { if (checked.has(node.key)) { const title = RunReplace(node.isDir, node.rawtitle, replace) node.newtitle = title[0] node.title = show ? title[0] : title[1] node.isMatch = node.newtitle != node.rawtitle } else { node.newtitle = node.rawtitle node.title = node.rawtitle node.isMatch = false } return true }) return } const tdelete = renameConfig.delete if (tdelete.enable) { RunAllNode(treeData, (node) => { if (checked.has(node.key)) { const title = RunDelete(node.isDir, node.rawtitle, tdelete) node.newtitle = title[0] node.title = show ? title[0] : title[1] node.isMatch = node.newtitle != node.rawtitle && node.newtitle != '' } else { node.newtitle = node.rawtitle node.title = node.rawtitle node.isMatch = false } return true }) return } const add = renameConfig.add if (add.enable) { RunAllNode(treeData, (node) => { if (checked.has(node.key)) { const title = RunAdd(node.isDir, node.rawtitle, add) node.newtitle = title[0] node.title = show ? title[0] : title[1] node.isMatch = node.newtitle != node.rawtitle } else { node.newtitle = node.rawtitle node.title = node.rawtitle node.isMatch = false } return true }) return } const index = renameConfig.index if (index.enable) { let nodeindex = 0 // const checkmap = new Set(checkedKeys || []) RunAllNode(treeData, (node) => { if (checked.has(node.key)) { const title = RunIndex(node.isDir, node.rawtitle, index, nodeindex) node.newtitle = title[0] node.title = show ? title[0] : title[1] node.isMatch = node.newtitle != node.rawtitle nodeindex++ } else { node.newtitle = node.rawtitle node.title = node.rawtitle node.isMatch = false } return true }) return } const others = renameConfig.others if (others.enable) { let sj1Base = '' if (others.randomformat == '0-9') sj1Base = '01234567899876543210012345678998765432100123456789987654321001' if (others.randomformat == 'a-z') sj1Base = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij' if (others.randomformat == 'A-Z') sj1Base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ' if (others.randomformat == 'a-zA-Z') sj1Base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZtuvwxABCDE' if (others.randomformat == '0-9a-z') sj1Base = '0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnop' if (others.randomformat == '0-9A-Z') sj1Base = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOP' if (others.randomformat == '0-9a-zA-Z') sj1Base = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' if (sj1Base) sj1Base = sj1Base + sj1Base + sj1Base + sj1Base + sj1Base RunAllNode(treeData, (node) => { if (checked.has(node.key)) { const title = RunOthers(node.isDir, node.rawtitle, others, sj1Base) node.newtitle = title[0] node.title = show ? title[0] : title[1] node.isMatch = node.newtitle != node.rawtitle } else { node.newtitle = node.rawtitle node.title = node.rawtitle node.isMatch = false } return true }) } } ================================================ FILE: src/renderer/pan/topbtns/topbtn.ts ================================================ import { IAliGetFileModel } from '../../aliapi/alimodels' import AliFile from '../../aliapi/file' import AliFileCmd from '../../aliapi/filecmd' import { IAliFileResp, NewIAliFileResp } from '../../aliapi/dirfilelist' import AliTrash from '../../aliapi/trash' import { IPageVideoXBT } from '../../store/appstore' import DebugLog from '../../utils/debuglog' import message from '../../utils/message' import { modalCopyFileTree, modalCreatNewShareLink, modalDLNAPlayer, modalDownload, modalM3U8Download, modalSearchPan, modalSelectPanDir, modalUpload } from '../../utils/modal' import { ArrayKeyList } from '../../utils/utils' import PanDAL from '../pandal' import usePanFileStore from '../panfilestore' import usePanTreeStore from '../pantreestore' import { useSettingStore } from '../../store' import { Sleep } from '../../utils/format' import TreeStore from '../../store/treestore' import { copyToClipboard } from '../../utils/electronhelper' const topbtnLock = new Set() export function handleUpload(uploadType: string) { const pantreeStore = usePanTreeStore() if (!pantreeStore.user_id || !pantreeStore.drive_id || !pantreeStore.selectDir.file_id) { message.error('上传操作失败 父文件夹错误') return } if (uploadType == 'file') { window.WebShowOpenDialogSync({ title: '选择多个文件上传到网盘', buttonLabel: '上传选中的文件', properties: ['openFile', 'multiSelections', 'showHiddenFiles', 'noResolveAliases', 'treatPackageAsDirectory', 'dontAddToRecent'] }, (files: string[] | undefined) => { if (files && files.length > 0) { modalUpload(pantreeStore.selectDir.file_id, files) } }) } else { window.WebShowOpenDialogSync({ title: '选择多个文件夹上传到网盘', buttonLabel: '上传文件夹', properties: ['openDirectory', 'multiSelections', 'showHiddenFiles', 'noResolveAliases', 'treatPackageAsDirectory', 'dontAddToRecent'] }, (files: string[] | undefined) => { if (files && files.length > 0) { modalUpload(pantreeStore.selectDir.file_id, files) } }) } } export function menuDownload(istree: boolean) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('下载操作失败 父文件夹错误') return } if (selectedData.isErrorSelected) { message.error('没有可以下载的文件') return } if (topbtnLock.has('menuDownload')) return topbtnLock.add('menuDownload') try { const settingStore = useSettingStore() if (settingStore.downSavePathDefault) { // todo:: 直接下载 } else modalDownload(false) } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('menuDownload', err) } topbtnLock.delete('menuDownload') } export async function menuFavSelectFile(istree: boolean, isFavor: boolean) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('收藏操作失败 父文件夹错误') return } if (selectedData.isErrorSelected) { message.error('没有可以收藏的文件') return } if (topbtnLock.has('menuFavSelectFile')) return topbtnLock.add('menuFavSelectFile') try { const successList = await AliFileCmd.ApiFavorBatch(selectedData.user_id, selectedData.drive_id, isFavor, true, selectedData.selectedKeys) if (isFavor) { if (usePanTreeStore().selectDir.file_id == 'favorite') { PanDAL.aReLoadOneDirToShow('', 'refresh', false) } else { usePanFileStore().mFavorFiles(isFavor, successList) } } else { if (usePanTreeStore().selectDir.file_id == 'favorite') { usePanFileStore().mDeleteFiles('favorite', successList, false) } else { usePanFileStore().mFavorFiles(isFavor, successList) } } } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('menuFavSelectFile', err) } topbtnLock.delete('menuFavSelectFile') } export async function menuTrashSelectFile(istree: boolean, isDelete: boolean) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('删除操作失败 父文件夹错误') return } if (selectedData.isErrorSelected) { message.error('没有可以删除的文件') return } if (selectedData.dirID.startsWith('video')) { message.error('请不要在放映室里删除文件') return } if (topbtnLock.has('menuTrashSelectFile')) return topbtnLock.add('menuTrashSelectFile') try { let successList: string[] if (isDelete) { successList = await AliFileCmd.ApiDeleteBatch(selectedData.user_id, selectedData.drive_id, selectedData.selectedKeys) } else { successList = await AliFileCmd.ApiTrashBatch(selectedData.user_id, selectedData.drive_id, selectedData.selectedKeys) } if (istree) { PanDAL.aReLoadOneDirToShow(selectedData.drive_id, selectedData.parentDirID, false) } else { usePanFileStore().mDeleteFiles(selectedData.dirID, successList, selectedData.dirID !== 'trash') if (selectedData.dirID !== 'trash') { // PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, selectedData.dirID) TreeStore.ClearDirSize(selectedData.drive_id, selectedData.selectedParentKeys) } } } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('menuTrashSelectFile', err) } topbtnLock.delete('menuTrashSelectFile') } export async function topRestoreSelectedFile() { const selectedData = PanDAL.GetPanSelectedData(false) if (selectedData.isError) { message.error('还原文件操作失败 父文件夹错误') return } if (selectedData.isErrorSelected) { message.error('没有可以还原的文件') return } const panfileStore = usePanFileStore() const diridList: string[] = [] panfileStore .GetSelected() .filter((t) => t.isDir) .map((t) => diridList.push(t.file_id)) if (topbtnLock.has('topRestoreSelectedFile')) return topbtnLock.add('topRestoreSelectedFile') try { await AliFileCmd.ApiTrashRestoreBatch(selectedData.user_id, selectedData.drive_id, true, selectedData.selectedKeys) if (usePanTreeStore().selectDir.file_id == 'trash') { usePanFileStore().mDeleteFiles('trash', selectedData.selectedKeys, false) } else { PanDAL.aReLoadOneDirToShow('', 'refresh', false) } await Sleep(2000) const dirList = await AliFileCmd.ApiGetFileBatch(selectedData.user_id, selectedData.drive_id, diridList) console.log(diridList, dirList) const pset = new Set() for (let i = 0, maxi = dirList.length; i < maxi; i++) { const parent_file_id = dirList[i].parent_file_id if (pset.has(parent_file_id)) continue pset.add(parent_file_id) await PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, parent_file_id) } TreeStore.ClearDirSize(selectedData.drive_id, Array.from(pset)) } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('topRestoreSelectedFile', err) } topbtnLock.delete('topRestoreSelectedFile') } export function menuCopySelectedFile(istree: boolean, copyby: string) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('复制移动操作失败 父文件夹错误') return } if (selectedData.dirID.startsWith('video')) { message.error('请不要在放映室里移动文件文件') return } let files: IAliGetFileModel[] = [] if (istree) { files = [{ ...usePanTreeStore().selectDir, isDir: true, ext: '', category: '', icon: '', sizeStr: '', timeStr: '', starred: false, thumbnail: '' } as IAliGetFileModel] } else { files = usePanFileStore().GetSelected() } if (files.length == 0) { message.error('没有选择要复制移动的文件!') return } const parent_file_id = files[0].parent_file_id const file_idList: string[] = [] const diridList: string[] = [] for (let i = 0, maxi = files.length; i < maxi; i++) { if (files[i].isDir && diridList.includes(files[i].parent_file_id) == false) diridList.push(files[i].parent_file_id) file_idList.push(files[i].file_id) } if (file_idList.length == 0) { message.error('没有可以复制移动的文件') return } modalSelectPanDir(copyby, '', async function (user_id: string, drive_id: string, dirID: string) { if (!drive_id || !dirID) return if (parent_file_id == dirID) { message.error('不能移动复制到原位置!') return } let successList: string[] if (copyby == 'copy') { successList = await AliFileCmd.ApiCopyBatch(user_id, drive_id, file_idList, drive_id, dirID) PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, dirID) TreeStore.ClearDirSize(drive_id, [dirID]) } else { successList = await AliFileCmd.ApiMoveBatch(user_id, drive_id, file_idList, drive_id, dirID) if (istree) { PanDAL.aReLoadOneDirToShow(selectedData.drive_id, selectedData.parentDirID, false) PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, dirID) } else { usePanFileStore().mDeleteFiles(selectedData.dirID, successList, true) PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, dirID) } TreeStore.ClearDirSize(drive_id, [dirID, ...selectedData.selectedParentKeys]) } }) } export function dropMoveSelectedFile(movetodirid: string) { const selectedData = PanDAL.GetPanSelectedData(false) if (selectedData.isErrorSelected) return if (selectedData.isError) { message.error('复制移动操作失败 父文件夹错误!') return } if (selectedData.dirID == 'trash') { message.error('回收站内文件不支持移动!') return } if (!movetodirid) { message.error('没有选择要移动到的位置!') return } if (movetodirid == selectedData.dirID) { message.error('不能移动到原位置!') return } const file_idList: string[] = [] const filenameList: string[] = [] const selectedFile = usePanFileStore().GetSelected() if (selectedFile.length == 0) { message.error('没有选择要拖放移动的文件!') return } for (let i = 0, maxi = selectedFile.length; i < maxi; i++) { file_idList.push(selectedFile[i].file_id) filenameList.push(selectedFile[i].name) } if (file_idList.includes(movetodirid)) { if (file_idList.length == 1) message.info('用户取消移动') else message.error('不能移动到原位置!') return } AliFileCmd.ApiMoveBatch(selectedData.user_id, selectedData.drive_id, file_idList, selectedData.drive_id, movetodirid).then((success: string[]) => { usePanFileStore().mDeleteFiles(selectedData.dirID, success, true) PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, movetodirid) TreeStore.ClearDirSize(selectedData.drive_id, [movetodirid, ...selectedData.selectedParentKeys]) }) } export async function menuFileColorChange(istree: boolean, color: string) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('标记文件操作失败 父文件夹错误') return } if (selectedData.isErrorSelected) { message.error('没有可以标记的文件') return } color = color.toLowerCase().replace('#', 'c') if (topbtnLock.has('menuFileColorChange')) return topbtnLock.add('menuFileColorChange') try { const successList = await AliFileCmd.ApiFileColorBatch(selectedData.user_id, selectedData.drive_id, color, selectedData.selectedKeys) usePanFileStore().mColorFiles(color, successList) } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('menuFileColorChange', err) } topbtnLock.delete('menuFileColorChange') } export function menuCreatShare(istree: boolean, shareby: string) { const selectedData = PanDAL.GetPanSelectedData(istree) if (selectedData.isError) { message.error('创建分享操作失败 父文件夹错误') return } let list: IAliGetFileModel[] = [] if (istree) { const dir = usePanTreeStore().selectDir list = [ { __v_skip: true, drive_id: dir.drive_id, file_id: dir.file_id, parent_file_id: dir.parent_file_id, name: dir.name, namesearch: dir.namesearch, ext: '', category: '', icon: 'iconfile-folder', size: 0, sizeStr: '', time: 0, timeStr: '', starred: false, isDir: true, thumbnail: '', description: '' } ] } else { list = usePanFileStore().GetSelected() } if (list.length == 0) { message.error('没有可以分享的文件!') return } modalCreatNewShareLink(shareby, list) } export async function topFavorDeleteAll() { const selectedData = PanDAL.GetPanSelectedData(false) if (selectedData.isError) { message.error('清空收藏夹操作失败 父文件夹错误') return } if (topbtnLock.has('topFavorDeleteAll')) return topbtnLock.add('topFavorDeleteAll') try { const loadingKey = 'cleartrash_' + Date.now().toString() message.loading('清空收藏夹执行中...', 60, loadingKey) let count = 0 while (true) { const resp: IAliFileResp = NewIAliFileResp(selectedData.user_id, selectedData.drive_id, 'favorite', '收藏夹') await AliTrash.ApiFavorFileListOnePageForClean('updated_at', 'DESC', resp) if (resp.items.length > 0) { const selectkeys = ArrayKeyList('file_id', resp.items) const successList = await AliFileCmd.ApiFavorBatch(selectedData.user_id, selectedData.drive_id, false, false, selectkeys) count += successList.length message.loading('清空收藏夹执行中...(' + count.toString() + ')', 60, loadingKey) } else { break } } message.success('清空收藏夹 成功!', 3, loadingKey) if (usePanTreeStore().selectDir.file_id == 'favorite') PanDAL.aReLoadOneDirToShow('', 'refresh', false) } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('topFavorDeleteAll', err) } topbtnLock.delete('topFavorDeleteAll') } export async function topTrashDeleteAll() { const selectedData = PanDAL.GetPanSelectedData(false) if (selectedData.isError) { message.error('清空回收站操作失败 父文件夹错误') return } if (topbtnLock.has('topTrashDeleteAll')) return topbtnLock.add('topTrashDeleteAll') const loadingKey = 'cleartrash_' + Date.now().toString() try { message.loading('清空回收站执行中...', 60, loadingKey) let count = 0 while (true) { const resp: IAliFileResp = NewIAliFileResp(selectedData.user_id, selectedData.drive_id, 'trash', '回收站') await AliTrash.ApiTrashFileListOnePageForClean('updated_at', 'DESC', resp) if (resp.items.length > 0) { const selectkeys = ArrayKeyList('file_id', resp.items) const successList = await AliFileCmd.ApiTrashCleanBatch(selectedData.user_id, selectedData.drive_id, false, selectkeys) count += successList.length message.loading('清空回收站执行中...(' + count.toString() + ')', 0, loadingKey) } else { break } } message.success('清空回收站 成功!', 3, loadingKey) if (usePanTreeStore().selectDir.file_id == 'trash') PanDAL.aReLoadOneDirToShow('', 'refresh', false) } catch (err: any) { message.error(err.message, 3, loadingKey) DebugLog.mSaveDanger('topTrashDeleteAll', err) } topbtnLock.delete('topTrashDeleteAll') } export async function topRecoverSelectedFile() { const selectedData = PanDAL.GetPanSelectedData(false) if (selectedData.isError) { message.error('恢复文件操作失败 父文件夹错误') return } const files = usePanFileStore().GetSelected() if (files.length == 0) { message.error('没有选择要恢复的文件!') return } const resumeList: { drive_id: string; file_id: string; content_hash: string; size: number; name: string }[] = [] const selectParentKeys: string[] = ['root', 'recover'] for (let i = 0, maxi = files.length; i < maxi; i++) { const file = files[i] resumeList.push({ drive_id: file.drive_id, file_id: file.file_id, content_hash: file.description, size: file.size, name: file.name }) if (selectParentKeys.includes(files[i].parent_file_id) == false) selectParentKeys.push(files[i].parent_file_id) } if (resumeList.length == 0) { message.error('没有可以恢复的文件') return } if (topbtnLock.has('topRecoverSelectedFile')) return topbtnLock.add('topRecoverSelectedFile') const loadingKey = 'recover_' + Date.now().toString() try { message.loading('文件恢复执行中...', 60, loadingKey) let successList: string[] = [] const oneTimeList: { drive_id: string; file_id: string; content_hash: string; size: number; name: string }[] = [] for (let i = 0, maxi = resumeList.length; i < maxi; i++) { oneTimeList.push(resumeList[i]) if (oneTimeList.length > 99) { const data = await AliFileCmd.ApiRecoverBatch(selectedData.user_id, oneTimeList) successList = successList.concat(data) oneTimeList.length = 0 message.loading('文件恢复执行中...(' + i.toString() + ')', 60, loadingKey) } } if (oneTimeList.length > 0) { const data = await AliFileCmd.ApiRecoverBatch(selectedData.user_id, oneTimeList) successList = successList.concat(data) oneTimeList.length = 0 } message.success('文件恢复(' + successList.length + ') 成功!', 3, loadingKey) PanDAL.aReLoadOneDirToRefreshTree(selectedData.user_id, selectedData.drive_id, 'root') usePanFileStore().mDeleteFiles('recover', successList, false) } catch (err: any) { message.error(err.message, 3, loadingKey) DebugLog.mSaveDanger('topRecoverSelectedFile', err) } topbtnLock.delete('topRecoverSelectedFile') } export async function topSearchAll(word: string) { if (word == 'topSearchAll高级搜索') { modalSearchPan() return } const pantreeStore = usePanTreeStore() if (!pantreeStore.user_id || !pantreeStore.drive_id || !pantreeStore.selectDir.file_id) { message.error('搜索文件操作失败 父文件夹错误') return } const searchid = 'search' + word PanDAL.aReLoadOneDirToShow('', searchid, false) } export async function menuJumpToDir() { let first = usePanFileStore().GetSelectedFirst() if (first && !first.parent_file_id) first = await AliFile.ApiGetFile(usePanTreeStore().user_id, first.drive_id, first.file_id) if (!first) { message.error('没有选中任何文件') return } PanDAL.aReLoadOneDirToShow('', first.parent_file_id, true).then(() => { usePanFileStore().mKeyboardSelect(first!.file_id, false, false) usePanFileStore().mSaveFileScrollTo(first!.file_id) }) } export function menuVideoXBT() { const first = usePanFileStore().GetSelectedFirst() if (!first) { message.error('没有选中任何文件') return } if (first.icon == 'iconweifa') { message.error('违规视频无法预览') return } const pageVideoXBT: IPageVideoXBT = { user_id: usePanTreeStore().user_id, drive_id: first.drive_id, file_id: first.file_id, file_name: first.name } window.WebOpenWindow({ page: 'PageVideoXBT', data: pageVideoXBT, theme: 'dark' }) } export function menuDLNA() { const first = usePanFileStore().GetSelectedFirst() if (!first) { message.error('没有选中任何文件') return } modalDLNAPlayer() } export function menuM3U8Download() { const first = usePanFileStore().GetSelectedFirst() if (!first) { message.error('没有选中任何文件') return } modalM3U8Download() } export function menuCopyFileName() { const list: IAliGetFileModel[] = usePanFileStore().GetSelected() if (list.length == 0) { message.error('没有选择要复制文件名的文件!') return } if (topbtnLock.has('menuCopyFileName')) return topbtnLock.add('menuCopyFileName') try { const nameList: string[] = [] for (let i = 0, maxi = list.length; i < maxi; i++) { nameList.push(list[i].name) } const fullStr = nameList.join('\r\n') copyToClipboard(fullStr) message.success('选中文件的文件名已复制到剪切板') } catch (err: any) { message.error(err.message) DebugLog.mSaveDanger('menuCopyFileName', err) } topbtnLock.delete('menuCopyFileName') } export function menuCopyFileTree() { const list: IAliGetFileModel[] = usePanFileStore().GetSelected() if (list.length == 0) { message.error('没有选中任何文件!') return } modalCopyFileTree(list) } ================================================ FILE: src/renderer/pic/PicLeft.vue ================================================ ================================================ FILE: src/renderer/pic/PicRight.vue ================================================ ================================================ FILE: src/renderer/pic/index.vue ================================================ ================================================ FILE: src/renderer/rss/ScanDAL.ts ================================================ import { h, Ref } from 'vue' import AliDirList from '../aliapi/dirlist' import { IAliGetDirModel } from '../aliapi/alimodels' import DebugLog from '../utils/debuglog' import message from '../utils/message' import DB from '../utils/db' export interface TreeNodeData { key: string title: string selectable?: boolean disabled?: boolean disableCheckbox?: boolean checkable?: boolean children: TreeNodeData[] icon: any size: number sizeStr?: string } export interface FileData { file_id: string name: string parent_file_id: string size: number sizeStr: string time: number timeStr: string icon: string parent_file_path: string } export interface FileNodeData { hash: string files: FileData[] } export interface ScanTreeDataModel { expandedKeys: string[] checkedKeys: string[] treeData: TreeNodeData[] treeDataMap: Map } export interface IScanDriverModel { drive_id: string DirMap: Map DirChildrenMap: Map EnmptyDirMap: Map WeiGuiDirMap: Map NoShareDirMap: Map SameDirMap: Map CleanDirMap: Map } export function NewScanDriver(drive_id: string): IScanDriverModel { return { drive_id, DirMap: new Map(), DirChildrenMap: new Map(), EnmptyDirMap: new Map(), WeiGuiDirMap: new Map(), NoShareDirMap: new Map(), SameDirMap: new Map(), CleanDirMap: new Map() } } export function ResetScanDriver(data: IScanDriverModel) { data.drive_id = '' data.DirMap = new Map() data.DirChildrenMap = new Map() data.EnmptyDirMap = new Map() data.WeiGuiDirMap = new Map() data.NoShareDirMap = new Map() data.SameDirMap = new Map() } function GetScanDriver(drive_id: string, children: IAliGetDirModel[]): IScanDriverModel { const ts = Date.now() const driverData = NewScanDriver(drive_id) const root: IAliGetDirModel = { __v_skip: true, drive_id, file_id: 'root', parent_file_id: '', name: '根目录', namesearch: '', size: 0, time: 0, description: '' } driverData.DirMap.set(root.file_id, root) const childrenMap = new Map() childrenMap.set(root.file_id, []) try { let parent_file_id: string = '' let parentDir: IAliGetDirModel[] = [] let item: IAliGetDirModel for (let i = 0, maxi = children.length; i < maxi; i++) { item = children[i] item.description = '' driverData.DirMap.set(item.file_id, item) if (parent_file_id != item.parent_file_id) { if (childrenMap.has(item.parent_file_id)) { parentDir = childrenMap.get(item.parent_file_id)! } else { parentDir = [] childrenMap.set(item.parent_file_id, parentDir) } parent_file_id = item.parent_file_id } parentDir.push(item) } } catch {} driverData.DirChildrenMap = childrenMap console.log('SaveAllDirLite time=', Date.now() - ts) return driverData } export function LoadScanDir(user_id: string, drive_id: string, totalDirCount: Ref, processing: Ref, scanPanData: IScanDriverModel) { scanPanData.drive_id = drive_id scanPanData.DirMap = new Map() scanPanData.DirChildrenMap = new Map() return GetAllDir(user_id, drive_id).then((dirList: IAliGetDirModel[]) => { totalDirCount.value = dirList.length processing.value = 50 const PanData = GetScanDriver(drive_id, dirList) Object.assign(scanPanData, PanData) }) } async function GetAllDir(user_id: string, drive_id: string) { const data = await DB.getValueObject('AllDir_' + drive_id) if (data) { const dt = await DB.getValueNumber('AllDir_' + drive_id) if (Date.now() - dt < 1000 * 60 * 60) { return data as IAliGetDirModel[] } } return AliDirList.ApiFastAllDirListByPID(user_id, drive_id) .then((data) => { if (!data.next_marker) { // return data.items const list: IAliGetDirModel[] = [] for (let i = 0, maxi = data.items.length; i < maxi; i++) { const item = data.items[i] list.push({ __v_skip: true, drive_id: drive_id, file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, namesearch: '', size: 0, time: 0, description: '' } as IAliGetDirModel) } DB.saveValueObject('AllDir_' + drive_id, data.items) DB.saveValueNumber('AllDir_' + drive_id, Date.now()) return list } else { DebugLog.mSaveWarning('列出文件夹失败file_id=all' + ' next_marker=' + data.next_marker) message.error('列出全盘文件夹失败' + data.next_marker) return [] } }) .catch((err: any) => { DebugLog.mSaveWarning('列出文件夹失败file_id=all', err) message.error('列出全盘文件夹失败' + err.message) return [] }) } const iconFolder = h('i', { class: 'iconfont iconfile-folder' }) export const foldericonfn = () => iconFolder const fileIcon = h('i', { class: 'iconfont iconwenjian' }) export const fileiconfn = () => fileIcon const iconWeifa = h('i', { class: 'iconfont iconweifa' }) const iconWeixiang = h('i', { class: 'iconfont iconweixiang' }) export const iconWeixiangFn = () => iconWeixiang export const iconWeifaFn = () => iconWeifa export function TreeSelectAll(checkedKeys: Ref, checkedKeysBak: string[]) { if (checkedKeys.value.length == checkedKeysBak.length) { checkedKeys.value = [] } else { checkedKeys.value = checkedKeysBak.concat() } } export function TreeSelectOne(selectedKeys: string[], checkedKeys: Ref) { if (selectedKeys.length > 0) { const key = selectedKeys[0] const checkedkeys = checkedKeys.value if (checkedkeys.includes(key)) { checkedKeys.value = checkedkeys.filter(function (x) { return x != key }) } else { checkedKeys.value.push(key) } } } export function TreeCheckFileChild(node: TreeNodeData, checkedKeys: Ref) { if (node.icon != foldericonfn) { TreeSelectOne([node.key], checkedKeys) return } const keys: string[] = [] GetFileChildNode(keys, node) if (keys.length == 0) return let isall = true const checkedkeysSet = new Set(checkedKeys.value) for (let i = 0, maxi = keys.length; i < maxi; i++) { if (!checkedkeysSet.has(keys[i])) { isall = false break } } if (isall) { for (let i = 0, maxi = keys.length; i < maxi; i++) { checkedkeysSet.delete(keys[i]) } } else { for (let i = 0, maxi = keys.length; i < maxi; i++) { checkedkeysSet.add(keys[i]) } } checkedKeys.value = Array.from(checkedkeysSet) } function GetFileChildNode(keys: string[], node: TreeNodeData) { if (node.children && node.children.length > 0) { for (let i = 0, maxi = node.children.length; i < maxi; i++) { if (node.children[i].icon != foldericonfn) { keys.push(node.children[i].key) } else { GetFileChildNode(keys, node.children[i]) } } } else if (node.icon != foldericonfn) { keys.push(node.key) } } ================================================ FILE: src/renderer/rss/appsame/AppSame.vue ================================================ ================================================ FILE: src/renderer/rss/appsame/same.ts ================================================ import AliHttp from '../../aliapi/alihttp' import { IAliFileItem, IAliGetDirModel, IAliGetFileModel } from '../../aliapi/alimodels' import AliDirFileList from '../../aliapi/dirfilelist' import DebugLog from '../../utils/debuglog' import { humanSize } from '../../utils/format' import message from '../../utils/message' import { Ref } from 'vue' import { FileData, IScanDriverModel } from '../ScanDAL' export async function GetDuplicateInfo(user_id: string, PanData: IScanDriverModel, scanType: string): Promise { if (!user_id) return '查询出错' const url = 'adrive/v1/file/getDuplicateInfo' const postData = { category: scanType, drive_id: PanData.drive_id } const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { return '找到' + (resp.body.total_group_count || 0) + '组重复文件,包含' + (resp.body.total_group_count || 0) + '个文件,总体积' + humanSize(resp.body.total_size || 0) } else { DebugLog.mSaveWarning('GetDuplicateInfo err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('GetDuplicateInfo ' + PanData.drive_id, err) } return '查询出错' } export async function GetSameFile(user_id: string, PanData: IScanDriverModel, Processing: Ref, scanCount: Ref, totalFileCount: Ref, scanType: string): Promise { scanCount.value = 0 const fileList = await ApiDuplicateList(user_id, PanData.drive_id, scanType == 'all' ? '' : scanType, Processing) if (!fileList) return false totalFileCount.value += fileList.length for (let j = 0, maxj = fileList.length; j < maxj; j++) { const fileItem = fileList[j] const hash = fileItem.namesearch if (hash) { let saveList = PanData.SameDirMap.get(hash) if (!saveList) saveList = [] if (saveList.length < 50) { saveList.push({ file_id: fileItem.file_id, name: fileItem.name, parent_file_id: fileItem.parent_file_id, size: fileItem.size, sizeStr: fileItem.sizeStr, time: fileItem.time, timeStr: fileItem.timeStr, icon: fileItem.icon, parent_file_path: '' } as FileData) PanData.SameDirMap.set(hash, saveList) } } } const sameDirMap = new Map() const entries = PanData.SameDirMap.entries() for (let i = 0, maxi = PanData.SameDirMap.size; i < maxi; i++) { const value = entries.next().value const arr = value[1] as FileData[] if (arr.length > 1) { arr.map((a) => { a.parent_file_path = GetParentPath(PanData, a.parent_file_id) return true }) arr.sort((a, b) => b.time - a.time) sameDirMap.set(value[0], arr) } } PanData.SameDirMap = sameDirMap scanCount.value = sameDirMap.size return true } /* 计算出完整的路径* */ function GetParentPath(PanData: IScanDriverModel, file_id: string) { const path: string[] = [] let dir: IAliGetDirModel | undefined while (true) { dir = PanData.DirMap.get(file_id) if (!dir) break path.push(dir.name) file_id = dir.parent_file_id if (!file_id) break } if (path.length == 0) return '' path.reverse() return path.join(' > ') } async function ApiDuplicateList(user_id: string, drive_id: string, category: string, Processing: Ref) { if (!user_id || !drive_id) return [] let next_marker = '' const items: IAliGetFileModel[] = [] do { const url = 'adrive/v1/file/duplicateList' let postData = { drive_id: drive_id, marker: next_marker } if (category) postData = Object.assign(postData, { category: category }) const resp = await AliHttp.Post(url, postData, user_id, '') Processing.value += 1 try { if (AliHttp.IsSuccess(resp.code)) { next_marker = resp.body.next_marker for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) { const oneItems = resp.body.items[i].items as IAliFileItem[] for (let j = 0; j < oneItems.length; j++) { const add = AliDirFileList.getFileInfo(oneItems[j], '') add.namesearch = oneItems[j].content_hash items.push(add) } } continue } else if (resp.code && resp.code == 403) { if (resp.body?.code == 'UserNotVip') message.error('此功能需要开通阿里云盘会员,请使用 扫描重复文件 功能代替') else message.error(resp.body?.code || '拒绝访问') return undefined } else if (resp.body && resp.body.code) { message.warning('列出文件出错 ' + resp.body.code, 2) } else { DebugLog.mSaveWarning('ApiDuplicateList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('ApiDuplicateList ' + drive_id, err) } return [] } while (next_marker) return items } ================================================ FILE: src/renderer/rss/index.vue ================================================ ================================================ FILE: src/renderer/rss/rssdrivecopy/RssDriveCopy.vue ================================================ ================================================ FILE: src/renderer/rss/rssdrivecopy/drivecopy.ts ================================================ import { IAliGetFileModel } from '../../aliapi/alimodels' import AliFile from '../../aliapi/file' import message from '../../utils/message' import { fileiconfn, foldericonfn } from '../ScanDAL' import AliTrash from '../../aliapi/trash' export interface ICopyTreeInfo { user_id: string drive_id: string driveType: string dirID: string dirName: string parentID: string loading: boolean onlyDir: boolean } export function NewCopyTreeInfo(onlyDir: boolean) { const info: ICopyTreeInfo = { user_id: '', driveType: '', drive_id: '', dirID: '', dirName: '', parentID: '', loading: false, onlyDir: onlyDir } return info } export interface ICopyTreeNode { key: string title: string icon: any download_url: string disabled: boolean children?: ICopyTreeNode[] } export async function LoadDir(dirID: string, DirData: ICopyTreeInfo, treeData: ICopyTreeNode[], disabledFile: boolean): Promise { DirData.loading = true if (!dirID) dirID = 'root' if (dirID.startsWith('dir_')) dirID = dirID.substring('dir_'.length) if (dirID == 'root') { DirData.dirID = 'root' DirData.dirName = '根目录' DirData.parentID = 'root' } else { const getDir = await AliFile.ApiFileInfo(DirData.user_id, DirData.drive_id, dirID) if (getDir) { DirData.dirID = getDir.file_id DirData.dirName = getDir.name DirData.parentID = getDir.parent_file_id } else { message.error('读取文件夹信息失败') } } const resp = await AliTrash.ApiDirFileListNoLock(DirData.user_id, DirData.drive_id, dirID, '', '', '') DirData.loading = false const list: ICopyTreeNode[] = [] const items = resp.items let item: IAliGetFileModel for (let i = 0, maxi = items.length; i < maxi; i++) { item = items[i] list.push({ key: (item.isDir ? 'dir_' : 'file_') + item.file_id, title: item.name, disabled: item.isDir ? false : disabledFile, icon: item.isDir ? foldericonfn : fileiconfn, download_url: '' } as ICopyTreeNode) } treeData.splice(0, treeData.length, ...list) } ================================================ FILE: src/renderer/rss/rssjiami/RssJiaMi.vue ================================================ ================================================ FILE: src/renderer/rss/rssjiami/jiami.ts ================================================ import { FileSystemErrorMessage } from '../../utils/filehelper' import DebugLog from '../../utils/debuglog' import message from '../../utils/message' const { Buffer } = window.require('buffer') const fspromises = window.require('fs/promises') const path = window.require('path') export async function DoXiMa(dirPath: string, breakSmall: boolean, matchExtList: string[]): Promise { const fileList: string[] = [] await GetAllFiles(dirPath, breakSmall, fileList) if (fileList.length == 0) { message.error('选择的文件夹下找不到任何文件') return 0 } else { let rand = Date.now() const rand1 = rand % 256 rand = rand / 128 const rand2 = Math.floor(rand % 256) let rand3 = Math.floor(Math.random() * 255) let RunCount = 0 for (let i = 0, maxi = fileList.length; i < maxi; i++) { const file = fileList[i].toLowerCase().trimEnd() if (matchExtList.length > 0) { let find = false for (let j = 0; j < matchExtList.length; j++) { if (file.endsWith(matchExtList[j])) { find = true break } } if (find == false) continue } try { const rand4 = (i % 255) + 1 if (rand4 == 200) rand3 = Math.floor(Math.random() * 255) const buff = Buffer.from([0, rand1, rand2, rand3, rand4]) fspromises.appendFile(fileList[i], buff).catch(() => {}) RunCount++ } catch (err: any) { DebugLog.mSaveDanger('XM appendFile' + (err.message || '') + fileList[i]) } } return RunCount } } async function GetAllFiles(dir: string, breakSmall: boolean, fileList: string[]) { if (dir.endsWith(path.sep) == false) dir = dir + path.sep try { const childFiles = await fspromises.readdir(dir).catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('XM GetAllFiles文件失败:' + dir, err) message.error('跳过文件夹:' + err + ' ' + dir) return [] }) let allTask: Promise[] = [] const dirList: string[] = [] for (let i = 0, maxi = childFiles.length; i < maxi; i++) { const name = childFiles[i] as string if (name.startsWith('.')) continue if (name.startsWith('#')) continue const item = dir + name allTask.push( fspromises .lstat(item) .then((stat: any) => { if (stat.isDirectory()) dirList.push(item) else if (stat.isSymbolicLink()) { // donothing } else if (stat.isFile()) { if (breakSmall == false || stat.size > 5 * 1024 * 1024) fileList.push(item) } }) .catch() ) if (allTask.length > 10) { await Promise.all(allTask).catch(() => {}) allTask = [] } } if (allTask.length > 0) { await Promise.all(allTask).catch(() => {}) allTask = [] } for (let i = 0, maxi = dirList.length; i < maxi; i++) { await GetAllFiles(dirList[i], breakSmall, fileList) } } catch (err: any) { DebugLog.mSaveDanger('GetAllFiles' + (err.message || '')) } return true } ================================================ FILE: src/renderer/rss/rssrename/RssRename.vue ================================================ ================================================ FILE: src/renderer/rss/rssscanclean/RssScanClean.vue ================================================ ================================================ FILE: src/renderer/rss/rssscanclean/ScanClean.ts ================================================ import AliHttp from '../../aliapi/alihttp' import { IAliGetDirModel } from '../../aliapi/alimodels' import { IAliDirBatchResp } from '../../aliapi/dirlist' import AliDirFileList from '../../aliapi/dirfilelist' import DebugLog from '../../utils/debuglog' import { humanSize } from '../../utils/format' import { HanToPin } from '../../utils/utils' import { h, Ref } from 'vue' import { foldericonfn, IScanDriverModel, TreeNodeData } from '../ScanDAL' export async function GetCleanFile(user_id: string, PanData: IScanDriverModel, Processing: Ref, scanCount: Ref, totalFileCount: Ref, scanType: string) { scanCount.value = 0 const keys = PanData.DirMap.keys() let dirList: IAliDirBatchResp[] = [] Processing.value = 0 while (true) { let add = 0 while (dirList.length < 20) { const key = keys.next() if (!key.done) { add++ dirList.push({ dirID: key.value, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp) } else break } Processing.value += add if (dirList.length == 0) break if (!PanData.drive_id) break const isGet = await ApiBatchDirFileList(user_id, PanData.drive_id, dirList, scanType) if (isGet) { const list: IAliDirBatchResp[] = [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].next_marker && dirList[i].items.length < 2000) { list.push(dirList[i]) } else { const dirID = dirList[i].dirID const fileList = dirList[i].items totalFileCount.value += fileList.length let saveList: IAliGetDirModel[] = [] for (let j = 0, maxj = fileList.length; j < maxj; j++) { const fileItem = fileList[j] saveList.push({ __v_skip: true, drive_id: fileItem.drive_id, file_id: fileItem.file_id, parent_file_id: fileItem.parent_file_id, name: fileItem.name, namesearch: fileItem.namesearch || HanToPin(fileItem.name), size: fileItem.size, time: fileItem.time, description: fileItem.icon } as IAliGetDirModel) } if (saveList.length > 0) { const node = PanData.DirChildrenMap.get(dirID) if (node && node.length > 0) { node.sort((a, b) => a.name.localeCompare(b.name)) saveList.sort((a, b) => b.size - a.size) saveList = node.concat(saveList) } else { saveList.sort((a, b) => b.size - a.size) } PanData.DirChildrenMap.set(dirID, saveList) } if (saveList.length > 0) { let dir = PanData.DirMap.get(dirID) if (dir) { PanData.CleanDirMap.set(dir.file_id, 'clean') while (true) { if (!dir.parent_file_id || PanData.CleanDirMap.has(dir.parent_file_id)) break PanData.CleanDirMap.set(dir.parent_file_id, 'parent') dir = PanData.DirMap.get(dir.parent_file_id)! } } } } } dirList.length = 0 dirList = list } } Processing.value = PanData.DirMap.size } async function ApiBatchDirFileList(user_id: string, drive_id: string, dirList: IAliDirBatchResp[], scanType: string) { if (!user_id || !drive_id || dirList.length == 0) return false let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' let query = 'parent_file_id="' + dirList[i].dirID + '"' if (scanType == 'size10') query += ' and size > 10485760' else if (scanType == 'size100') query += ' and size > 104857600' else if (scanType == 'size1000') query += ' and size > 1048576000' else if (scanType == 'size5000') query += ' and size > 5242880000' else if (['video', 'doc', 'image', 'audio', 'others', 'zip'].includes(scanType)) query += ' and size > 1048576000 and category = "' + scanType + '"' if (!query.includes('category')) query += ' and type = "file"' const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, limit: 100, fields: 'thumbnail', order_by: 'size DESC' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID, method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cmime_extension%2Cpunish_flag)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID == id) { const dir = dirList[i] const items = respi.body.items dir.next_marker = respi.body.next_marker for (let i = 0, maxi = items.length; i < maxi; i++) { if (dir.itemsKey.has(items[i].file_id)) continue const add = AliDirFileList.getFileInfo(items[i], '') dir.items.push(add) dir.itemsKey.add(add.file_id) } if (dir.items.length >= 3000) dir.next_marker = '' break } } } } return true } else { DebugLog.mSaveWarning('SCApiDuplicateList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveWarning('ApiBatchDirFileList', err) } return false } const fileiconfn = (icon: string) => h('i', { class: 'iconfont ' + icon }) export function GetTreeNodes(PanData: IScanDriverModel, parent_file_id: string, treeDataMap: Map) { const data: TreeNodeData[] = [] let item: IAliGetDirModel const dirList = PanData.DirChildrenMap.get(parent_file_id) || [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { item = dirList[i] if (item.description != '' || PanData.CleanDirMap.has(item.file_id)) { const isDir = item.description == 'iconfile-folder' || !item.description data.push({ key: item.file_id, title: item.name, icon: isDir ? foldericonfn : () => fileiconfn(item.description), children: GetTreeNodes(PanData, item.file_id, treeDataMap), size: isDir ? 0 : item.size, sizeStr: isDir ? '' : humanSize(item.size) } as TreeNodeData) } } data.map((a) => { treeDataMap.set(a.key as string, a) return true }) return data } export function DeleteFromScanClean(PanData: IScanDriverModel, idList: string[]) { const entries = PanData.DirChildrenMap.entries() for (let i = 0, maxi = PanData.DirChildrenMap.size; i < maxi && idList.length > 0; i++) { const value = entries.next().value const children = value[1] as IAliGetDirModel[] const saveList: IAliGetDirModel[] = [] for (let j = 0, maxj = children.length; j < maxj; j++) { const key = children[j].file_id if (idList.includes(key)) { idList = idList.filter((t) => t != key) } else { saveList.push(children[j]) } } if (children.length != saveList.length) PanData.DirChildrenMap.set(value[0], saveList) } } export function GetTreeCheckedSize(PanData: IScanDriverModel, checkedKeys: string[]) { if (checkedKeys.length == 0) return 0 const checkedMap = new Set(checkedKeys) let checkedsize = 0 const treeDataMap = new Map() GetTreeNodes(PanData, 'root', treeDataMap) const values = treeDataMap.values() let clen = 0 for (let i = 0, maxi = treeDataMap.size; i < maxi; i++) { const node = values.next().value as TreeNodeData if (checkedMap.has(node.key)) { clen = node.children!.length if (clen > 0) { // donothing } else if (node.icon != foldericonfn) { checkedsize += node.size } } } return checkedsize } ================================================ FILE: src/renderer/rss/rssscanenmpty/RssScanEnmpty.vue ================================================ ================================================ FILE: src/renderer/rss/rssscanenmpty/scanenmpty.ts ================================================ import AliHttp from '../../aliapi/alihttp' import { IAliGetDirModel } from '../../aliapi/alimodels' import DebugLog from '../../utils/debuglog' import { Ref } from 'vue' import { foldericonfn, IScanDriverModel, TreeNodeData } from '../ScanDAL' export async function GetEnmptyDir(user_id: string, PanData: IScanDriverModel, Processing: Ref, scanCount: Ref) { scanCount.value = 0 const enmpty = new Map() const entries = PanData.DirMap.keys() for (let i = 0, maxi = PanData.DirMap.size; i < maxi; i++) { const key = entries.next().value if (!PanData.DirChildrenMap.has(key)) { enmpty.set(key, PanData.DirMap.get(key)!) } } const proAdd = (100 - Processing.value) / ((enmpty.size + 1) / 99) let proVal = Processing.value const idList: string[] = [] const keys = enmpty.keys() for (let i = 0, maxi = enmpty.size; i < maxi; i++) { idList.push(keys.next().value) if (idList.length >= 100) { proVal += proAdd Processing.value = Math.max(50, Math.floor(proVal)) scanCount.value += await TestEnmptyDir(user_id, PanData, idList) idList.length = 0 } } if (idList.length > 0) { scanCount.value += await TestEnmptyDir(user_id, PanData, idList) idList.length = 0 } Processing.value = 99 } async function TestEnmptyDir(user_id: string, PanData: IScanDriverModel, idList: string[]) { const enmptyidList = await ApiTestEnmptyDir(user_id, PanData.drive_id, idList) if (enmptyidList.length > 0) { for (let i = 0, maxi = enmptyidList.length; i < maxi; i++) { let dir = PanData.DirMap.get(enmptyidList[i]) if (dir) { PanData.EnmptyDirMap.set(dir.file_id, 'enmpty') while (true) { if (!dir || !dir.parent_file_id || PanData.EnmptyDirMap.has(dir.parent_file_id)) break PanData.EnmptyDirMap.set(dir.parent_file_id, 'parent') dir = PanData.DirMap.get(dir.parent_file_id) } } } } return enmptyidList.length } async function ApiTestEnmptyDir(user_id: string, drive_id: string, idList: string[]) { const list: string[] = [] if (!user_id || !drive_id || idList.length === 0) return [] let postData = '{"requests":[' for (let i = 0, maxi = idList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' const data2 = { body: { drive_id: drive_id, query: 'parent_file_id="' + idList[i] + '"', limit: 1, fields: 'thumbnail' }, headers: { 'Content-Type': 'application/json' }, id: idList[i], method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cmime_extension%2Cpunish_flag)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] if (respi.body.items.length == 0) list.push(respi.id) } } return list } else { DebugLog.mSaveWarning('ApiTestEnmptyDir err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveWarning('ApiTestEnmptyDir', err) } return list } export function GetTreeNodes(PanData: IScanDriverModel, parent_file_id: string, treeDataMap: Map) { const data: TreeNodeData[] = [] let item: IAliGetDirModel const dirList = PanData.DirChildrenMap.get(parent_file_id) || [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { item = dirList[i] if (PanData.EnmptyDirMap.has(item.file_id)) { data.push({ key: item.file_id, title: item.name, icon: foldericonfn, size: item.size, children: GetTreeNodes(PanData, item.file_id, treeDataMap) } as TreeNodeData) } } data.sort((a, b) => a.title!.localeCompare(b.title!)) data.map((a) => { treeDataMap.set(a.key as string, a) return true }) return data } ================================================ FILE: src/renderer/rss/rssscanpunish/RssScanPunish.vue ================================================ ================================================ FILE: src/renderer/rss/rssscanpunish/scanpunish.ts ================================================ import AliHttp from '../../aliapi/alihttp' import { IAliGetDirModel } from '../../aliapi/alimodels' import { IAliDirBatchResp } from '../../aliapi/dirlist' import AliDirFileList from '../../aliapi/dirfilelist' import DebugLog from '../../utils/debuglog' import { Ref } from 'vue' import { foldericonfn, iconWeifaFn, iconWeixiangFn, IScanDriverModel, TreeNodeData } from '../ScanDAL' export async function GetWeiGuiFile(user_id: string, PanData: IScanDriverModel, Processing: Ref, scanCount: Ref, totalFileCount: Ref, scanType: string) { scanCount.value = 0 const keys = PanData.DirMap.keys() let dirList: IAliDirBatchResp[] = [] Processing.value = 0 while (true) { let add = 0 while (dirList.length < 20) { const key = keys.next() if (!key.done) { add++ dirList.push({ dirID: key.value, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp) } else break } Processing.value += add if (dirList.length == 0) break if (!PanData.drive_id) break const isGet = await ApiBatchDirFileList(user_id, PanData.drive_id, dirList, scanType) if (isGet) { const list: IAliDirBatchResp[] = [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].next_marker && dirList[i].items.length < 2000) { list.push(dirList[i]) } else { const dirID = dirList[i].dirID const fileList = dirList[i].items totalFileCount.value += fileList.length let saveList: IAliGetDirModel[] = [] let weifa = 0 let noshare = 0 for (let j = 0, maxj = fileList.length; j < maxj; j++) { const fileItem = fileList[j] if (fileItem.icon == 'iconweifa' || fileItem.icon == 'iconweixiang') { saveList.push({ __v_skip: true, drive_id: fileItem.drive_id, file_id: fileItem.file_id, parent_file_id: fileItem.parent_file_id, name: fileItem.name, namesearch: '', size: fileItem.size, time: fileItem.time, description: fileItem.icon } as IAliGetDirModel) if (fileItem.icon == 'iconweifa') weifa++ if (fileItem.icon == 'iconweixiang') noshare++ } } if (saveList.length > 0) { const node = PanData.DirChildrenMap.get(dirID) if (node && node.length > 0) { node.sort((a, b) => a.name.localeCompare(b.name)) saveList.sort((a, b) => a.name.localeCompare(b.name)) saveList = node.concat(saveList) } else { saveList.sort((a, b) => a.name.localeCompare(b.name)) } PanData.DirChildrenMap.set(dirID, saveList) } if (weifa > 0) { let dir = PanData.DirMap.get(dirID) if (dir) { PanData.WeiGuiDirMap.set(dir.file_id, 'weifa') while (true) { if (!dir || !dir.parent_file_id || PanData.WeiGuiDirMap.has(dir.parent_file_id)) break PanData.WeiGuiDirMap.set(dir.parent_file_id, 'parent') dir = PanData.DirMap.get(dir.parent_file_id) } } } if (noshare > 0) { let dir = PanData.DirMap.get(dirID) if (dir) { PanData.NoShareDirMap.set(dir.file_id, 'noshare') while (true) { if (!dir || !dir.parent_file_id || PanData.NoShareDirMap.has(dir.parent_file_id)) break PanData.NoShareDirMap.set(dir.parent_file_id, 'parent') dir = PanData.DirMap.get(dir.parent_file_id) } } } } } dirList.length = 0 dirList = list } } Processing.value = PanData.DirMap.size } async function ApiBatchDirFileList(user_id: string, drive_id: string, dirList: IAliDirBatchResp[], scanType: string) { if (!user_id || !drive_id || dirList.length == 0) return false let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' let query = 'parent_file_id="' + dirList[i].dirID + '"' if (scanType == 'size10') query += ' and size > 10485760' else if (scanType == 'size100') query += ' and size > 104857600' else if (scanType == 'size1000') query += ' and size > 1048576000' else if (['video', 'doc', 'image', 'audio', 'others', 'zip'].includes(scanType)) query += ' and category = "' + scanType + '"' if (!query.includes('category')) query += ' and type = "file"' const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, limit: 100, fields: 'thumbnail' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID, method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cmime_extension%2Cpunish_flag)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID == id) { const dir = dirList[i] const items = respi.body.items dir.next_marker = respi.body.next_marker for (let i = 0, maxi = items.length; i < maxi; i++) { if (dir.itemsKey.has(items[i].file_id)) continue const add = AliDirFileList.getFileInfo(items[i], '') dir.items.push(add) dir.itemsKey.add(add.file_id) } if (dir.items.length >= 3000) dir.next_marker = '' break } } } } return true } else { DebugLog.mSaveWarning('SPApiBatchDirFileList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveWarning('ApiBatchDirFileList', err) } return false } export function GetTreeNodes(PanData: IScanDriverModel, parent_file_id: string, treeDataMap: Map, ShowWeiGui: boolean, ShowNoShare: boolean) { const data: TreeNodeData[] = [] let item: IAliGetDirModel const dirList = PanData.DirChildrenMap.get(parent_file_id) || [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { item = dirList[i] if (ShowWeiGui && (item.description == 'iconweifa' || PanData.WeiGuiDirMap.has(item.file_id))) { data.push({ key: item.file_id, title: item.name, icon: item.description == 'iconweifa' ? iconWeifaFn : foldericonfn, size: item.size, children: GetTreeNodes(PanData, item.file_id, treeDataMap, ShowWeiGui, ShowNoShare) } as TreeNodeData) } else if (ShowNoShare && (item.description == 'iconweixiang' || PanData.NoShareDirMap.has(item.file_id))) { data.push({ key: item.file_id, title: item.name, icon: item.description == 'iconweixiang' ? iconWeixiangFn : foldericonfn, size: item.size, children: GetTreeNodes(PanData, item.file_id, treeDataMap, ShowWeiGui, ShowNoShare) } as TreeNodeData) } } data.map((a) => { treeDataMap.set(a.key as string, a) return true }) return data } export function DeleteFromScanDataPunish(PanData: IScanDriverModel, idList: string[]) { const entries = PanData.DirChildrenMap.entries() for (let i = 0, maxi = PanData.DirChildrenMap.size; i < maxi && idList.length > 0; i++) { const value = entries.next().value const children = value[1] as IAliGetDirModel[] const saveList: IAliGetDirModel[] = [] for (let j = 0, maxj = children.length; j < maxj; j++) { const key = children[j].file_id if (idList.includes(key)) { idList = idList.filter((t) => t != key) } else { saveList.push(children[j]) } } if (children.length != saveList.length) PanData.DirChildrenMap.set(value[0], saveList) } } export function GetTreeCheckedSize(PanData: IScanDriverModel, checkedKeys: string[], ShowWeiGui: boolean, ShowNoShare: boolean) { if (checkedKeys.length == 0) return 0 const checkedMap = new Set(checkedKeys) let checkedsize = 0 const treeDataMap = new Map() GetTreeNodes(PanData, 'root', treeDataMap, ShowWeiGui, ShowNoShare) const values = treeDataMap.values() let clen = 0 for (let i = 0, maxi = treeDataMap.size; i < maxi; i++) { const node = values.next().value as TreeNodeData if (checkedMap.has(node.key)) { clen = node.children!.length if (clen > 0) { // donothing } else if (node.icon != foldericonfn) { checkedsize += node.size } } } return checkedsize } ================================================ FILE: src/renderer/rss/rssscansame/RssScanSame.vue ================================================ ================================================ FILE: src/renderer/rss/rssscansame/scansame.ts ================================================ import AliHttp from '../../aliapi/alihttp' import { IAliGetDirModel } from '../../aliapi/alimodels' import { IAliDirBatchResp } from '../../aliapi/dirlist' import AliDirFileList from '../../aliapi/dirfilelist' import DebugLog from '../../utils/debuglog' import message from '../../utils/message' import { Ref } from 'vue' import { FileData, IScanDriverModel } from '../ScanDAL' export async function GetSameFile(user_id: string, PanData: IScanDriverModel, Processing: Ref, scanCount: Ref, totalFileCount: Ref, scanType: string) { scanCount.value = 0 const keys = PanData.DirMap.keys() let dirList: IAliDirBatchResp[] = [] Processing.value = 0 while (true) { let add = 0 while (dirList.length < 20) { const key = keys.next() if (!key.done) { add++ dirList.push({ dirID: key.value, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp) } else break } Processing.value += add if (dirList.length == 0) break if (!PanData.drive_id) break const isGet = await ApiBatchDirFileList(user_id, PanData.drive_id, dirList, scanType) if (isGet) { const list: IAliDirBatchResp[] = [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].next_marker && dirList[i].items.length < 2000) { list.push(dirList[i]) } else { const fileList = dirList[i].items totalFileCount.value += fileList.length for (let j = 0, maxj = fileList.length; j < maxj; j++) { const fileItem = fileList[j] const hash = fileItem.namesearch if (hash) { let saveList = PanData.SameDirMap.get(hash) if (!saveList) saveList = [] if (saveList.length < 50) { saveList.push({ file_id: fileItem.file_id, name: fileItem.name, parent_file_id: fileItem.parent_file_id, size: fileItem.size, sizeStr: fileItem.sizeStr, time: fileItem.time, timeStr: fileItem.timeStr, icon: fileItem.icon, parent_file_path: '' } as FileData) PanData.SameDirMap.set(hash, saveList) } } } } } dirList.length = 0 dirList = list } } Processing.value = PanData.DirMap.size const sameDirMap = new Map() const entries = PanData.SameDirMap.entries() for (let i = 0, maxi = PanData.SameDirMap.size; i < maxi; i++) { const value = entries.next().value const arr = value[1] as FileData[] if (arr.length > 1) { arr.map((a) => { a.parent_file_path = GetParentPath(PanData, a.parent_file_id) return true }) arr.sort((a, b) => b.time - a.time) sameDirMap.set(value[0], arr) } } PanData.SameDirMap = sameDirMap scanCount.value = sameDirMap.size } /* 计算出完整的路径* */ function GetParentPath(PanData: IScanDriverModel, file_id: string) { const path: string[] = [] let dir: IAliGetDirModel | undefined while (true) { dir = PanData.DirMap.get(file_id) if (!dir) break path.push(dir.name) file_id = dir.parent_file_id if (!file_id) break } if (path.length == 0) return '' path.reverse() return path.join(' > ') } async function ApiBatchDirFileList(user_id: string, drive_id: string, dirList: IAliDirBatchResp[], scanType: string) { if (!user_id || !drive_id || dirList.length == 0) return false let postData = '{"requests":[' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (i > 0) postData = postData + ',' let query = 'parent_file_id="' + dirList[i].dirID + '"' if (scanType == 'size10') query += ' and size > 10485760' else if (scanType == 'size100') query += ' and size > 104857600' else if (scanType == 'size1000') query += ' and size > 1048576000' else if (['video', 'doc', 'image', 'audio', 'others', 'zip'].includes(scanType)) query += ' and category = "' + scanType + '"' if (!query.includes('category')) query += ' and type = "file"' const data2 = { body: { drive_id: drive_id, query: query, marker: dirList[i].next_marker, limit: 100, fields: 'thumbnail' }, headers: { 'Content-Type': 'application/json' }, id: dirList[i].dirID, method: 'POST', url: '/file/search' } postData = postData + JSON.stringify(data2) } postData += '],"resource":"file"}' const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cmime_extension%2Ccontent_hash%2Cpunish_flag)))' const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { const responses = resp.body.responses for (let j = 0, maxj = responses.length; j < maxj; j++) { const status = responses[j].status as number if (status >= 200 && status <= 205) { const respi = responses[j] const id = respi.id || '' for (let i = 0, maxi = dirList.length; i < maxi; i++) { if (dirList[i].dirID == id) { const dir = dirList[i] const items = respi.body.items dir.next_marker = respi.body.next_marker for (let i = 0, maxi = items.length; i < maxi; i++) { if (dir.itemsKey.has(items[i].file_id)) continue const add = AliDirFileList.getFileInfo(items[i], '') add.namesearch = items[i].content_hash dir.items.push(add) dir.itemsKey.add(add.file_id) } if (dir.items.length >= 3000) dir.next_marker = '' break } } } } return true } else { DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveWarning('ApiBatchDirFileList', err) } return false } // eslint-disable-next-line no-unused-vars async function ApiWalkDirFileList(user_id: string, drive_id: string, file_id: string, limit: number, category: string) { if (!user_id || !drive_id || !file_id) return false let next_marker = '' let items: any[] = [] do { const url = 'v2/file/walk?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(name%2Cfile_id%2Cdrive_id%2Ctype%2Csize%2Cupdated_at%2Ccategory%2Cfile_extension%2Cparent_file_id%2Cmime_type%2Cmime_extension%2Ccontent_hash%2Cpunish_flag)' let postData = { all: false, drive_id: drive_id, parent_file_id: file_id, marker: next_marker, limit: 1000, fields: 'thumbnail', order_by: 'updated_at', order_direction: 'DESC', image_cropping_aspect_ratios: ['1:1'], type: 'file' } if (category && category != 'all') postData = Object.assign(postData, { category }) const resp = await AliHttp.Post(url, postData, user_id, '') try { if (AliHttp.IsSuccess(resp.code)) { next_marker = resp.body.next_marker items = items.concat(resp.body.items) } else if (resp.code == 404) { next_marker = '' break } else if (resp.body && resp.body.code) { items.length = 0 next_marker = resp.body.code message.warning('列出文件出错 ' + resp.body.code, 2) return false } else { DebugLog.mSaveWarning('ApiWalkDirFileList err=' + (resp.code || '')) } } catch (err: any) { DebugLog.mSaveDanger('ApiWalkDirFileList' + file_id, err) break } } while (next_marker) return items } export function DeleteFromSameData(PanData: IScanDriverModel, idList: string[]) { const entries = PanData.SameDirMap.entries() for (let i = 0, maxi = PanData.SameDirMap.size; i < maxi && idList.length > 0; i++) { const value = entries.next().value const children = value[1] as FileData[] const saveList: FileData[] = [] for (let j = 0, maxj = children.length; j < maxj; j++) { const key = children[j].file_id if (idList.includes(key)) { idList = idList.filter((t) => t != key) } else { saveList.push(children[j]) } } if (children.length != saveList.length) PanData.SameDirMap.set(value[0], saveList) } } ================================================ FILE: src/renderer/rss/rssusercopy/RssUserCopy.vue ================================================ ================================================ FILE: src/renderer/rss/rssusercopy/usercopy.ts ================================================ import { IAliGetFileModel } from '../../aliapi/alimodels' import AliFile from '../../aliapi/file' import message from '../../utils/message' import { Ref } from 'vue' import { fileiconfn, foldericonfn } from '../ScanDAL' import AliTrash from '../../aliapi/trash' export interface ICopyTreeInfo { user_id: string drive_id: string dirID: string dirName: string parentID: string loading: boolean onlyDir: boolean } export function NewCopyTreeInfo(onlyDir: boolean) { const info: ICopyTreeInfo = { user_id: '', drive_id: '', dirID: '', dirName: '', parentID: '', loading: false, onlyDir: onlyDir } return info } export interface ICopyTreeNode { key: string title: string icon: any download_url: string children?: ICopyTreeNode[] } export async function LoadDir(dirID: string, DirData: ICopyTreeInfo, treeData: Ref) { DirData.loading = true if (!dirID) dirID = 'root' if (dirID.startsWith('dir_')) dirID = dirID.substring('dir_'.length) if (dirID == 'root') { DirData.dirID = 'root' DirData.dirName = '根目录' DirData.parentID = 'root' } else { const getdir = await AliFile.ApiFileInfo(DirData.user_id, DirData.drive_id, dirID) if (getdir) { DirData.dirID = getdir.file_id DirData.dirName = getdir.name DirData.parentID = getdir.parent_file_id } else { message.error('读取文件夹信息失败') } } const resp = await AliTrash.ApiDirFileListNoLock(DirData.user_id, DirData.drive_id, dirID, '', '', DirData.onlyDir ? 'folder' : '') DirData.loading = false const list: ICopyTreeNode[] = [] const items = resp.items let item: IAliGetFileModel for (let i = 0, maxi = items.length; i < maxi; i++) { item = items[i] list.push({ key: (item.isDir ? 'dir_' : 'file_') + item.file_id, title: item.name, icon: item.isDir ? foldericonfn : fileiconfn, download_url: '' // item.download_url } as ICopyTreeNode) } treeData.value = list } export async function LoadCopy(LeftData: ICopyTreeInfo, LeftCheckedKeys: string[], LeftTreeData: ICopyTreeNode[], CopyTreeLoading: Ref, treeData: ICopyTreeNode[]) { CopyTreeLoading.value = true treeData.length = 0 for (let i = 0, maxi = LeftTreeData.length; i < maxi && LeftCheckedKeys.length > 0; i++) { const node = LeftTreeData[i] if (LeftCheckedKeys.includes(node.key)) { const key = node.key LeftCheckedKeys = LeftCheckedKeys.filter((t) => t != key) treeData.push({ ...node, children: [] } as ICopyTreeNode) } } for (let i = 0, maxi = treeData.length; i < maxi; i++) { const node = treeData[i] if (node.key.startsWith('dir_')) { await LoadChildDir(LeftData.user_id, LeftData.drive_id, node) } } CopyTreeLoading.value = false } async function LoadChildDir(user_id: string, drive_id: string, node: ICopyTreeNode) { const dirID = node.key.substring('dir_'.length) const resp = await AliTrash.ApiDirFileListNoLock(user_id, drive_id, dirID, '', '', 'folder') const list: ICopyTreeNode[] = [] const items = resp.items let item: IAliGetFileModel for (let i = 0, maxi = items.length; i < maxi; i++) { item = items[i] list.push({ key: (item.isDir ? 'dir_' : 'file_') + item.file_id, title: item.name, icon: item.isDir ? foldericonfn : fileiconfn, download_url: '', // item.download_url, children: [] } as ICopyTreeNode) } node.children = list for (let i = 0, maxi = list.length; i < maxi; i++) { const nd = list[i] if (nd.key.startsWith('dir_')) { await LoadChildDir(user_id, drive_id, nd) } } } export function GetTreeNodes(treeData: ICopyTreeNode[], treeDataMap: Map) { const data: ICopyTreeNode[] = [] for (let i = 0, maxi = treeData.length; i < maxi; i++) { const item = treeData[i] data.push({ key: item.key, title: item.title, icon: item.icon, download_url: item.download_url, children: GetTreeNodes(item.children!, treeDataMap) } as ICopyTreeNode) } data.sort((a, b) => a.title!.localeCompare(b.title!)) data.map((a) => { treeDataMap.set(a.key as string, a) return true }) return data } ================================================ FILE: src/renderer/rss/rssxima/RssXiMa.vue ================================================ ================================================ FILE: src/renderer/rss/rssxima/xima.ts ================================================ import { FileSystemErrorMessage } from '../../utils/filehelper' import DebugLog from '../../utils/debuglog' import message from '../../utils/message' const { Buffer } = window.require('buffer') const fspromises = window.require('fs/promises') const path = window.require('path') export async function DoXiMa(dirPath: string, breakSmall: boolean, matchExtList: string[]): Promise { const fileList: string[] = [] await GetAllFiles(dirPath, breakSmall, fileList) if (fileList.length == 0) { message.error('选择的文件夹下找不到任何文件') return 0 } else { let rand = Date.now() const rand1 = rand % 256 rand = rand / 128 const rand2 = Math.floor(rand % 256) let rand3 = Math.floor(Math.random() * 255) let runCount = 0 for (let i = 0, maxi = fileList.length; i < maxi; i++) { const file = fileList[i].toLowerCase().trimEnd() if (matchExtList.length > 0) { let find = false for (let j = 0; j < matchExtList.length; j++) { if (file.endsWith(matchExtList[j])) { find = true break } } if (find == false) continue } try { const rand4 = (i % 255) + 1 if (rand4 == 200) rand3 = Math.floor(Math.random() * 255) const buff = Buffer.from([0, rand1, rand2, rand3, rand4]) fspromises.appendFile(fileList[i], buff).catch(() => {}) runCount++ } catch (err: any) { DebugLog.mSaveDanger('XM appendFile' + (err.message || '') + fileList[i]) } } return runCount } } async function GetAllFiles(dir: string, breakSmall: boolean, fileList: string[]) { if (dir.endsWith(path.sep) == false) dir = dir + path.sep try { const childfiles = await fspromises.readdir(dir).catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('XMGetAllFiles文件失败:' + dir, err) message.error('跳过文件夹:' + err + ' ' + dir) return [] }) let allTask: Promise[] = [] const dirList: string[] = [] for (let i = 0, maxi = childfiles.length; i < maxi; i++) { const name = childfiles[i] as string if (name.startsWith('.')) continue if (name.startsWith('#')) continue const item = dir + name allTask.push( fspromises .lstat(item) .then((stat: any) => { if (stat.isDirectory()) dirList.push(item) else if (stat.isSymbolicLink()) { // donothing } else if (stat.isFile()) { if (breakSmall == false || stat.size > 5 * 1024 * 1024) fileList.push(item) } }) .catch() ) if (allTask.length > 10) { await Promise.all(allTask).catch(() => {}) allTask = [] } } if (allTask.length > 0) { await Promise.all(allTask).catch(() => {}) allTask = [] } for (let i = 0, maxi = dirList.length; i < maxi; i++) { await GetAllFiles(dirList[i], breakSmall, fileList) } } catch (err: any) { DebugLog.mSaveDanger('GetAllFiles' + (err.message || '')) } return true } ================================================ FILE: src/renderer/setting/SettingDebug.vue ================================================ ================================================ FILE: src/renderer/setting/SettingDown.vue ================================================ ================================================ FILE: src/renderer/setting/SettingLog.vue ================================================ ================================================ FILE: src/renderer/setting/SettingPan.vue ================================================ ================================================ FILE: src/renderer/setting/SettingPlay.vue ================================================ ================================================ FILE: src/renderer/setting/SettingProxy.vue ================================================ ================================================ FILE: src/renderer/setting/SettingUI.vue ================================================ ================================================ FILE: src/renderer/setting/SettingUpload.vue ================================================ ================================================ FILE: src/renderer/setting/ShutDown.vue ================================================ ================================================ FILE: src/renderer/setting/index.vue ================================================ ================================================ FILE: src/renderer/setting/settingstore.ts ================================================ import { defineStore } from 'pinia' import DebugLog from '../utils/debuglog' import { getResourcesPath } from '../utils/electronhelper' import { useAppStore } from '../store' import PanDAL from '../pan/pandal' const { existsSync, readFileSync, writeFileSync } = window.require('fs') declare type ProxyType = 'none' | 'http' | 'https' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' export interface SettingState { uiTheme: string uiImageMode: string uiVideoMode: string uiVideoPlayer: string uiVideoPlayerPath: string uiAutoColorVideo: boolean uiAutoPlaycursorVideo: boolean uiShowPanPath: boolean uiShowPanMedia: boolean uiExitOnClose: boolean uiFolderSize: boolean uiFileOrderDuli: string uiTimeFolderFormate: string uiTimeFolderIndex: number uiShareDays: string uiSharePassword: string uiShareFormate: string uiXBTNumber: number uiXBTWidth: number uiFileListOrder: string uiFileListMode: string uiFileColorArray: { key: string; title: string }[] downSavePath: string downSavePathDefault: boolean downSavePathFull: boolean downSaveBreakWeiGui: boolean uploadFileMax: number downFileMax: number downThreadMax: number uploadGlobalSpeed: number uploadGlobalSpeedM: string downGlobalSpeed: number downGlobalSpeedM: string downAutoShutDown: number downSaveShowPro: boolean downSmallFileFirst: boolean downUploadBreakFile: boolean downUploadWhatExist: string downIngoredList: string[] downFinishAudio: boolean downAutoStart: boolean debugCacheSize: string debugFileListMax: number debugFavorListMax: number debugDowningListMax: number debugDownedListMax: number debugFolderSizeCacheHour: number yinsiLinkPassword: boolean yinsiZipPassword: boolean proxyUseProxy: boolean proxyType: ProxyType proxyHost: string proxyPort: number proxyUserName: string proxyPassword: string } const setting: SettingState = { uiTheme: 'system', uiImageMode: 'fill', uiVideoMode: 'mpv', uiVideoPlayer: 'mpv', uiVideoPlayerPath: '', uiAutoColorVideo: true, uiAutoPlaycursorVideo: true, uiShowPanPath: true, uiShowPanMedia: false, uiExitOnClose: false, uiFolderSize: true, uiFileOrderDuli: 'null', uiTimeFolderFormate: 'yyyy-MM-dd HH-mm-ss', uiTimeFolderIndex: 1, uiShareDays: 'always', uiSharePassword: 'random', uiShareFormate: '「NAME」URL 提取码: PWD\n点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。', uiXBTNumber: 36, uiXBTWidth: 960, uiFileListOrder: 'updated_at desc', uiFileListMode: 'list', uiFileColorArray: [ { key: '#df5659', title: '鹅冠红' }, { key: '#9c27b0', title: '兰花紫' }, { key: '#42a5f5', title: '晴空蓝' }, { key: '#00bc99', title: '竹叶青' }, { key: '#4caf50', title: '宝石绿' }, { key: '#ff9800', title: '金盏黄' } ], downSavePath: '', downSavePathDefault: true, downSavePathFull: true, downSaveBreakWeiGui: true, uploadFileMax: 5, downFileMax: 5, downThreadMax: 4, uploadGlobalSpeed: 0, uploadGlobalSpeedM: 'MB', downGlobalSpeed: 0, downGlobalSpeedM: 'MB', downAutoShutDown: 0, downSaveShowPro: true, downSmallFileFirst: false, downUploadBreakFile: false, downUploadWhatExist: 'refuse', downIngoredList: ['thumbs.db', 'desktop.ini', '.ds_store', '.td', '~', '.downloading'], downFinishAudio: true, downAutoStart: true, debugCacheSize: '', debugFileListMax: 3000, debugFavorListMax: 1000, debugDowningListMax: 1000, debugDownedListMax: 5000, debugFolderSizeCacheHour: 72, yinsiLinkPassword: false, yinsiZipPassword: false, proxyUseProxy: false, proxyType: 'none', proxyHost: '', proxyPort: 0, proxyUserName: '', proxyPassword: '' } function _loadSetting(val: any) { setting.uiTheme = defaultValue(val.uiTheme, ['system', 'light', 'dark']) console.log('_loadSetting', val) setting.uiImageMode = defaultValue(val.uiImageMode, ['fill', 'width', 'web']) setting.uiVideoMode = defaultValue(val.uiVideoMode, ['mpv', 'online']) setting.uiVideoPlayer = defaultValue(val.uiVideoPlayer, ['mpv', 'other', 'web']) setting.uiVideoPlayerPath = defaultString(val.uiVideoPlayerPath, '') setting.uiAutoColorVideo = defaultBool(val.uiAutoColorVideo, true) setting.uiAutoPlaycursorVideo = defaultBool(val.uiAutoPlaycursorVideo, true) setting.uiShowPanPath = defaultBool(val.uiShowPanPath, true) setting.uiShowPanMedia = defaultBool(val.uiShowPanMedia, false) setting.uiExitOnClose = defaultBool(val.uiExitOnClose, false) setting.uiFolderSize = defaultBool(val.uiFolderSize, true) setting.uiFileOrderDuli = defaultString(val.uiFileOrderDuli, 'null') setting.uiTimeFolderFormate = defaultString(val.uiTimeFolderFormate, 'yyyy-MM-dd HH-mm-ss').replace('mm-dd', 'MM-dd').replace('HH-MM', 'HH-mm') setting.uiTimeFolderIndex = defaultNumber(val.uiTimeFolderIndex, 1) setting.uiShareDays = defaultValue(val.uiShareDays, ['always', 'week', 'month']) setting.uiSharePassword = defaultValue(val.uiSharePassword, ['random', 'last', 'nopassword']) setting.uiShareFormate = defaultString(val.uiShareFormate, 'NAME URL 提取码:PWD') setting.uiXBTNumber = defaultValue(val.uiXBTNumber, [36, 24, 36, 48, 60, 72]) setting.uiXBTWidth = defaultValue(val.uiXBTWidth, [960, 720, 960, 1080, 1280]) setting.uiFileListOrder = defaultValue(val.uiFileListOrder, ['updated_at desc', 'name asc', 'name desc', 'updated_at asc', 'updated_at desc', 'size asc', 'size desc']) setting.uiFileListMode = defaultValue(val.uiFileListMode, ['list', 'image', 'bigimage']) if (val.uiFileColorArray && val.uiFileColorArray.length >= 6) setting.uiFileColorArray = val.uiFileColorArray setting.downSavePath = defaultString(val.downSavePath, '') setting.downSavePathDefault = defaultBool(val.downSavePathDefault, true) setting.downSavePathFull = defaultBool(val.downSavePathFull, true) setting.downSaveBreakWeiGui = defaultBool(val.downSaveBreakWeiGui, true) setting.uploadFileMax = defaultValue(val.uploadFileMax, [5, 1, 3, 5, 10, 20, 30, 50]) setting.downFileMax = defaultValue(val.downFileMax, [5, 1, 3, 5, 10, 20, 30]) setting.downThreadMax = defaultValue(val.downThreadMax, [4, 1, 2, 4, 8, 16]) setting.uploadGlobalSpeed = defaultNumberSub(val.uploadGlobalSpeed, 0, 0, 999) setting.uploadGlobalSpeedM = defaultValue(val.uploadGlobalSpeedM, ['MB', 'KB']) setting.downGlobalSpeed = defaultNumberSub(val.downGlobalSpeed, 0, 0, 999) setting.downGlobalSpeedM = defaultValue(val.downGlobalSpeedM, ['MB', 'KB']) setting.downAutoShutDown = 0 setting.downSaveShowPro = defaultBool(val.downSaveShowPro, true) setting.downSmallFileFirst = defaultBool(val.downSmallFileFirst, false) setting.downUploadBreakFile = defaultBool(val.downUploadBreakFile, false) setting.downUploadWhatExist = defaultValue(val.downUploadWhatExist, ['ignore', 'overwrite', 'auto_rename', 'refuse']) setting.downIngoredList = val.downIngoredList && val.downIngoredList.length > 0 ? val.downIngoredList : ['thumbs.db', 'desktop.ini', '.ds_store', '.td', '~', '.downloading'] setting.downFinishAudio = defaultBool(val.downFinishAudio, true) setting.downAutoStart = defaultBool(val.downAutoStart, true) setting.debugCacheSize = defaultString(val.debugCacheSize, '') setting.debugFileListMax = defaultNumberSub(val.debugFileListMax, 3000, 3000, 10000) setting.debugFavorListMax = defaultNumberSub(val.debugFavorListMax, 1000, 100, 3000) setting.debugDowningListMax = 1000 setting.debugDownedListMax = defaultNumberSub(val.debugDownedListMax, 5000, 1000, 50000) setting.debugFolderSizeCacheHour = defaultValue(val.debugFolderSizeCacheHour, [72, 2, 8, 24, 48, 72]) setting.yinsiLinkPassword = defaultBool(val.yinsiLinkPassword, false) setting.yinsiZipPassword = defaultBool(val.yinsiZipPassword, false) setting.proxyUseProxy = defaultBool(val.proxyUseProxy, false) setting.proxyType = defaultValue(val.proxyType, ['none', 'http', 'https', 'socks5', 'socks5h']) setting.proxyHost = defaultString(val.proxyHost, '') setting.proxyPort = defaultNumber(val.proxyPort, 0) setting.proxyUserName = defaultString(val.proxyUserName, '') setting.proxyPassword = defaultString(val.proxyPassword, '') } let settingstr = '' function LoadSetting() { try { const settingConfig = getResourcesPath('setting.config') if (settingConfig && existsSync(settingConfig)) { settingstr = readFileSync(settingConfig, 'utf-8') const val = JSON.parse(settingstr) _loadSetting(val) useAppStore().toggleTheme(setting.uiTheme) } else { SaveSetting() } } catch { SaveSetting() } return setting } function defaultValue(val: any, check: any[]) { if (val && check.includes(val)) return val return check[0] } function defaultString(val: any, check: string) { if (val && typeof val == 'string') return val return check } function defaultBool(val: any, check: boolean) { if (typeof val == 'boolean') return val return check } function defaultNumber(val: any, check: number) { if (typeof val == 'number') return val return check } function defaultNumberSub(val: any, check: number, min: number, max: number) { if (typeof val == 'number') { if (val < min) return min if (val > max) return max return val } return check } function SaveSetting() { try { const saveStr = JSON.stringify(setting) if (saveStr != settingstr) { const settingConfig = getResourcesPath('setting.config') writeFileSync(settingConfig, saveStr, 'utf-8') settingstr = saveStr } } catch (err: any) { DebugLog.mSaveDanger('SaveSettingToJson', err) } } const useSettingStore = defineStore('setting', { state: (): SettingState => LoadSetting(), getters: {}, actions: { updateStore(partial: Partial) { if (partial.uiTimeFolderFormate) partial.uiTimeFolderFormate = partial.uiTimeFolderFormate.replace('mm-dd', 'MM-dd').replace('HH-MM', 'HH-mm') this.$patch(partial) if (Object.hasOwn(partial, 'proxyUseProxy')) { this.WebSetProxy() } SaveSetting() window.WinMsgToUpload({ cmd: 'SettingRefresh' }) window.WinMsgToDownload({ cmd: 'SettingRefresh' }) useAppStore().toggleTheme(setting.uiTheme) if (Object.hasOwn(partial, 'uiShowPanMedia') || Object.hasOwn(partial, 'uiFolderSize') || Object.hasOwn(partial, 'uiFileOrderDuli')) { PanDAL.aReLoadOneDirToShow('', 'refresh', false) } }, updateFileColor(key: string, title: string) { if (!key) return const arr = setting.uiFileColorArray.concat() for (let i = 0; i < arr.length; i++) { if (arr[i].key == key) arr[i].title = title } this.$patch({ uiFileColorArray: arr }) SaveSetting() }, getProxy() { if (!this.proxyType || this.proxyType == 'none') return undefined if (!this.proxyHost) return undefined if (this.proxyType.startsWith('http')) { const auth = this.proxyUserName && this.proxyPassword ? this.proxyUserName + ':' + this.proxyPassword : '' const proxy = this.proxyType + '://' + (auth ? auth + '@' : '') + this.proxyHost + ':' + this.proxyPort return proxy } return { hostname: this.proxyHost, port: this.proxyPort, protocol: this.proxyType, username: this.proxyUserName, password: this.proxyPassword } }, WebSetProxy() { let proxy = '' if (this.proxyUseProxy) { if (this.proxyType && this.proxyType !== 'none' && this.proxyHost && this.proxyPort) { const auth = this.proxyUserName && this.proxyPassword ? this.proxyUserName + ':' + this.proxyPassword : '' proxy = this.proxyType + '://' + (auth ? auth + '@' : '') + this.proxyHost + ':' + this.proxyPort } } window.WebSetProxy({ proxyUrl: proxy }) } } }) export default useSettingStore ================================================ FILE: src/renderer/share/following/FollowingDAL.ts ================================================ import AliFollowing from '../../aliapi/following' import { IAliOtherFollowingModel } from '../../aliapi/alimodels' import message from '../../utils/message' import useOtherFollowingStore from './OtherFollowingStore' import useMyFollowingStore from './MyFollowingStore' import { throttle } from '../../utils/debounce' export default class FollowingDAL { static async aReloadOtherFollowingList(user_id: string, force: boolean): Promise { if (!user_id) return const otherfollowingStore = useOtherFollowingStore() if (!force && otherfollowingStore.TuiJianLoaded) return if (otherfollowingStore.TuiJianLoading == true) return otherfollowingStore.TuiJianLoading = true const resp = await AliFollowing.ApiOtherFollowingListAll(user_id) otherfollowingStore.aSaveOtherFollowingList('官方推荐', 'arcoblue', resp.items) const classed = await AliFollowing.ApiOtherFollowingClassListAll() const map = new Map() for (let i = 0, maxi = classed.length; i < maxi; i++) { const item = classed[i] if (!item.class_name) continue if (map.has(item.class_name) == false) map.set(item.class_name, []) const list = map.get(item.class_name)! const add: IAliOtherFollowingModel = { avatar: item.avatar || '', phone: '', is_following: false, description: item.description, user_id: item.user_id, nick_name: item.nick_name, follower_count: item.follower_count } list.push(add) } const entries = map.entries() for (let i = 0, maxi = map.size; i < maxi; i++) { const entry = entries.next().value if (entry[1].length > 0) otherfollowingStore.aSaveOtherFollowingList(entry[0] + ' (' + entry[1].length + ')', 'orangered', entry[1]) } otherfollowingStore.TuiJianLoading = false otherfollowingStore.TuiJianLoaded = true } static async aReloadMyFollowing(user_id: string, force: boolean): Promise { if (!user_id) return const myfollowingStore = useMyFollowingStore() if (!force && myfollowingStore.ListDataRaw.length > 0) return if (myfollowingStore.ListLoading == true) return myfollowingStore.ListLoading = true const resp = await AliFollowing.ApiMyFollowingListAll(user_id) myfollowingStore.aLoadListData(resp.items) myfollowingStore.ListLoading = false } static onRFollowing = throttle((user_id: string) => { FollowingDAL.aReloadMyFollowing(user_id, true) }, 3000) static async aSetFollowing(user_id: string, followingid: string, isFollowing: boolean): Promise { await AliFollowing.ApiSetFollowing(user_id, followingid, isFollowing, true) useMyFollowingStore().mSetFollowing(followingid, isFollowing) FollowingDAL.onRFollowing(user_id) } static async aSetFollowingBatch(user_id: string, idList: string[], isFollowing: boolean): Promise { let followingid = '' for (let i = 0, maxi = idList.length; i < maxi; i++) { followingid = idList[i] message.info((isFollowing ? '' : '取消') + '订阅中( ' + i + ' / ' + maxi + ' )', 3, 'aSetFollowingBatch' + isFollowing) await AliFollowing.ApiSetFollowing(user_id, followingid, isFollowing, false) useMyFollowingStore().mSetFollowing(followingid, isFollowing) } message.success((isFollowing ? '订阅' : '取消订阅') + ' 成功', 3, 'aSetFollowingBatch' + isFollowing) } static aSetFollowingText(user_id: string, text: string, isFollowing: boolean): Promise { const idList: string[] = [] text = text.replaceAll('/drive/subscription', '') let index = text.indexOf('aliyundrive.com/u/') while (index > 0) { let id = text.substring(index + 'aliyundrive.com/u/'.length) if (id.length > 50) id = id.substring(0, 50) if (id.indexOf('/') > 0) id = id.substring(0, id.indexOf('/')) if (id.indexOf('#') > 0) id = id.substring(0, id.indexOf('#')) if (id.indexOf('?') > 0) id = id.substring(0, id.indexOf('?')) if (id.indexOf('&') > 0) id = id.substring(0, id.indexOf('&')) id = id.trim() if (id.length == 32 && /^[A-Za-z0-9]+$/.test(id) && idList.includes(id) == false) idList.push(id) text = text.substring(index + 'aliyundrive.com/u/'.length) index = text.indexOf('aliyundrive.com/u/') } if (idList.length == 0) { message.error('解析订阅链接失败,格式错误') return Promise.resolve(false) } return FollowingDAL.aSetFollowingBatch(user_id, idList, isFollowing).then(() => true) } } ================================================ FILE: src/renderer/share/following/MyFollowingRight.vue ================================================ ================================================ FILE: src/renderer/share/following/MyFollowingStore.ts ================================================ import fuzzysort from 'fuzzysort' import { defineStore } from 'pinia' import { IAliMyFollowingModel } from '../../aliapi/alimodels' import { GetSelectedList, GetFocusNext, SelectAll, MouseSelectOne, KeyboardSelectOne } from '../../utils/selecthelper' import { HanToPin } from '../../utils/utils' type Item = IAliMyFollowingModel export interface MyFollowingState { ListLoading: boolean ListDataRaw: Item[] ListDataShow: Item[] ListSelected: Set ListOrderKey: string ListFocusKey: string ListSelectKey: string ListSearchKey: string FollowingKeys: Set } type State = MyFollowingState const KEY = 'user_id' const useMyFollowingStore = defineStore('myfollowing', { state: (): State => ({ ListLoading: false, ListDataRaw: [], ListDataShow: [], ListSelected: new Set(), ListOrderKey: 'time desc', ListFocusKey: '', ListSelectKey: '', ListSearchKey: '', FollowingKeys: new Set() }), getters: { ListDataCount(state: State): number { return state.ListDataShow.length }, IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length } }, actions: { aLoadListData(list: Item[]) { list.sort((a, b) => b.latest_messages[0].created - a.latest_messages[0].created) let item: Item for (let i = 0, maxi = list.length; i < maxi; i++) { item = list[i] item.SearchName = HanToPin(item.nick_name) } this.ListDataRaw = list const oldSelected = this.ListSelected const newSelected = new Set() const map = new Set() let key = '' let findFocusKey = false let findSelectKey = false let listFocusKey = this.ListFocusKey let listSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == listFocusKey) findFocusKey = true if (key == listSelectKey) findSelectKey = true map.add(key) } if (!findFocusKey) listFocusKey = '' if (!findSelectKey) listSelectKey = '' this.$patch({ FollowingKeys: map, ListSelected: newSelected, ListFocusKey: listFocusKey, ListSelectKey: listSelectKey, ListSearchKey: '' }) this.mRefreshListDataShow(true) }, mSearchListData(value: string) { this.$patch({ ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '', ListSearchKey: value }) this.mRefreshListDataShow(true) }, mSetFollowing(followingid: string, isFollowing: boolean) { if (isFollowing) this.FollowingKeys.add(followingid) else if (this.FollowingKeys.has(followingid)) this.FollowingKeys.delete(followingid) if (isFollowing) { } else { const listNew: Item[] = [] const listOld = this.ListDataRaw for (let i = 0, maxi = listOld.length; i < maxi; i++) { if (listOld[i].user_id !== followingid) { listNew.push(listOld[i]) } } if (listNew.length != listOld.length) { this.ListDataRaw = listNew this.mRefreshListDataShow(true) } if (this.ListSelected.has(followingid)) this.ListSelected.delete(followingid) } }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow return } if (this.ListSearchKey) { const searchList: Item[] = [] const results = fuzzysort.go(this.ListSearchKey, this.ListDataRaw, { threshold: -200000, keys: ['nick_name', 'SearchName', 'description'], scoreFn: (a) => Math.max(a[0] ? a[0].score : -200000, a[1] ? a[1].score : -200000, a[2] ? a[2].score - 100 : -200000) }) for (let i = 0, maxi = results.length; i < maxi; i++) { if (results[i].score > -200000) searchList.push(results[i].obj) } Object.freeze(searchList) this.ListDataShow = searchList } else { const listDataShow = this.ListDataRaw.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = '' for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: '', ListSelectKey: '' }) this.mRefreshListDataShow(false) }, mMouseSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: string) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (!this.ListFocusKey && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, '') } } }) export default useMyFollowingStore ================================================ FILE: src/renderer/share/following/OtherFollowingRight.vue ================================================ ================================================ FILE: src/renderer/share/following/OtherFollowingStore.ts ================================================ import { defineStore } from 'pinia' import { IAliOtherFollowingModel } from '../../aliapi/alimodels' export declare interface FollowingState { TuiJianLoading: boolean TuiJianLoaded: boolean TuiJianList: { key: string; color: string; list: IAliOtherFollowingModel[] }[] } const useFollowingStore = defineStore('following', { state: (): FollowingState => ({ TuiJianLoading: false, TuiJianLoaded: false, TuiJianList: [{ key: '官方推荐', color: 'arcoblue', list: [] }] }), getters: {}, actions: { aSaveOtherFollowingList(key: string, color: string, list: IAliOtherFollowingModel[]) { list.sort((a, b) => b.follower_count - a.follower_count) for (let i = 0, maxi = this.TuiJianList.length; i < maxi; i++) { if (this.TuiJianList[i].key == key) { this.TuiJianList[i].color = color this.TuiJianList[i].list = list return } } this.TuiJianList.push({ key, color, list }) } } }) export default useFollowingStore ================================================ FILE: src/renderer/share/index.vue ================================================ ================================================ FILE: src/renderer/share/share/EditShareLinkModal.vue ================================================ ================================================ FILE: src/renderer/share/share/MyShareRight.vue ================================================ ================================================ FILE: src/renderer/share/share/MyShareStore.ts ================================================ import fuzzysort from 'fuzzysort' import { defineStore } from 'pinia' import { IAliShareItem } from '../../aliapi/alimodels' import { GetSelectedList, GetFocusNext, SelectAll, MouseSelectOne, KeyboardSelectOne } from '../../utils/selecthelper' import { HanToPin } from '../../utils/utils' import { UpdateShareModel } from '../../aliapi/share' import { humanExpiration } from '../../utils/format' type Item = IAliShareItem export interface MyShareState { ListLoading: boolean ListDataRaw: Item[] ListDataShow: Item[] ListSelected: Set ListOrderKey: string ListFocusKey: string ListSelectKey: string ListSearchKey: string } type State = MyShareState const KEY = 'share_id' const useMyShareStore = defineStore('myshare', { state: (): State => ({ ListLoading: false, ListDataRaw: [], ListDataShow: [], ListSelected: new Set(), ListOrderKey: 'time', ListFocusKey: '', ListSelectKey: '', ListSearchKey: '' }), getters: { ListDataCount(state: State): number { return state.ListDataShow.length }, IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length }, ListStats(state: State) { const stats = { preview: 0, download: 0, save: 0, previewMax: 0, forbidden: 0, expired: 0, expir2day: 0 } const list = state.ListDataShow let item: Item const day = new Date().getTime() for (let i = 0, maxi = list.length; i < maxi; i++) { item = list[i] stats.preview += item.preview_count stats.previewMax = Math.max(stats.previewMax, item.preview_count) stats.download += item.download_count stats.save += item.save_count if (item.status == 'forbidden') stats.forbidden++ if (item.expired) stats.expired++ else if (new Date(item.expiration).getTime() - day < 2 * 24 * 60 * 60 * 1000) stats.expir2day++ } return stats } }, actions: { aLoadListData(list: Item[]) { let item: Item for (let i = 0, maxi = list.length; i < maxi; i++) { item = list[i] item.description = HanToPin(item.share_name) } this.ListDataRaw = this.mGetOrder(this.ListOrderKey, list) const oldSelected = this.ListSelected const newSelected = new Set() let key = '' let findFocusKey = false let findSelectKey = false let ListFocusKey = this.ListFocusKey let ListSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == ListFocusKey) findFocusKey = true if (key == ListSelectKey) findSelectKey = true } if (!findFocusKey) ListFocusKey = '' if (!findSelectKey) ListSelectKey = '' this.$patch({ ListSelected: newSelected, ListFocusKey: ListFocusKey, ListSelectKey: ListSelectKey, ListSearchKey: '' }) this.mRefreshListDataShow(true) }, mSearchListData(value: string) { this.$patch({ ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '', ListSearchKey: value }) this.mRefreshListDataShow(true) }, mOrderListData(value: string) { this.$patch({ ListOrderKey: value, ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '' }) this.ListDataRaw = this.mGetOrder(value, this.ListDataRaw) this.mRefreshListDataShow(true) }, mGetOrder(order: string, list: Item[]) { if (order == 'time') list.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()) if (order == 'preview') list.sort((a, b) => b.preview_count - a.preview_count) if (order == 'download') list.sort((a, b) => b.download_count - a.download_count) if (order == 'save') list.sort((a, b) => b.save_count - a.save_count) if (order == 'state') list.sort((a, b) => { const s = a.share_msg.localeCompare(b.share_msg) if (s == 0) { if (a.first_file && b.first_file) return 0 if (a.first_file) return 1 if (b.first_file) return -1 return 0 } return s }) return list }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const ListDataShow = this.ListDataShow.concat() Object.freeze(ListDataShow) this.ListDataShow = ListDataShow return } if (this.ListSearchKey) { const searchList: Item[] = [] const results = fuzzysort.go(this.ListSearchKey, this.ListDataRaw, { threshold: -200000, keys: ['share_name', 'description'], scoreFn: (a) => Math.max(a[0] ? a[0].score : -200000, a[1] ? a[1].score : -200000) }) for (let i = 0, maxi = results.length; i < maxi; i++) { if (results[i].score > -200000) searchList.push(results[i].obj as IAliShareItem) } Object.freeze(searchList) this.ListDataShow = searchList } else { const listDataShow = this.ListDataRaw.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = '' for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: '', ListSelectKey: '' }) this.mRefreshListDataShow(false) }, mMouseSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: string) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (!this.ListFocusKey && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, '') }, mDeleteFiles(share_idList: string[]) { const fileMap = new Set(share_idList) const listDataRaw = this.ListDataRaw const newDataList: Item[] = [] for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (!fileMap.has(item.share_id)) { newDataList.push(item) } } if (this.ListDataRaw.length != newDataList.length) { this.ListDataRaw = newDataList this.mRefreshListDataShow(true) } }, mUpdateShare(success: UpdateShareModel[]) { const listDataRaw = this.ListDataRaw const timeNow = new Date().getTime() for (let j = 0, jmax = success.length; j < jmax; j++) { const info = success[j] for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (item.share_id == info.share_id) { item.share_pwd = info.share_pwd item.share_name = info.share_name item.description = HanToPin(info.share_name) item.expiration = info.expiration item.share_msg = humanExpiration(info.expiration, timeNow) item.expired = item.share_msg == '过期失效' break } } } this.mRefreshListDataShow(false) } } }) export default useMyShareStore ================================================ FILE: src/renderer/share/share/OtherShareRight.vue ================================================ ================================================ FILE: src/renderer/share/share/OtherShareStore.ts ================================================ import fuzzysort from 'fuzzysort' import { defineStore } from 'pinia' import { GetSelectedList, GetFocusNext, SelectAll, MouseSelectOne, KeyboardSelectOne } from '../../utils/selecthelper' import { HanToPin } from '../../utils/utils' export interface IOtherShareLinkModel { share_id: string share_name: string description: string share_pwd: string expiration: string expired: boolean share_msg: string created_at: string updated_at: string saved_at: string saved_time: number } type Item = IOtherShareLinkModel export interface OtherShareState { ListLoading: boolean ListDataRaw: Item[] ListDataShow: Item[] ListSelected: Set ListOrderKey: string ListFocusKey: string ListSelectKey: string ListSearchKey: string } type State = OtherShareState const KEY = 'share_id' const useOtherShareStore = defineStore('othershare', { state: (): State => ({ ListLoading: false, ListDataRaw: [], ListDataShow: [], ListSelected: new Set(), ListOrderKey: 'time', ListFocusKey: '', ListSelectKey: '', ListSearchKey: '' }), getters: { ListDataCount(state: State): number { return state.ListDataShow.length }, IsListSelected(state: State): boolean { return state.ListSelected.size > 0 }, ListSelectedCount(state: State): number { return state.ListSelected.size }, ListDataSelectCountInfo(state: State): string { return '已选中 ' + state.ListSelected.size + ' / ' + state.ListDataShow.length + ' 个' }, IsListSelectedAll(state: State): boolean { return state.ListSelected.size > 0 && state.ListSelected.size == state.ListDataShow.length } }, actions: { aLoadListData(list: Item[]) { let item: Item for (let i = 0, maxi = list.length; i < maxi; i++) { item = list[i] item.description = HanToPin(item.share_name) } this.ListDataRaw = this.mGetOrder(this.ListOrderKey, list) const oldSelected = this.ListSelected const newSelected = new Set() let key = '' let findFocusKey = false let findSelectKey = false let listFocusKey = this.ListFocusKey let listSelectKey = this.ListSelectKey for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][KEY] if (oldSelected.has(key)) newSelected.add(key) if (key == listFocusKey) findFocusKey = true if (key == listSelectKey) findSelectKey = true } if (!findFocusKey) listFocusKey = '' if (!findSelectKey) listSelectKey = '' this.$patch({ ListSelected: newSelected, ListFocusKey: listFocusKey, ListSelectKey: listSelectKey, ListSearchKey: '' }) this.mRefreshListDataShow(true) }, mSearchListData(value: string) { this.$patch({ ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '', ListSearchKey: value }) this.mRefreshListDataShow(true) }, mOrderListData(value: string) { this.$patch({ ListOrderKey: value, ListSelected: new Set(), ListFocusKey: '', ListSelectKey: '' }) this.ListDataRaw = this.mGetOrder(value, this.ListDataRaw) this.mRefreshListDataShow(true) }, mGetOrder(order: string, list: Item[]) { if (order == 'state') list.sort((a, b) => a.share_msg.localeCompare(b.share_msg)) if (order == 'update') list.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()) if (order == 'time') list.sort((a, b) => b.saved_time - a.saved_time) return list }, mRefreshListDataShow(refreshRaw: boolean) { if (!refreshRaw) { const listDataShow = this.ListDataShow.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow return } if (this.ListSearchKey) { const searchList: Item[] = [] const results = fuzzysort.go(this.ListSearchKey, this.ListDataRaw, { threshold: -200000, keys: ['share_name', 'description'], scoreFn: (a) => Math.max(a[0] ? a[0].score : -200000, a[1] ? a[1].score : -200000) }) for (let i = 0, maxi = results.length; i < maxi; i++) { if (results[i].score > -200000) searchList.push(results[i].obj) } Object.freeze(searchList) this.ListDataShow = searchList } else { const listDataShow = this.ListDataRaw.concat() Object.freeze(listDataShow) this.ListDataShow = listDataShow } const freezeList = this.ListDataShow const oldSelected = this.ListSelected const newSelected = new Set() let key = '' for (let i = 0, maxi = freezeList.length; i < maxi; i++) { key = freezeList[i][KEY] if (oldSelected.has(key)) newSelected.add(key) } this.ListSelected = newSelected }, mSelectAll() { this.$patch({ ListSelected: SelectAll(this.ListDataShow, KEY, this.ListSelected), ListFocusKey: '', ListSelectKey: '' }) this.mRefreshListDataShow(false) }, mMouseSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = MouseSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, mKeyboardSelect(key: string, Ctrl: boolean, Shift: boolean) { if (this.ListDataShow.length == 0) return const data = KeyboardSelectOne(this.ListDataShow, KEY, this.ListSelected, this.ListFocusKey, this.ListSelectKey, key, Ctrl, Shift, '') this.$patch({ ListSelected: data.selectedNew, ListFocusKey: data.focusLast, ListSelectKey: data.selectedLast }) this.mRefreshListDataShow(false) }, GetSelected() { return GetSelectedList(this.ListDataShow, KEY, this.ListSelected) }, GetSelectedFirst() { const list = GetSelectedList(this.ListDataShow, KEY, this.ListSelected) if (list.length > 0) return list[0] return undefined }, mSetFocus(key: string) { this.ListFocusKey = key this.mRefreshListDataShow(false) }, mGetFocus() { if (!this.ListFocusKey && this.ListDataShow.length > 0) return this.ListDataShow[0][KEY] return this.ListFocusKey }, mGetFocusNext(position: string) { return GetFocusNext(this.ListDataShow, KEY, this.ListFocusKey, position, '') }, mDeleteFiles(share_idList: string[]) { const fileMap = new Set(share_idList) const listDataRaw = this.ListDataRaw const newDataList: Item[] = [] for (let i = 0, maxi = listDataRaw.length; i < maxi; i++) { const item = listDataRaw[i] if (!fileMap.has(item.share_id)) { newDataList.push(item) } } this.ListDataRaw = newDataList this.mRefreshListDataShow(true) } } }) export default useOtherShareStore ================================================ FILE: src/renderer/share/share/ShareDAL.ts ================================================ import AliShareList from '../../aliapi/sharelist' import DB from '../../utils/db' import { humanDateTime, humanExpiration, Sleep } from '../../utils/format' import message from '../../utils/message' import useMyShareStore from './MyShareStore' import { useServerStore, IShareSiteModel } from '../../store' import useOtherShareStore, { IOtherShareLinkModel } from './OtherShareStore' import ServerHttp from '../../aliapi/server' import { IID, ParseShareIDList } from '../../utils/shareurl' import { RunBatch } from '../../aliapi/batch' import AliShare from '../../aliapi/share' import { IAliShareAnonymous } from '../../aliapi/alimodels' export default class ShareDAL { static async aLoadFromDB(): Promise { const shareSiteList = await DB.getValueObject('shareSiteList') useServerStore().mSaveShareSiteList(shareSiteList as IShareSiteModel[]) ShareDAL.aReloadOtherShare() } static async aReloadMyShare(user_id: string, force: boolean): Promise { if (!user_id) return const myshareStore = useMyShareStore() if (!force && myshareStore.ListDataRaw.length > 0) return if (myshareStore.ListLoading == true) return myshareStore.ListLoading = true const resp = await AliShareList.ApiShareListAll(user_id) myshareStore.aLoadListData(resp.items) myshareStore.ListLoading = false } static async aReloadMyShareUntilShareID(user_id: string, share_id: string): Promise { if (!user_id) return const find = await AliShareList.ApiShareListUntilShareID(user_id, share_id) if (find) ShareDAL.aReloadMyShare(user_id, true) } static async aReloadOtherShare(): Promise { const othershareStore = useOtherShareStore() if (othershareStore.ListLoading == true) return othershareStore.ListLoading = true const shareList = await DB.getOtherShareAll() const timeNow = new Date().getTime() for (let i = 0, maxi = shareList.length; i < maxi; i++) { const item = shareList[i] if (item.updated_at) { const updated_at = new Date(item.updated_at).getTime() item.updated_at = humanDateTime(updated_at) } if (item.expired == false) { if (item.share_msg != '已失效') item.share_msg = humanExpiration(item.expiration, timeNow) item.expired = item.share_msg == '过期失效' } } othershareStore.aLoadListData(shareList) await Sleep(1000) othershareStore.ListLoading = false } static async SaveOtherShare(password: string, info: IAliShareAnonymous, refresh: boolean) { let share = await DB.getOtherShare(info.shareinfo.share_id) if (!share) { share = { share_id: info.shareinfo.share_id, share_name: info.shareinfo.share_id, description: '', share_pwd: password, expiration: '0', expired: false, created_at: '', updated_at: new Date().toISOString(), saved_at: '', saved_time: Date.now(), share_msg: '' } } share.share_name = info.shareinfo.display_name || info.shareinfo.share_id share.created_at = info.shareinfo.created_at || new Date().toISOString() share.updated_at = info.shareinfo.updated_at || new Date().toISOString() share.saved_at = humanDateTime(share.saved_time) if (info.error != '') { share.share_msg = '已失效' share.expired = false } else { share.expiration = info.shareinfo.expiration share.share_msg = humanExpiration(share.expiration) share.expired = share.share_msg == '过期失效' } await DB.saveOtherShare(share) if (!refresh) return ShareDAL.aReloadOtherShare() } static async SaveOtherShareText(text: string): Promise { const idList = ParseShareIDList(text) if (idList.length == 0) { message.error('解析分享链接失败,格式错误') return false } const savefunc = (one: IID) => { return AliShare.ApiGetShareAnonymous(one.id).then((info) => { return ShareDAL.SaveOtherShare(one.pwd, info, false) }) } await RunBatch('解析分享链接', idList, 10, savefunc) ShareDAL.aReloadOtherShare() return true } static async SaveOtherShareRefresh(): Promise { const shareList = await DB.getOtherShareAll() if (shareList.length == 0) { return false } const savefunc = (share: IOtherShareLinkModel) => { return AliShare.ApiGetShareAnonymous(share.share_id).then((info) => { if (info.error != '') { share.expired = false share.share_msg = '已失效' } else { share.share_name = info.shareinfo.display_name share.expiration = info.shareinfo.expiration share.updated_at = info.shareinfo.updated_at share.share_msg = humanExpiration(share.expiration) share.expired = share.share_msg == '过期失效' } return DB.saveOtherShare(share) }) } await RunBatch('更新状态', shareList, 10, savefunc) ShareDAL.aReloadOtherShare() return true } static async DeleteOtherShare(selectKeys: string[]): Promise { if (selectKeys) await DB.deleteOtherShareBatch(selectKeys) useOtherShareStore().mDeleteFiles(selectKeys) } static aLoadShareSite() { if (useServerStore().shareSiteList.length == 0) ServerHttp.CheckUpgrade(false) } static SaveShareSite(list: IShareSiteModel[]) { DB.saveValueObject('shareSiteList', list).catch(() => {}) useServerStore().mSaveShareSiteList(list) } } ================================================ FILE: src/renderer/share/share/ShareSiteRight.vue ================================================ ================================================ FILE: src/renderer/share/share/ShowShareLinkModal.vue ================================================ ================================================ FILE: src/renderer/store/appstore.ts ================================================ import DebugLog from '../utils/debuglog' import { onHideRightMenu } from '../utils/keyboardhelper' import { defineStore } from 'pinia' export interface IPageOffice { user_id: string drive_id: string file_id: string file_name: string preview_url: string access_token: string } export interface IPageCode { user_id: string drive_id: string file_id: string file_name: string code_ext: string file_size: number download_url: string } export interface IPageImage { user_id: string drive_id: string file_id: string file_name: string mode: string imageidlist: string[] imagenamelist: string[] } export interface IPageVideoXBT { user_id: string drive_id: string file_id: string file_name: string } export interface IPageVideo { user_id: string drive_id: string file_id: string file_name: string } export interface AppState { appTheme: string appPage: string appTab: string appTabMenuMap: Map appDark: boolean appShutDown: boolean pageOffice?: IPageOffice pageCode?: IPageCode pageImage?: IPageImage pageVideoXBT?: IPageVideoXBT pageVideo?: IPageVideo } const useAppStore = defineStore('app', { state: (): AppState => ({ appTheme: 'light', appPage: 'PageLoading', appTab: 'pan', appTabMenuMap: new Map([ ['pan', 'wangpan'], ['pic', 'allpic'], ['down', 'DowningRight'], ['share', 'OtherShareRight'], ['rss', 'AppSame'], ['setting', ''] ]), appDark: false, appShutDown: false }), getters: { GetAppTabMenu(state: AppState): string { return state.appTabMenuMap.get(state.appTab)! } }, actions: { updateStore(partial: Partial) { this.$patch(partial) }, toggleTheme(theme: string) { console.log('toggleTheme', theme, this) this.appTheme = theme if (this.appTheme == 'dark' || (this.appTheme == 'system' && this.appDark)) { document.body.setAttribute('arco-theme', 'dark') } else { document.body.removeAttribute('arco-theme') } }, toggleDark(dark: boolean) { console.log('toggleDark', dark, this) this.appDark = dark if (this.appTheme == 'dark' || (this.appTheme == 'system' && dark)) { document.body.setAttribute('arco-theme', 'dark') } else { document.body.removeAttribute('arco-theme') } }, togglePage(page: string) { if (page == this.appPage) return this.appPage = page }, resetTab() { this.$patch({ appTab: 'pan', appTabMenuMap: new Map([ ['pan', 'wangpan'], ['pic', 'allpic'], ['down', 'DowningRight'], ['share', 'OtherShareRight'], ['rss', 'AppSame'], ['setting', ''] ]) }) }, toggleTab(tab: string) { if (this.appTab != tab) { this.appTab = tab if (tab == 'setting') DebugLog.aLoadFromDB() onHideRightMenu() } }, toggleTabMenu(tab: string, menu: string) { if (this.appTab != tab) { this.appTab = tab if (tab == 'setting') DebugLog.aLoadFromDB() } this.appTabMenuMap.set(tab, menu) if (tab == 'setting') document.getElementById(menu)?.scrollIntoView() onHideRightMenu() }, toggleTabSetting(tab: string, menu: string) { if (tab == this.appTab && this.appTabMenuMap.get(tab) == menu) return if (this.appTab != tab) { this.appTab = tab } if (menu) { this.appTabMenuMap.set(tab, menu) } }, toggleTabNext() { switch (this.appTab) { case 'pan': { this.appTab = 'pic' break } case 'pic': { this.appTab = 'down' break } case 'down': { this.appTab = 'share' break } case 'share': { this.appTab = 'rss' break } case 'rss': { this.appTab = 'setting' DebugLog.aLoadFromDB() break } case 'setting': { this.appTab = 'pan' break } } onHideRightMenu() }, toggleTabNextMenu() { const next = function (map: Map, tab: string, menuList: string[]) { const menu = map.get(tab)! for (let i = 0, maxi = menuList.length; i < maxi; i++) { if (menuList[i] == menu) { if (i + 1 >= menuList.length) map.set(tab, menuList[0]) else map.set(tab, menuList[i + 1]) } } } switch (this.appTab) { case 'pan': { next(this.appTabMenuMap, this.appTab, ['wangpan', 'kuaijie', 'fangying']) break } case 'pic': { next(this.appTabMenuMap, this.appTab, ['allpic', 'xiangce']) break } case 'down': { next(this.appTabMenuMap, this.appTab, ['DowningRight', 'DownedRight', 'UploadingRight', 'UploadedRight', 'SyncRight', 'M3U8Right']) break } case 'share': { next(this.appTabMenuMap, this.appTab, ['OtherShareRight', 'MyShareRight', 'MyFollowingRight', 'OtherFollowingRight', 'ShareSiteRight']) break } case 'rss': { next(this.appTabMenuMap, this.appTab, ['AppSame', 'RssXiMa', 'RssRename', 'RssJiaMi', 'RssScanClean', 'RssScanSame', 'RssScanPunish', 'RssScanEnmpty', 'RssMakeFileTree', 'RssMakeTreeMap', 'RssDriveCopy', 'RssUserCopy']) break } case 'setting': { next(this.appTabMenuMap, this.appTab, ['SettingUI', 'SettingDown', 'SettingPan', 'SettingDebug', 'SettingAria', 'SettingLog']) const menu = this.appTabMenuMap.get('setting')! document.getElementById(menu)?.scrollIntoView() break } } onHideRightMenu() } } }) export default useAppStore ================================================ FILE: src/renderer/store/footstore.ts ================================================ import { ApiGetAsyncTask, ApiGetAsyncTaskUnzip, AsyncType, Drive } from '../aliapi/utils' import PanDAL from '../pan/pandal' import DebugLog from '../utils/debuglog' import { humanTimeFM } from '../utils/format' import { defineStore } from 'pinia' import { ITokenInfo } from '../user/userstore' import useAppStore from './appstore' export interface AsyncModel { user_id: string key: string title: string starttime: number endtime: number usetime: string status: string tofile_id: string todrive_id: string zipfile_id: string zipdrive_id: string zipdomain_id: string type: AsyncType } export interface FootState { taskVisible: boolean taskList: AsyncModel[] audioUrl: string rightWidth: number panDirInfo: string picDirInfo: string uploadingInfo: string downloadingInfo: string loadingInfo: string panSpaceInfo: string picSpaceInfo: string } const useFootStore = defineStore('foot', { state: (): FootState => ({ taskVisible: false, taskList: [], audioUrl: '', rightWidth: 301, panDirInfo: '', picDirInfo: '', uploadingInfo: '', downloadingInfo: '', loadingInfo: '', panSpaceInfo: '', picSpaceInfo: '' }), getters: { GetIsRunning(state: FootState): boolean { let isRunning = false state.taskList.map((t) => { if (t.status == 'running') isRunning = true return true }) return isRunning }, GetSpaceInfo(state: FootState): string { if (state.loadingInfo) return '' const appTab = useAppStore().appTab if (appTab == 'pan') return state.panSpaceInfo if (appTab == 'pic') return state.panSpaceInfo return '' }, GetInfo(state: FootState): string { if (state.audioUrl) return '' const appTab = useAppStore().appTab const appPage = useAppStore().GetAppTabMenu if (appTab == 'pan') return state.panDirInfo if (appTab == 'pic') return state.panDirInfo if (appPage == 'DowningRight') return state.downloadingInfo if (appPage == 'UploadingRight') return state.uploadingInfo return '' } }, actions: { updateStore(partial: Partial) { this.$patch(partial) }, mDeleteTask(key: string) { this.taskList = this.taskList.filter((t) => t.key != key) }, mAddTask(user_id: string, key: string, type: AsyncType, title: string, todrive_id: string, tofile_id: string) { this.taskList = [{ user_id, todrive_id, tofile_id, zipdrive_id: '', zipfile_id: '', zipdomain_id: '', key, type, title: type + ' ' + title, status: 'running', starttime: new Date().getTime(), endtime: 0, usetime: '' } as AsyncModel].concat(this.taskList) this.taskVisible = true }, mAddTaskZip(user_id: string, key: string, type: AsyncType, title: string, todrive_id: string, tofile_id: string, zipdrive_id: string, zipfile_id: string, zipdomain_id: string) { this.taskList = [{ user_id, todrive_id, tofile_id, zipdrive_id, zipfile_id, zipdomain_id, key, type, title: type + ' ' + title, status: 'running', starttime: new Date().getTime(), endtime: 0, usetime: '' } as AsyncModel].concat(this.taskList) this.taskVisible = true }, aUpdateTask() { const list = this.taskList for (let i = 0, maxi = list.length; i < maxi; i++) { const item = list[i] if (item.status == 'running') { let result if (item.type == '解压') { result = ApiGetAsyncTaskUnzip(item.user_id, item.zipdrive_id, item.zipfile_id, item.zipdomain_id, item.key) } else { result = ApiGetAsyncTask(item.user_id, item.key) } result .then((resp) => { item.status = resp list[i].endtime = new Date().getTime() list[i].usetime = humanTimeFM((list[i].endtime - list[i].starttime) / 1000) if (item.status != 'running') { if (item.type == '解压' || item.type == '复制' || item.type == '导入分享' || item.type == '回收站还原') { PanDAL.GetDirFileList(item.user_id, item.todrive_id, item.tofile_id, '') } } }) .catch((err: any) => { DebugLog.mSaveDanger('aUpdateTask' + item.title, err) }) } } }, mClearTask() { const list = this.taskList const newList: AsyncModel[] = [] for (let i = 0, maxi = list.length; i < maxi; i++) { if (list[i].status == 'running') newList.push(list[i]) } this.taskList = newList }, mSaveUploadingInfo(total: number) { this.uploadingInfo = total > 1000 ? '前 1000 / ' + total + ' 个' : '' }, mSaveAudioUrl(url: string) { this.audioUrl = url }, mSaveLoading(title: string) { this.loadingInfo = title }, mSaveUserInfo(token: ITokenInfo) { this.panSpaceInfo = '总空间 ' + token.spaceinfo }, mSaveDirInfo(drive: Drive, info: string) { if (drive == 'pan') this.panDirInfo = info if (drive == 'pic') this.picDirInfo = info } } }) export default useFootStore ================================================ FILE: src/renderer/store/index.ts ================================================ import { createPinia } from 'pinia' import useAppStore from './appstore' import useKeyboardStore from './keyboardstore' import type { KeyboardState } from './keyboardstore' import useLogStore from './logstore' import useModalStore from './modalstore' import type { ModalState } from './modalstore' import useWinStore from './winstore' import type { WinState } from './winstore' import useSettingStore from '../setting/settingstore' import useUserStore from '../user/userstore' import type { ITokenInfo } from '../user/userstore' import usePanTreeStore from '../pan/pantreestore' import usePanFileStore from '../pan/panfilestore' import useServerStore from './serverstore' import type { IOtherShareLinkModel } from '../share/share/OtherShareStore' import type { IShareSiteModel } from './serverstore' import useMyShareStore from '../share/share/MyShareStore' import useOtherShareStore from '../share/share/OtherShareStore' import useMyFollowingStore from '../share/following/MyFollowingStore' import useOtherFollowingStore from '../share/following/OtherFollowingStore' import type { FollowingState } from '../share/following/OtherFollowingStore' import useFootStore from './footstore' import type { AsyncModel } from './footstore' const pinia = createPinia() export { useAppStore, useSettingStore, useLogStore, useModalStore, ModalState, useWinStore, WinState, useKeyboardStore, KeyboardState, useUserStore, ITokenInfo, usePanTreeStore, usePanFileStore, useServerStore, IOtherShareLinkModel, IShareSiteModel, useMyShareStore, useOtherShareStore, useOtherFollowingStore, FollowingState, useMyFollowingStore, useFootStore, AsyncModel } export default pinia ================================================ FILE: src/renderer/store/keyboardstore.ts ================================================ import { defineStore } from 'pinia' export interface KeyboardMessage { Code: string Key: string Ctrl: boolean Shift: boolean Alt: boolean Repeat: boolean IsInput: boolean IsEnmpty: boolean } export interface KeyboardState { KeyDownEvent: KeyboardMessage KeyUpEvent: KeyboardMessage } const useKeyboardStore = defineStore('keyboard', { state: (): KeyboardState => ({ KeyDownEvent: { Ctrl: false, Shift: false, Alt: false, Repeat: false, IsInput: false, Code: '', Key: '', IsEnmpty: true } as KeyboardMessage, KeyUpEvent: { Ctrl: false, Shift: false, Alt: false, Repeat: false, IsInput: false, Code: '', Key: '', IsEnmpty: true } as KeyboardMessage }), getters: {}, actions: { updateStore(partial: Partial) { this.$patch(partial) }, KeyDown(event: KeyboardEvent) { console.log(event) this.KeyDownEvent = { Ctrl: event.ctrlKey, Shift: event.shiftKey, Alt: event.altKey, Repeat: event.repeat, IsInput: false, Code: event.code, Key: event.key.toLowerCase(), IsEnmpty: false } } } }) export default useKeyboardStore ================================================ FILE: src/renderer/store/logstore.ts ================================================ import { defineStore } from 'pinia' export interface LogState { logTime: number } const useLogStore = defineStore('log', { state: (): LogState => ({ logTime: Date.now() }), getters: {}, actions: { logRefresh(time: number) { this.logTime = time } } }) export default useLogStore ================================================ FILE: src/renderer/store/modalstore.ts ================================================ import { defineStore } from 'pinia' import { onHideRightMenuScroll } from '../utils/keyboardhelper' export interface ModalState { modalName: string modalData: any } const useModalStore = defineStore('modal', { state: (): ModalState => ({ modalName: '', modalData: {} }), actions: { showModal(modalName: string, modalData: any) { if (modalName) onHideRightMenuScroll() if (modalName && modalName == this.modalName) { this.$patch({ modalName: '', modalData: {} }) setTimeout(() => { this.$patch({ modalName, modalData }) }, 300) } else this.$patch({ modalName, modalData }) } } }) export default useModalStore ================================================ FILE: src/renderer/store/protobuf.ts.bak ================================================ import { IAliGetDirModel } from '@/aliapi/alimodels' import { Message, Type, Field, OneOf } from 'protobufjs/light' // respectively "./node_modules/protobufjs/light.js" export class AwesomeSubMessage extends Message { @Field.d(1, 'string') public awesomeString?: string } export enum AwesomeEnum { ONE = 1, TWO = 2 } @Type.d('SuperAwesomeMessage') export class AwesomeMessage extends Message { @Field.d(1, 'string', 'optional', 'awesome default string') public awesomeField?: string @Field.d(2, AwesomeSubMessage) public awesomeSubMessage?: AwesomeSubMessage @Field.d(3, AwesomeEnum, 'optional', AwesomeEnum.ONE) public awesomeEnum?: AwesomeEnum @OneOf.d('awesomeSubMessage', 'awesomeEnum') public which?: string } // example code let message = { awesomeField: 'hello' } let buffer = AwesomeMessage.encode(message).finish() let decoded = AwesomeMessage.decode(buffer) console.log(message, buffer, decoded) @Type.d('IAliGetDirModel') export class PAliGetDirModel extends Message { @Field.d(1, 'bool') public __v_skip!: true @Field.d(2, 'string') public drive_id!: string @Field.d(3, 'string') public file_id!: string @Field.d(4, 'string') public parent_file_id!: string @Field.d(5, 'string') public name!: string @Field.d(6, 'string') public namesearch!: string @Field.d(7, 'int64') public size!: number @Field.d(8, 'int32') public time!: number @Field.d(9, 'string') public description!: string } export function ToIAliGetDirModelBuffer(list: any[]) { let result: Uint8Array[] = [] for (let i = 0, maxi = list.length; i < maxi; i++) { result.push(PAliGetDirModel.encode(list[i]).finish()) } return result } export function ToIAliGetDirModelObject(list: Uint8Array[]) { let result: IAliGetDirModel[] = [] for (let i = 0, maxi = list.length; i < maxi; i++) { result.push(PAliGetDirModel.decode(list[i])) } return result } ================================================ FILE: src/renderer/store/serverstore.ts ================================================ import { defineStore } from 'pinia' export interface IShareSiteModel { title: string url: string tip: string } export interface ServerState { shareSiteList: IShareSiteModel[] helpUrl: string } const useServerStore = defineStore('serverstore', { state: (): ServerState => ({ shareSiteList: [], helpUrl: 'aHR0cHM6Ly9naXRodWIuY29tL2xpdXBhbjE4OTAvYWxpeXVucGFuL3dpa2k=' }), actions: { mSaveShareSiteList(shareSiteList: IShareSiteModel[]) { this.shareSiteList = shareSiteList || [] }, mSaveHelpUrl(url: string) { this.helpUrl = url || 'aHR0cHM6Ly9naXRodWIuY29tL2xpdXBhbjE4OTAvYWxpeXVucGFuL3dpa2k=' } } }) export default useServerStore ================================================ FILE: src/renderer/store/treestore.ts ================================================ import { IAliFileResp } from '../aliapi/dirfilelist' import { IAliGetDirModel, IAliGetFileModel } from '../aliapi/alimodels' import DB from '../utils/db' import { ArrayCopy } from '../utils/utils' import { useSettingStore } from '../store' import { debounce, throttle } from '../utils/debounce' import { OrderNode } from '../utils/filenameorder' export interface TreeNodeData { __v_skip: true key: string title: string namesearch?: string children: TreeNodeData[] icon?: any isLeaf?: boolean } export interface DirData { file_id: string parent_file_id: string name: string time: number size: number } export interface IDriverModel { drive_id: string DirMap: Map DirChildrenMap: Map DirFileSizeMap: { [key: string]: number } DirFileSizeTimeMap: { [key: string]: number } DirTotalSizeMap: { [key: string]: number } FileOrderMap: { [key: string]: string } } const DriverData = new Map() const UserAllDir = new Map() export default class TreeStore { static async ConvertToOneDriver(drive_id: string, children: DirData[], saveToDB: boolean, saveToDriverData: boolean): Promise { console.log('ConvertToOneDriver') if (saveToDB) { UserAllDir.set(drive_id, new Date().getTime()) DB.saveValueObject('AllDir_' + drive_id, children) DB.saveValueNumber('AllDir_' + drive_id, Date.now()) } const OneDriver: IDriverModel = { drive_id, DirMap: new Map(), DirChildrenMap: new Map(), DirFileSizeMap: {}, DirFileSizeTimeMap: {}, DirTotalSizeMap: {}, FileOrderMap: {} } const jsonSize = await DB.getValueObject('DirFileSize_' + drive_id) const sizeMap = jsonSize ? (jsonSize as { [key: string]: number }) : {} const jsonSizeTime = await DB.getValueObject('DirFileSizeTime_' + drive_id) const sizeTimeMap = jsonSizeTime ? (jsonSizeTime as { [key: string]: number }) : {} const jsonOrder = await DB.getValueObject('DirFileOrder_' + drive_id) OneDriver.FileOrderMap = jsonOrder ? (jsonOrder as { [key: string]: string }) : {} const root: DirData = { file_id: 'root', parent_file_id: '', name: '根目录', time: 0, size: 0 } OneDriver.DirMap.set(root.file_id, root) const childrenMap = new Map() childrenMap.set(root.file_id, []) try { let parent_file_id: string = '' let childDirList: DirData[] = [] let item: DirData for (let i = 0, maxi = children.length; i < maxi; i++) { item = children[i] OneDriver.DirMap.set(item.file_id, item) OneDriver.DirFileSizeMap[item.file_id] = sizeMap[item.file_id] || 0 OneDriver.DirFileSizeTimeMap[item.file_id] = sizeTimeMap[item.file_id] || 0 if (parent_file_id != item.parent_file_id) { if (childrenMap.has(item.parent_file_id)) { childDirList = childrenMap.get(item.parent_file_id)! } else { childDirList = [] childrenMap.set(item.parent_file_id, childDirList) } parent_file_id = item.parent_file_id } childDirList.push(item) } } catch {} if (saveToDriverData) { const childrenMap2 = new Map() childrenMap.forEach(function (value, key) { Object.freeze(value) childrenMap2.set(key, value) }) OneDriver.DirChildrenMap = childrenMap2 OneDriver.DirTotalSizeMap.root = TotalSize('root', OneDriver.DirTotalSizeMap, OneDriver.DirFileSizeMap, OneDriver.DirChildrenMap) DriverData.set(OneDriver.drive_id, OneDriver) } else { OneDriver.DirChildrenMap = childrenMap } return OneDriver } static async SaveOneDriver(OneDriver: IDriverModel): Promise { const childrenMap2 = new Map() OneDriver.DirChildrenMap.forEach(function (value, key) { Object.freeze(value) childrenMap2.set(key, value) }) OneDriver.DirChildrenMap = childrenMap2 DriverData.set(OneDriver.drive_id, OneDriver) _RefreshAllDirTotalSizeFunc(OneDriver.drive_id) } static async SaveOneDirFileList(oneDir: IAliFileResp, hasFiles: boolean): Promise { console.log('SaveOneDirFileList', oneDir.dirID) if (oneDir.dirID == 'favorite' || oneDir.dirID == 'trash' || oneDir.dirID == 'recover' || oneDir.dirID.startsWith('search') || oneDir.dirID.startsWith('color') || oneDir.dirID.startsWith('video')) { return } let driverData = DriverData.get(oneDir.m_drive_id) if (!driverData) { const cache = await DB.getValueObject('AllDir_' + oneDir.m_drive_id) if (cache) { console.log('SaveOneDirFileList LoadCacheAllDir') driverData = await TreeStore.ConvertToOneDriver(oneDir.m_drive_id, cache as DirData[], false, true) } else { console.log('SaveOneDirFileList 找不到cache直接退出') return } } const dirs: IAliGetFileModel[] = [] const files: IAliGetFileModel[] = [] for (let i = 0, maxi = oneDir.items.length; i < maxi; i++) { if (oneDir.items[i].isDir) dirs.push(oneDir.items[i]) else files.push(oneDir.items[i]) } if (hasFiles) { let dirSize = 0 for (let i = 0, maxi = files.length; i < maxi; i++) { if (!files[i].isDir) dirSize += files[i].size } driverData.DirFileSizeMap[oneDir.dirID] = dirSize driverData.DirFileSizeTimeMap[oneDir.dirID] = Math.floor(Date.now() / 1000) - 1654500000 } const dirList: DirData[] = [] for (let i = 0, maxi = dirs.length; i < maxi; i++) { const item = dirs[i] const dirItem: DirData = { file_id: item.file_id, parent_file_id: item.parent_file_id, name: item.name, time: item.time, size: 0 } dirList.push(dirItem) driverData.DirMap.set(dirItem.file_id, dirItem) } Object.freeze(dirList) driverData.DirChildrenMap.set(oneDir.dirID, dirList) let dirID = oneDir.dirID while (true) { driverData.DirTotalSizeMap[dirID] = TotalSize(dirID, driverData.DirTotalSizeMap, driverData.DirFileSizeMap, driverData.DirChildrenMap) const tdir = driverData.DirMap.get(dirID) if (tdir && tdir.parent_file_id != 'root' && tdir.parent_file_id != '') dirID = tdir.parent_file_id else break } if (oneDir.dirID !== 'root') _SaveDirSize() } static GetDirOrder(drive_id: string, file_id: string): string { const settingStore = useSettingStore() let order = settingStore.uiFileListOrder || 'name desc' if (settingStore.uiFileOrderDuli != 'null') { const driverData = DriverData.get(drive_id) if (driverData) order = driverData.FileOrderMap[file_id] || settingStore.uiFileOrderDuli || order } return order.toLowerCase() } static SaveDirOrder(drive_id: string, file_id: string, order: string): void { const settingStore = useSettingStore() if (settingStore.uiFileOrderDuli != 'null') { const driverData = DriverData.get(drive_id) if (driverData) { driverData.FileOrderMap[file_id] = order DB.saveValueObject('DirFileOrder_' + drive_id, driverData.FileOrderMap) } } else { settingStore.updateStore({ uiFileListOrder: order }) } } static GetTreeDataToShow(driverData: IDriverModel, node: TreeNodeData, expandedKeys: Set, map: Map, getChildren: boolean, order: string = ''): void { let childDirList: DirData[] = ArrayCopy(driverData.DirChildrenMap.get(node.key) || []) node.isLeaf = childDirList.length == 0 let dirOrder = '' if (!order) { const settingStore = useSettingStore() if (settingStore.uiFileOrderDuli != 'null') { dirOrder = driverData.FileOrderMap[node.key] || settingStore.uiFileOrderDuli || settingStore.uiFileListOrder || 'name desc' } else { dirOrder = settingStore.uiFileListOrder || 'name desc' order = dirOrder } } else dirOrder = order if (dirOrder.startsWith('size ')) { for (let i = 0, maxi = childDirList.length; i < maxi; i++) { const item = childDirList[i] item.size = driverData.DirTotalSizeMap[item.file_id] || 0 } } childDirList = OrderNode(dirOrder, childDirList) as DirData[] const children: TreeNodeData[] = [] for (let i = 0, maxi = childDirList.length; i < maxi; i++) { const item = childDirList[i] const itemNode: TreeNodeData = { __v_skip: true, key: item.file_id, title: item.name, children: [] } if (expandedKeys.has(itemNode.key)) TreeStore.GetTreeDataToShow(driverData, itemNode, expandedKeys, map, true, order) else if (getChildren) TreeStore.GetTreeDataToShow(driverData, itemNode, expandedKeys, map, false, order) children.push(itemNode) map.set(itemNode.key, itemNode) } node.children = children } static GetDriver(drive_id: string): IDriverModel | undefined { return DriverData.get(drive_id) } static GetDir(drive_id: string, file_id: string): IAliGetDirModel | undefined { if (file_id == 'root') return { __v_skip: true, drive_id, file_id: 'root', parent_file_id: '', name: '根目录', namesearch: '', size: 0, time: 0, description: '' } if (file_id == 'favorite') return { __v_skip: true, drive_id, file_id: 'favorite', parent_file_id: '', name: '收藏夹', namesearch: '', size: 0, time: 0, description: '' } if (file_id == 'trash') return { __v_skip: true, drive_id, file_id: 'trash', parent_file_id: '', name: '回收站', namesearch: '', size: 0, time: 0, description: '' } if (file_id == 'recover') return { __v_skip: true, drive_id, file_id: 'recover', parent_file_id: '', name: '文件恢复', namesearch: '', size: 0, time: 0, description: '' } if (file_id.startsWith('search')) return { __v_skip: true, drive_id, file_id: file_id, parent_file_id: '', name: ('搜索 ' + file_id.substring(6)).trimEnd(), namesearch: '', size: 0, time: 0, description: '' } if (file_id.startsWith('color')) return { __v_skip: true, drive_id, file_id: file_id, parent_file_id: '', name: '标记 · ' + file_id.substring(file_id.indexOf(' ') + 1), namesearch: '', size: 0, time: 0, description: '' } if (file_id == 'video') return { __v_skip: true, drive_id, file_id: 'video', parent_file_id: '', name: '放映室', namesearch: '', size: 0, time: 0, description: '' } if (file_id.startsWith('video')) return { __v_skip: true, drive_id, file_id: file_id, parent_file_id: '', name: '放映室 · ' + file_id.substring('video'.length), namesearch: '', size: 0, time: 0, description: '' } const driverData = DriverData.get(drive_id) if (!driverData) return undefined const dir = driverData.DirMap.get(file_id) if (!dir) return undefined return { __v_skip: true, drive_id, namesearch: '', description: '', ...dir } } static GetDirPath(drive_id: string, file_id: string): IAliGetDirModel[] { const dirPath: IAliGetDirModel[] = [] if (!drive_id || !file_id) return dirPath if (file_id == 'root') return [{ __v_skip: true, drive_id, file_id: 'root', parent_file_id: '', name: '根目录', namesearch: '', size: 0, time: 0, description: '' }] if (file_id == 'favorite') return [{ __v_skip: true, drive_id, file_id: 'favorite', parent_file_id: '', name: '收藏夹', namesearch: '', size: 0, time: 0, description: '' }] if (file_id == 'trash') return [{ __v_skip: true, drive_id, file_id: 'trash', parent_file_id: '', name: '回收站', namesearch: '', size: 0, time: 0, description: '' }] if (file_id == 'recover') return [{ __v_skip: true, drive_id, file_id: 'recover', parent_file_id: '', name: '文件恢复', namesearch: '', size: 0, time: 0, description: '' }] if (file_id == 'search') return [{ __v_skip: true, drive_id, file_id: 'search', parent_file_id: '', name: '全盘搜索', namesearch: '', size: 0, time: 0, description: '' }] if (file_id.startsWith('search')) { return [ { __v_skip: true, drive_id, file_id: 'search', parent_file_id: '', name: '全盘搜索', namesearch: '', size: 0, time: 0, description: '' }, { __v_skip: true, drive_id, file_id: file_id, parent_file_id: 'search', name: file_id.substring(6), namesearch: '', size: 0, time: 0, description: '' } ] } if (file_id.startsWith('color')) return [{ __v_skip: true, drive_id, file_id: file_id, parent_file_id: '', name: '标记 · ' + file_id.substring(file_id.indexOf(' ') + 1), namesearch: '', size: 0, time: 0, description: '' }] if (file_id == 'video') return [{ __v_skip: true, drive_id, file_id: 'video', parent_file_id: '', name: '放映室', namesearch: '', size: 0, time: 0, description: '' }] if (file_id.startsWith('video')) return [ { __v_skip: true, drive_id, file_id: 'video', parent_file_id: '', name: '放映室', namesearch: '', size: 0, time: 0, description: '' }, { __v_skip: true, drive_id, file_id: file_id, parent_file_id: '', name: '放映室 · ' + file_id.substring('video'.length), namesearch: '', size: 0, time: 0, description: '' } ] const driverData = DriverData.get(drive_id) if (!driverData) return dirPath const dirMap = driverData.DirMap while (true) { const dir = dirMap.get(file_id) if (!dir) break dirPath.push({ __v_skip: true, drive_id, namesearch: '', description: '', ...dir } as IAliGetDirModel) file_id = dir.parent_file_id } dirPath.reverse() return dirPath } static GetDirChildDirID(drive_id: string, file_id: string): string[] { const allList: string[] = [] const driverData = DriverData.get(drive_id) if (!driverData) return allList const childrens = driverData.DirChildrenMap.get(file_id) if (childrens) childrens.map((t) => allList.push(t.file_id)) return allList } static RenameDirs(drive_id: string, fileList: { file_id: string; parent_file_id: string; name: string; isDir: boolean }[]): void { const driverData = DriverData.get(drive_id) if (!driverData) return const dirMap = driverData.DirMap for (let i = 0, maxi = fileList.length; i < maxi; i++) { const item = fileList[i] if (!item.isDir) continue const findNode = dirMap.get(item.file_id) if (findNode) findNode.name = item.name } } static DeleteDirs(drive_id: string, file_idList: string[]): void { const driverData = DriverData.get(drive_id) if (!driverData) return const dirMap = driverData.DirMap const dirChildrenMap = driverData.DirChildrenMap for (let i = 0, maxi = file_idList.length; i < maxi; i++) { const dirID = file_idList[i] const dir = dirMap.get(dirID) if (dir) { const parent_file_id = dir.parent_file_id let clist = dirChildrenMap.get(parent_file_id) if (clist) { clist = clist.filter((t) => t.file_id != dirID) Object.freeze(clist) dirChildrenMap.set(parent_file_id, clist) } } dirMap.delete(dirID) dirChildrenMap.delete(dirID) } } static GetDirSizeNeedRefresh(drive_id: string, maxCacheTime: number = 604800): string[] { const driverData = DriverData.get(drive_id) if (!driverData) return [] const map = driverData.DirMap.keys() const timeMap = driverData.DirFileSizeTimeMap const timeNow = Math.floor(Date.now() / 1000) - 1654500000 const diridList: string[] = [] while (true) { const next = map.next() if (next.done) break const file_id = next.value as string const time = timeMap[file_id] || 0 if (time == 0 || timeNow - time > maxCacheTime) { diridList.push(file_id) } } return diridList } static SaveDirSizeNeedRefresh(drive_id: string, dirSizeList: { dirID: string; size: number }[]): void { const driverData = DriverData.get(drive_id) if (!driverData) return const fileMap = driverData.DirFileSizeMap const timeMap = driverData.DirFileSizeTimeMap const timeNow = Math.floor(Date.now() / 1000) - 1654500000 for (let i = 0, maxi = dirSizeList.length; i < maxi; i++) { const t = dirSizeList[i] fileMap[t.dirID] = t.size timeMap[t.dirID] = timeNow } _SaveDirSize(drive_id) _RefreshAllDirTotalSize(drive_id) } static ClearDirSize(drive_id: string, parentDirIDList: string[]) { const driverData = DriverData.get(drive_id) if (!driverData) return const timeMap = driverData.DirFileSizeTimeMap for (let i = 0, maxi = parentDirIDList.length; i < maxi; i++) { timeMap[parentDirIDList[i]] = 0 } } } const _SaveDirSize = throttle((drive_id: string) => { const driverData = DriverData.get(drive_id) if (!driverData) return DB.saveValueObjectBatch(['DirFileSize_' + driverData.drive_id, 'DirFileSizeTime_' + driverData.drive_id], [driverData.DirFileSizeMap, driverData.DirFileSizeTimeMap]) }, 5000) const _RefreshAllDirTotalSize = debounce(_RefreshAllDirTotalSizeFunc, 12000, false, true, true) function _RefreshAllDirTotalSizeFunc(drive_id: string): void { const driverData = DriverData.get(drive_id) if (!driverData) return console.log('_RefreshAllDirTotalSizeFuncbegin') driverData.DirTotalSizeMap.root = TotalSize('root', driverData.DirTotalSizeMap, driverData.DirFileSizeMap, driverData.DirChildrenMap) console.log('_RefreshAllDirTotalSizeFunc') _SaveDirSize(drive_id) } function TotalSize(file_id: string, DirTotalSizeMap: { [key: string]: number }, DirFileSizeMap: { [key: string]: number }, DirChildrenMap: Map): number { const dirChildrenList = DirChildrenMap.get(file_id) || [] let size = DirFileSizeMap[file_id] || 0 for (let i = 0, maxi = dirChildrenList.length; i < maxi; i++) { size += TotalSize(dirChildrenList[i].file_id, DirTotalSizeMap, DirFileSizeMap, DirChildrenMap) } DirTotalSizeMap[file_id] = size return size } ================================================ FILE: src/renderer/store/winstore.ts ================================================ import { defineStore } from 'pinia' export interface WinState { width: number height: number } const useWinStore = defineStore('win', { state: (): WinState => ({ width: 0, height: 0 }), getters: { GetListHeight(state: WinState): string { return (state.height - 192).toString() + 'px' }, GetListHeightNumber(state: WinState): number { return state.height - 192 } }, actions: { updateStore(partial: Partial) { this.$patch(partial) } } }) export default useWinStore ================================================ FILE: src/renderer/transfer/uploaddal.ts ================================================ import { useSettingStore } from '../store' import DBUpload from '../utils/dbupload' import { clickWait, clickWaitDelete } from '../utils/debounce' import useUploadedStore from '../down/uploadedstore' export default class UploadDAL { static async aReloadUploaded() { const uploadedStore = useUploadedStore() if (uploadedStore.ListLoading == true) return uploadedStore.ListLoading = true const showlist = await DBUpload.getUploadedByTop(5000) const count = await DBUpload.getUploadTaskCount() uploadedStore.aLoadListData(showlist, count) uploadedStore.ListLoading = false } static async aClearUploaded() { const max = useSettingStore().debugDownedListMax return await DBUpload.deleteUploadedOutCount(max) } static async UploadedDelete(all: boolean) { if (clickWait('UploadedDelete', -1)) return if (all) { await DBUpload.clearUploadedAll() } else { const uploadedStore = useUploadedStore() const keys = Array.from(uploadedStore.ListSelected) await DBUpload.deleteUploadedBatch(keys) } await this.aReloadUploaded() clickWaitDelete('UploadedDelete') } } ================================================ FILE: src/renderer/transfer/uploadingdal.ts ================================================ import useUploadingStore from '../down/uploadingstore' import { useFootStore, useSettingStore } from '../store' import { IStateUploadInfo, IStateUploadTask, IStateUploadTaskFile } from '../utils/dbupload' import { clickWait } from '../utils/debounce' import DebugLog from '../utils/debuglog' import { CheckWindowsBreakPath, FileSystemErrorMessage } from '../utils/filehelper' import { humanSize, humanSizeSpeed } from '../utils/format' import message from '../utils/message' import UploadingData from './uploadingdata' const path = window.require('path') const fspromises = window.require('fs/promises') export default class UploadingDAL { static QueryIsUploading() { return UploadingData.QueryIsUploading() } static async aReloadUploading() { const uploadingStore = useUploadingStore() if (uploadingStore.ListLoading == true) return uploadingStore.ListLoading = true UploadingData.ReloadUploading() uploadingStore.mShowTask(uploadingStore.showTaskID, uploadingStore.ShowTaskName) UploadingDAL.mUploadingRefresh() uploadingStore.ListLoading = false } static mUploadingRefresh() { const uploadingStore = useUploadingStore() let dirKey = uploadingStore.showTaskID || 0 let dirName = uploadingStore.ShowTaskName || '' if (dirKey) { const data = UploadingData.UploadingShowListDir(dirKey) if (data.count > 0) { uploadingStore.aLoadListData(dirKey, dirName, data.showList, data.count) useFootStore().mSaveUploadingInfo(data.count) UploadingData.UploadingShowProgress() return } } dirKey = 0 dirName = '' const data = UploadingData.UploadingShowList() uploadingStore.aLoadListData(dirKey, dirName, data.showList, data.count) useFootStore().mSaveUploadingInfo(data.count) UploadingData.UploadingShowProgress() } static async aUploadingStart(all: boolean, isToStart: boolean) { if (clickWait('aUploadingStart', 500)) return const uploadingStore = useUploadingStore() if (uploadingStore.showTaskID) { let UploadIDList: number[] = all ? [] : Array.from(uploadingStore.ListSelected) UploadIDList = await UploadingData.UploadingStartTaskFile(uploadingStore.showTaskID, UploadIDList, isToStart) if (!isToStart) { if (all) { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: false, UploadIDList: [], TaskIDList: [uploadingStore.showTaskID] }) } else { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: false, UploadIDList: UploadIDList, TaskIDList: [] }) } } } else { let TaskIDList: number[] = all ? [] : Array.from(uploadingStore.ListSelected) TaskIDList = await UploadingData.UploadingStartTask(TaskIDList, isToStart) if (!isToStart) { if (all) { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: true, UploadIDList: [], TaskIDList: [] }) } else { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: false, UploadIDList: [], TaskIDList: TaskIDList }) } } } UploadingDAL.mUploadingRefresh() } static async aUploadingStartOne(TaskOrUploadID: number) { if (clickWait('aUploadingStartOne', 400)) return const uploadingStore = useUploadingStore() if (uploadingStore.showTaskID) { const isToStart = UploadingData.GetTaskFileIsStop(TaskOrUploadID) const UploadIDList: number[] = [TaskOrUploadID] await UploadingData.UploadingStartTaskFile(uploadingStore.showTaskID, UploadIDList, isToStart) if (!isToStart) window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: false, UploadIDList: UploadIDList, TaskIDList: [] }) } else { const isToStart = UploadingData.GetTaskIsStop(TaskOrUploadID) const TaskIDList: number[] = [TaskOrUploadID] await UploadingData.UploadingStartTask(TaskIDList, isToStart) if (!isToStart) window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'stop', IsAll: false, UploadIDList: [], TaskIDList: TaskIDList }) } UploadingDAL.mUploadingRefresh() } static async aUploadingDelete(all: boolean) { if (clickWait('aUploadingDelete', 500)) return const uploadingStore = useUploadingStore() if (uploadingStore.showTaskID) { let UploadIDList: number[] = all ? [] : Array.from(useUploadingStore().ListSelected) UploadIDList = await UploadingData.UploadingDeleteTaskFile(uploadingStore.showTaskID, UploadIDList) if (all) { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'delete', IsAll: false, UploadIDList: [], TaskIDList: [uploadingStore.showTaskID] }) } else { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'delete', IsAll: false, UploadIDList: UploadIDList, TaskIDList: [] }) } } else { let TaskIDList: number[] = all ? [] : Array.from(useUploadingStore().ListSelected) TaskIDList = await UploadingData.UploadingDeleteTask(TaskIDList) if (all) { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'delete', IsAll: true, UploadIDList: [], TaskIDList: [] }) } else { window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'delete', IsAll: false, UploadIDList: [], TaskIDList: TaskIDList }) } } UploadingDAL.mUploadingRefresh() } static mUploadingShowTask(TaskID: number = 0) { if (!TaskID) { const uploadingStore = useUploadingStore() const selectitem = uploadingStore.GetSelectedFirst() if (selectitem && selectitem.isDir) TaskID = selectitem.TaskID } if (TaskID) { const task = UploadingData.GetTask(TaskID) if (task && task.isDir) { useUploadingStore().mShowTask(task.TaskID, task.TaskName) UploadingDAL.mUploadingRefresh() } } } static mUploadingShowTaskBack() { useUploadingStore().mShowTask(0, '') UploadingDAL.mUploadingRefresh() } static async aUploadingEvent(ReportList: IStateUploadInfo[], ErrorList: IStateUploadInfo[], SuccessList: IStateUploadTaskFile[], RunningKeys: number[], StopKeys: number[], LoadingKeys: number[], SpeedTotal: string) { UploadingData.UploadingEventSave(ReportList, ErrorList, SuccessList) const check = UploadingData.UploadingEventRunningCheck(RunningKeys, StopKeys) if (check.delList.length > 0) { console.log('UploadingEventRunningCheck', check.delList) window.WinMsgToUpload({ cmd: 'UploadCmd', Command: 'delete', IsAll: false, UploadIDList: check.delList, TaskIDList: [] }) } const sendList = UploadingData.UploadingEventSendList(check.newList, LoadingKeys) if (sendList.length > 0) { window.WinMsgToUpload({ cmd: 'UploadAdd', UploadList: sendList }) if (!SpeedTotal) SpeedTotal = humanSizeSpeed(0) } const doc = document.getElementById('footUploadSpeed') if (doc) doc.innerHTML = SpeedTotal ? '' + SpeedTotal + '' : '' UploadingDAL.mUploadingRefresh() } static async aUploadingAppendFiles(TaskID: number, UploadID: number, CreatedDirID: string, AppendList: IStateUploadTaskFile[]) { await UploadingData.UploadingAppendFilesSave(TaskID, UploadID, CreatedDirID, AppendList) } static async aUploadLocalFiles(user_id: string, drive_id: string, parent_file_id: string, files: string[], check_name_mode: string, tip: boolean) { if (!user_id) return 0 if (!files || files.length == 0) return 0 const dateNow = Date.now() const loadingKey = 'adduploading_' + dateNow if (tip) { message.loading('正在保存上传任务', 60, loadingKey) } const settingStore = useSettingStore() const ingoredList = [...settingStore.downIngoredList] const UniqueMap = UploadingData.GetTaskUniqueID() let addList: IStateUploadTask[] = [] let plist: Promise[] = [] const timeStr = dateNow.toString().substring(2, 12) + '00000' let tasktime = parseInt(timeStr) let addall = 0 const formax = ingoredList.length for (let i = 0, maxi = files.length; i < maxi; i++) { const filePath = files[i] if (CheckWindowsBreakPath(filePath)) continue const filePathLower = filePath.toLowerCase() plist.push( fspromises .lstat(filePath) .then((stat: any) => { if (stat.isSymbolicLink()) return const isDir = stat.isDirectory() if (isDir == false) { if (stat.isFile() == false) return for (let j = 0; j < formax; j++) { if (filePathLower.endsWith(ingoredList[j])) return } } let baseName: string = path.basename(filePath) const basePath: string = path.dirname(filePath) const pathName = baseName if (!baseName && basePath.endsWith(':\\')) baseName = basePath.substring(0, basePath.length - 2) if (!baseName) { message.error('跳过上传任务,无法识别路径:' + filePath) DebugLog.mSaveDanger('上传文件出错 无法识别路径 ' + filePath) return } if (UniqueMap.has(parent_file_id + '|' + basePath + '|' + baseName)) { message.warning('跳过上传任务,已存在相同的任务:' + filePath) return } const TaskID = tasktime tasktime += 2 const task: IStateUploadTask = { TaskID: TaskID, TaskName: baseName, TaskFileID: '', check_name_mode: check_name_mode, user_id: user_id, localFilePath: basePath, parent_file_id: parent_file_id, drive_id: drive_id, isDir: isDir, Children: [], ChildFinishCount: 0, ChildTotalCount: 0, ChildTotalSize: 0, ChildFinishSize: 0 } task.ChildTotalCount = isDir ? 0 : 1 task.ChildTotalSize = isDir ? 0 : stat.size task.Children.push({ TaskID: TaskID, UploadID: TaskID + 1, partPath: pathName, name: baseName, size: stat.size, sizeStr: isDir ? '' : humanSize(stat.size), mtime: stat.mtime.getTime() , isDir: isDir, IsRoot: true, uploaded_is_rapid: false, uploaded_file_id: '' } as IStateUploadTaskFile) addList.push(task) }) .catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) message.error('上传文件出错 ' + err + ' ' + filePath, 3, loadingKey) DebugLog.mSaveDanger('上传文件出错 ' + err + ' ' + filePath) }) ) if (plist.length >= 10) { await Promise.all(plist).catch(() => {}) plist = [] if (addList.length >= 1000) { await UploadingData.UploadingAddTask(addList) addall += addList.length addList = [] } } } await Promise.all(plist).catch(() => {}) await UploadingData.UploadingAddTask(addList) addall += addList.length addList = [] UploadingDAL.mUploadingRefresh() if (tip) { message.success('成功创建 ' + addall.toString() + '个上传任务', 3, loadingKey) } return addall } } ================================================ FILE: src/renderer/transfer/uploadingdata.ts ================================================ import { IUploadingModel } from '../down/uploadingstore' import PanDAL from '../pan/pandal' import { useSettingStore } from '../store' import UploadDAL from './uploaddal' import DBUpload, { IStateUploadInfo, IStateUploadTask, IStateUploadTaskFile, IUploadingUI } from '../utils/dbupload' import { humanSize, humanSizeSpeed, humanTime, humanTimeFM } from '../utils/format' import { MapValueToArray } from '../utils/utils' import { throttle } from '../utils/debounce' import { SetProgressBar } from '../utils/electronhelper' const path = window.require('path') const UploadingTaskList = new Map() const UploadingInfoList = new Map() let UploadingTaskStop = new Set() let UploadingInfoStop = new Set() let _UploadingSendTime = 0 function SaveStopToDB() { return DBUpload.saveUploadObj('UploadingStop', { TaskIDList: Array.from(UploadingTaskStop), UploadIDList: Array.from(UploadingInfoStop) }) } const SaveTaskList = new Map() const SaveTaskToDB = throttle(() => { if (SaveTaskList.size > 0) { const list = MapValueToArray(SaveTaskList) DBUpload.saveUploadTaskBatch(list) } }, 10000) export default class UploadingData { static QueryIsUploading(): boolean { const keys = UploadingTaskList.keys() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const TaskID = keys.next().value as number if (UploadingTaskStop.has(TaskID) == false) return true } return false } static GetTaskUniqueID(): Set { const map = new Set() const values = UploadingTaskList.values() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const task = values.next().value as IStateUploadTask map.add(task.parent_file_id + '|' + task.localFilePath + '|' + task.TaskName) } return map } static GetTaskIsStop(TaskID: number): boolean { return UploadingTaskStop.has(TaskID) } static GetTaskFileIsStop(UploadID: number): boolean { return UploadingInfoStop.has(UploadID) } static GetTask(TaskID: number): IStateUploadTask | undefined { return UploadingTaskList.get(TaskID) } static GetTaskFile(TaskID: number, UploadID: number): IStateUploadTaskFile | undefined { const task = UploadingTaskList.get(TaskID) if (task) { const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { if (childrenList[i].UploadID == UploadID) return childrenList[i] } } return undefined } static GetTaskFileInfo(UploadID: number): IStateUploadInfo | undefined { return UploadingInfoList.get(UploadID) } static StartTask(TaskID: number, isToStart: boolean): boolean { const task = UploadingTaskList.get(TaskID) if (!task) return false if (isToStart) UploadingTaskStop.delete(TaskID) else UploadingTaskStop.add(TaskID) const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { const UploadID = childrenList[i].UploadID if (isToStart) { UploadingInfoStop.delete(UploadID) } else { UploadingInfoStop.add(UploadID) } const info = UploadingInfoList.get(UploadID) if (info) { info.uploadState = isToStart ? '排队中' : '已暂停' info.failedCode = 0 info.failedMessage = '' info.autoTryCount = 0 info.autoTryTime = 0 info.Speed = 0 info.speedStr = '' } } return true } static StartTaskFile(TaskID: number, UploadID: number, isToStart: boolean): boolean { const task = UploadingTaskList.get(TaskID) if (!task) return false if (isToStart) UploadingInfoStop.delete(UploadID) else UploadingInfoStop.add(UploadID) if (isToStart) UploadingTaskStop.delete(TaskID) else { const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { if (UploadingInfoStop.has(childrenList[i].UploadID) == false) { UploadingTaskStop.delete(TaskID) return true } } UploadingTaskStop.add(TaskID) } const info = UploadingInfoList.get(UploadID) if (info) { info.uploadState = isToStart ? '排队中' : '已暂停' info.failedCode = 0 info.failedMessage = '' info.autoTryCount = 0 info.autoTryTime = 0 info.Speed = 0 info.speedStr = '' } return true } static async ReloadUploading(): Promise { const stop = (await DBUpload.getUploadObj('UploadingStop')) as { TaskIDList: number[]; UploadIDList: number[] } | undefined UploadingTaskStop = new Set(stop?.TaskIDList || []) UploadingInfoStop = new Set(stop?.UploadIDList || []) UploadingTaskList.clear() let delTaskList: number[] = [] const fileList = await DBUpload.getUploadTaskAll() const fileMap = new Set() for (let i = 0, maxi = fileList.length; i < maxi; i++) { const item = fileList[i] if (item.Children.length == 0) { delTaskList.push(item.TaskID) } else { UploadingTaskList.set(item.TaskID, item) item.Children.map((t) => fileMap.add(t.UploadID)) } } if (delTaskList.length > 0) await DBUpload.deleteUploadTaskBatch(delTaskList) const downAutoStart = useSettingStore().downAutoStart const infoList = await DBUpload.getUploadInfoAll() UploadingInfoList.clear() if (UploadingTaskList.size == 0) { DBUpload.clearUploadTaskAll() UploadingTaskStop.clear() UploadingInfoStop.clear() } else { const delInfoList: number[] = [] for (let i = 0, maxi = infoList.length; i < maxi; i++) { const item = infoList[i] if (fileMap.has(item.UploadID)) { if (downAutoStart && UploadingInfoStop.has(item.UploadID) == false) { item.uploadState = '排队中' } else { item.uploadState = '已暂停' } item.failedCode = 0 item.failedMessage = '' item.autoTryCount = 0 item.autoTryTime = 0 item.Speed = 0 item.speedStr = '' UploadingInfoList.set(item.UploadID, item) } else { delInfoList.push(item.UploadID) UploadingInfoStop.delete(item.UploadID) } } if (delInfoList.length > 0) DBUpload.deleteUploadInfoBatch(delInfoList) } } static UploadingShowList(): { showList: IUploadingModel[]; count: number } { const showList: IUploadingModel[] = [] const now = Date.now() / 1000 const values = UploadingTaskList.values() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const task = values.next().value as IStateUploadTask if (!task.isDir) { if (task.Children.length == 1) { const item = UploadingData.UploadingShowOneItem(task.Children[0], now, task.localFilePath, task.TaskID, true) showList.push(item) } } else { let isRunning = 0 let isError = 0 let speed = 0 let childFinishSize = task.ChildFinishSize const isStop = UploadingTaskStop.has(task.TaskID) if (!isStop) { const childrenList = task.Children for (let j = 0, maxj = childrenList.length; j < maxj; j++) { const item = childrenList[j] const info = UploadingInfoList.get(item.UploadID) if (info) { if (info.uploadState == 'error') isError++ // else if (info.uploadState == '排队中') iswaiting++ else if (info.uploadState == 'running') { isRunning++ speed += info.Speed } else if (info.uploadState == '读取中') isRunning++ else if (info.uploadState == 'hashing') isRunning++ childFinishSize += info.uploadSize } } } showList.push({ UploadID: task.TaskID, TaskID: task.TaskID, localFilePath: path.join(task.localFilePath, task.localFilePath.endsWith(':\\') ? '' : task.TaskName) , name: task.TaskName, sizeStr: humanSize(task.ChildTotalSize), icon: 'iconfont iconfile-folder', isDir: task.isDir, uploadState: isStop ? '暂停中' : isRunning ? '上传中' : '排队中', speedStr: isRunning ? humanSizeSpeed(speed) : '' , Progress: Math.floor((childFinishSize * 100) / (task.ChildTotalSize + 1)) % 100, ProgressStr: task.ChildFinishCount + ' / ' + task.ChildTotalCount, errorMessage: isError > 0 ? '有错误点击查看' : '' } as IUploadingModel) } if (showList.length > 999) break } return { showList: showList, count: UploadingTaskList.size } } static UploadingShowOneItem(item: IStateUploadTaskFile, now: number, localFilePath: string, TaskID: number, isShowTask: boolean): IUploadingModel { const info = UploadingInfoList.get(item.UploadID) if (info && !UploadingInfoStop.has(item.UploadID)) { const isError = info.uploadState == 'error' const isSuccess = info.uploadState == 'success' const isRunning = info.uploadState == 'running' const isLoading = info.uploadState == '读取中' const isHashing = info.uploadState == 'hashing' const lastTime = Math.max(1, Math.min((item.size - info.uploadSize) / (info.Speed + 1), 356400)) let uploadState: string = info.uploadState if (isRunning) uploadState = info.failedMessage ? info.failedMessage : info.Progress + '% ' + humanTime(lastTime) if (isLoading) uploadState = info.failedMessage ? info.failedMessage : '读取中' if (isHashing) uploadState = info.failedMessage ? info.failedMessage : '计算sha1 ' + info.Progress + '% ' + humanTime(lastTime) if (isError && info.autoTryTime > 0) uploadState = '稍后自动重试 ' + humanTimeFM(info.autoTryTime / 1000 - now) return { UploadID: isShowTask ? TaskID : item.UploadID, TaskID: TaskID, localFilePath: path.join(localFilePath, item.partPath) , name: item.partPath || item.name, sizeStr: item.sizeStr, icon: item.isDir ? 'iconfont iconfile-folder' : 'iconfont iconwenjian', isDir: item.isDir, uploadState: uploadState, speedStr: isRunning || isHashing ? info.speedStr : '' , Progress: isSuccess ? 100 : info.Progress, ProgressStr: '', errorMessage: isError ? info.failedCode + ' ' + info.failedMessage : '' } } else { const isError = info && info.uploadState == 'error' return { UploadID: isShowTask ? TaskID : item.UploadID, TaskID: TaskID, localFilePath: path.join(localFilePath, item.partPath), name: item.partPath || item.name, sizeStr: item.sizeStr, icon: item.isDir ? 'iconfont iconfile-folder' : 'iconfont iconwenjian', isDir: item.isDir, uploadState: UploadingTaskStop.has(item.TaskID) || UploadingInfoStop.has(item.UploadID) ? '已暂停' : '排队中', speedStr: '', Progress: info ? info.Progress : 0, ProgressStr: '', errorMessage: isError ? info!.failedCode + ' ' + info!.failedMessage : '' } } } static UploadingShowListDir(showTaskID: number): { showList: IUploadingModel[]; count: number } { const showList: IUploadingModel[] = [] const now = Date.now() / 1000 const task = UploadingTaskList.get(showTaskID) if (!task) return { showList: [], count: 0 } const childrenList = task.Children for (let j = 0, maxj = childrenList.length; j < maxj; j++) { const item = childrenList[j] showList.push(UploadingData.UploadingShowOneItem(item, now, task.localFilePath, task.TaskID, false)) if (showList.length > 999) break } return { showList: showList, count: task.Children.length } } static UploadingShowProgress(): void { let progress = -1 let isRunning = false let finishSize = 0 let totalSize = 0 const values2 = UploadingInfoList.values() for (let i = 0, maxi = UploadingInfoList.size; i < maxi; i++) { const info = values2.next().value as IStateUploadInfo finishSize += info.uploadSize if (!isRunning && !UploadingInfoStop.has(info.UploadID)) isRunning = true } const values = UploadingTaskList.values() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const task = values.next().value as IStateUploadTask if (task.isDir) finishSize += task.ChildFinishSize totalSize += task.ChildTotalSize if (!isRunning && !UploadingTaskStop.has(task.TaskID)) isRunning = true } if (isRunning) { progress = Math.floor((finishSize / (totalSize + 1)) * 100) / 100 } SetProgressBar(progress, 'upload') } static async UploadingAddTask(taskList: IStateUploadTask[]): Promise { taskList.map((t) => UploadingTaskList.set(t.TaskID, t)) await DBUpload.saveUploadTaskBatch(taskList) } static async UploadingStartTask(TaskIDList: number[], isToStart: boolean): Promise { const IDList: number[] = [] const map = new Set(TaskIDList) const values = UploadingTaskList.values() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const task = values.next().value as IStateUploadTask if (map.size == 0 || map.has(task.TaskID)) { IDList.push(task.TaskID) UploadingData.StartTask(task.TaskID, isToStart) } } SaveStopToDB() return IDList } static async UploadingStartTaskFile(TaskID: number, UploadIDList: number[], isToStart: boolean): Promise { const IDList: number[] = [] const map = new Set(UploadIDList) const task = UploadingTaskList.get(TaskID) if (task) { const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { const fileItem = childrenList[i] if (map.size == 0 || map.has(fileItem.UploadID)) { IDList.push(fileItem.UploadID) if (isToStart) UploadingInfoStop.delete(fileItem.UploadID) else UploadingInfoStop.add(fileItem.UploadID) const info = UploadingInfoList.get(fileItem.UploadID) if (info) { info.uploadState = isToStart ? '排队中' : '已暂停' info.failedCode = 0 info.failedMessage = '' info.autoTryCount = 0 info.autoTryTime = 0 info.Speed = 0 info.speedStr = '' } } } if (isToStart) { UploadingTaskStop.delete(TaskID) } else { for (let i = 0, maxi = childrenList.length; i < maxi; i++) { if (UploadingInfoStop.has(childrenList[i].UploadID) == false) { UploadingTaskStop.delete(TaskID) await DBUpload.saveUploadObj('UploadingStop', { TaskIDList: Array.from(UploadingTaskStop), UploadIDList: Array.from(UploadingInfoStop) }) return IDList } } UploadingTaskStop.add(TaskID) } } SaveStopToDB() return IDList } static async UploadingDeleteTask(TaskIDList: number[]): Promise { const IDList: number[] = [] const map = new Set(TaskIDList) const values = UploadingTaskList.values() const delInfoList: number[] = [] const delTaskList: number[] = [] for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { const task = values.next().value as IStateUploadTask const TaskID = task.TaskID if (map.size == 0 || map.has(TaskID)) { IDList.push(TaskID) const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { const UploadID = childrenList[i].UploadID UploadingInfoList.delete(UploadID) if (childrenList[i].isDir == false && childrenList[i].size > 3 * 1024 * 1024) delInfoList.push(UploadID) UploadingInfoStop.delete(UploadID) } UploadingTaskList.delete(TaskID) SaveTaskList.delete(TaskID) delTaskList.push(TaskID) UploadingTaskStop.delete(TaskID) } } await DBUpload.deleteUploadInfoBatch(delInfoList) await DBUpload.deleteUploadTaskBatch(delTaskList) return IDList } static async UploadingDeleteTaskFile(TaskID: number, UploadIDList: number[]): Promise { const IDList: number[] = [] const map = new Set(UploadIDList) const task = UploadingTaskList.get(TaskID) if (task) { const newChildren: IStateUploadTaskFile[] = [] const delInfoList: number[] = [] const childrenList = task.Children for (let i = 0, maxi = childrenList.length; i < maxi; i++) { const fileItem = childrenList[i] if (map.size == 0 || map.has(fileItem.UploadID)) { IDList.push(fileItem.UploadID) delInfoList.push(fileItem.UploadID) UploadingInfoList.delete(fileItem.UploadID) if (fileItem.isDir == false && fileItem.size > 3 * 1024 * 1024) delInfoList.push(fileItem.UploadID) UploadingInfoStop.delete(fileItem.UploadID) } else { newChildren.push(fileItem) } } if (newChildren.length == 0) { UploadingTaskList.delete(TaskID) SaveTaskList.delete(TaskID) UploadingTaskStop.delete(TaskID) await DBUpload.deleteUploadTask(TaskID) } else if (delInfoList.length > 0) { task.Children = newChildren await DBUpload.saveUploadTask(task) } if (delInfoList.length > 0) await DBUpload.deleteUploadInfoBatch(delInfoList) } return IDList } static async UploadingEventSave(ReportList: IStateUploadInfo[], ErrorList: IStateUploadInfo[], SuccessList: IStateUploadTaskFile[]): Promise { for (let i = 0, maxi = ReportList.length; i < maxi; i++) { const item = ReportList[i] item.autoTryCount = UploadingInfoList.get(item.UploadID)?.autoTryCount || 0 UploadingInfoList.set(item.UploadID, item) } const time = Date.now() for (let i = 0, maxi = ErrorList.length; i < maxi; i++) { const item = ErrorList[i] item.Speed = 0 item.speedStr = '' if (item.failedMessage.indexOf('出错暂停') >= 0 || item.failedMessage.indexOf('读取文件失败') >= 0 || item.failedMessage.indexOf('没有权限') >= 0 || item.failedMessage.indexOf('不存在') >= 0 || item.failedMessage.indexOf('跳过') >= 0) { item.autoTryCount = 0 item.autoTryTime = 0 item.uploadState = 'error' UploadingInfoStop.add(item.UploadID) } else { if (UploadingInfoList.has(item.UploadID)) { item.autoTryCount = UploadingInfoList.get(item.UploadID)!.autoTryCount + 1 } else { item.autoTryCount = 1 } if (item.autoTryCount > 20) { item.autoTryCount = 0 item.autoTryTime = 0 item.uploadState = '已暂停' UploadingInfoStop.add(item.UploadID) } else { item.autoTryTime = time + 60 * 1000 * Math.min(item.autoTryCount, 10) } } UploadingInfoList.set(item.UploadID, item) } if (SuccessList.length > 0) { const delInfoList: number[] = [] let saveTaskList: number[] = [] const delTaskList: number[] = [] const saveUploadedList: IStateUploadTask[] = [] for (let i = 0, maxi = SuccessList.length; i < maxi; i++) { const fileItem = SuccessList[i] const TaskID = fileItem.TaskID const task = UploadingTaskList.get(TaskID) if (task) { if (!task.isDir && fileItem.uploaded_file_id) { task.TaskFileID = fileItem.uploaded_file_id if (!saveTaskList.includes(TaskID)) saveTaskList.push(TaskID) } let index = -1 for (let j = 0, maxj = task.Children.length; j < maxj; j++) { const itemFile = task.Children[j] if (itemFile.UploadID == fileItem.UploadID) { index = j break } } if (index >= 0) { task.Children.splice(index, 1) if (!fileItem.isDir) { task.ChildFinishCount += 1 task.ChildFinishSize += fileItem.size } if (!saveTaskList.includes(TaskID)) saveTaskList.push(TaskID) if (task.Children.length == 0) { UploadingTaskList.delete(TaskID) SaveTaskList.delete(TaskID) delTaskList.push(TaskID) UploadingTaskStop.delete(TaskID) saveUploadedList.push(task) PanDAL.aReLoadOneDirToRefreshTree(task.user_id, task.drive_id, task.parent_file_id) } UploadingInfoList.delete(fileItem.UploadID) if (fileItem.isDir == false && fileItem.size > 3 * 1024 * 1024) delInfoList.push(fileItem.UploadID) UploadingInfoStop.delete(fileItem.UploadID) } } } if (delInfoList.length > 0) await DBUpload.deleteUploadInfoBatch(delInfoList) saveTaskList = saveTaskList.filter((t) => !delTaskList.concat(t)) for (let k = 0, maxk = saveTaskList.length; k < maxk; k++) { const kitem = UploadingTaskList.get(saveTaskList[k]) if (kitem) SaveTaskList.set(kitem.TaskID, kitem) } if (SaveTaskList.size > 0) SaveTaskToDB() if (delTaskList.length > 0) await DBUpload.deleteUploadTaskBatch(delTaskList) if (saveUploadedList.length > 0) { await DBUpload.saveUploadedBatch(saveUploadedList) UploadDAL.aReloadUploaded() } if (useSettingStore().downAutoShutDown == 1) useSettingStore().downAutoShutDown = 2 } } static UploadingEventRunningCheck(RunningKeys: number[], StopKeys: number[]): { delList: number[]; newList: number[] } { let fixStop = 0 for (let i = 0, maxi = StopKeys.length; i < maxi; i++) { if (UploadingInfoStop.has(StopKeys[i]) == false) { UploadingInfoStop.add(StopKeys[i]) fixStop++ } const item = UploadingInfoList.get(StopKeys[i]) if (item && item.uploadState != '已暂停') { item.uploadState = '已暂停' } } if (fixStop > 0) SaveStopToDB() const delList: number[] = [] const newList: number[] = [] for (let i = 0, maxi = RunningKeys.length; i < maxi; i++) { if (UploadingInfoStop.has(RunningKeys[i])) delList.push(RunningKeys[i]) else newList.push(RunningKeys[i]) } return { delList: delList, newList: newList } } static UploadingEventSendList(RunningKeys: number[], LoadingKeys: number[]): IUploadingUI[] { let sendList: IUploadingUI[] = [] const time = Date.now() if (time - _UploadingSendTime > 800) { _UploadingSendTime = time const settingStore = useSettingStore() const uploadFileMax = settingStore.uploadFileMax if (settingStore.downSmallFileFirst) sendList = UploadingData._GetSendList(RunningKeys, LoadingKeys, time, uploadFileMax, true) sendList = sendList.length > 0 ? sendList.concat(UploadingData._GetSendList(RunningKeys, LoadingKeys, time, uploadFileMax, false)) : UploadingData._GetSendList(RunningKeys, LoadingKeys, time, uploadFileMax, false) } return sendList } private static _GetSendList(RunningKeys: number[], LoadingKeys: number[], time: number, uploadFileMax: number, downSmallFileFirst: boolean): IUploadingUI[] { const sendList: IUploadingUI[] = [] const values = UploadingTaskList.values() for (let i = 0, maxi = UploadingTaskList.size; i < maxi; i++) { if (RunningKeys.length >= uploadFileMax) break const task = values.next().value as IStateUploadTask if (UploadingTaskStop.has(task.TaskID)) continue const childrenList = task.Children let dirCount = 0 let fileCount = 0 for (let j = 0, maxj = childrenList.length; j < maxj; j++) { const fileItem = childrenList[j] if (UploadingInfoStop.has(fileItem.UploadID)) continue if (fileItem.isDir) { dirCount++ } else if (RunningKeys.length >= uploadFileMax) { fileCount++ } else { let info = UploadingInfoList.get(fileItem.UploadID) if (!info) { info = { UploadID: fileItem.UploadID, uploadState: '排队中', uploadSize: 0, fileSize: fileItem.isDir ? 0 : fileItem.size, Speed: 0, speedStr: '', Progress: 0, failedCode: 0, failedMessage: '', autoTryTime: 0, autoTryCount: 0, up_upload_id: '', up_file_id: '' } UploadingInfoList.set(fileItem.UploadID, info) } if (info.uploadState == 'error' && info.autoTryTime > 0 && info.autoTryTime < time) { info.uploadState = '排队中' info.failedCode = 0 info.failedMessage = '' info.Speed = 0 info.speedStr = '' } if (info.uploadState == '排队中' && (downSmallFileFirst == false || fileItem.size < 100 * 1024 * 1024)) { RunningKeys.push(fileItem.UploadID) info.uploadState = 'running' sendList.push({ IsRunning: true, TaskID: task.TaskID, UploadID: fileItem.UploadID, user_id: task.user_id, parent_file_id: task.parent_file_id, drive_id: task.drive_id, check_name_mode: task.check_name_mode, localFilePath: task.localFilePath, File: fileItem, Info: info } as IUploadingUI) } } } if (LoadingKeys.length < 2 && dirCount > 0 && fileCount < 2000 && downSmallFileFirst == false) { for (let j = 0, maxj = childrenList.length; j < maxj; j++) { const fileItem = childrenList[j] if (UploadingInfoStop.has(fileItem.UploadID)) continue if (fileItem.isDir) { let info = UploadingInfoList.get(fileItem.UploadID) if (!info) { info = { UploadID: fileItem.UploadID, uploadState: '排队中', uploadSize: 0, fileSize: fileItem.isDir ? 0 : fileItem.size, Speed: 0, speedStr: '', Progress: 0, failedCode: 0, failedMessage: '', autoTryTime: 0, autoTryCount: 0, up_upload_id: '', up_file_id: '' } UploadingInfoList.set(fileItem.UploadID, info) } if (info.uploadState == 'error' && info.autoTryTime > 0 && info.autoTryTime < time) { info.uploadState = '排队中' info.failedCode = 0 info.failedMessage = '' info.Speed = 0 info.speedStr = '' } if (info.uploadState == '排队中') { RunningKeys.push(fileItem.UploadID) info.uploadState = 'running' sendList.push({ IsRunning: true, TaskID: task.TaskID, UploadID: fileItem.UploadID, user_id: task.user_id, parent_file_id: task.parent_file_id, drive_id: task.drive_id, check_name_mode: task.check_name_mode, localFilePath: task.localFilePath, File: fileItem, Info: info } as IUploadingUI) break } } } } } return sendList } static async UploadingAppendFilesSave(TaskID: number, UploadID: number, CreatedDirID: string, AppendList: IStateUploadTaskFile[]): Promise { const task = UploadingTaskList.get(TaskID) if (task) { if (CreatedDirID) task.TaskFileID = CreatedDirID const childrenList = task.Children const fileList: IStateUploadTaskFile[] = [] const dirList: IStateUploadTaskFile[] = [] for (let i = 0, maxi = childrenList.length; i < maxi; i++) { const itemFile = childrenList[i] if (itemFile.UploadID == UploadID) continue if (itemFile.isDir) dirList.push(itemFile) else fileList.push(itemFile) } UploadingInfoList.delete(UploadID) UploadingInfoStop.delete(UploadID) let fileCount = 0 let fileSize = 0 for (let i = 0, maxi = AppendList.length; i < maxi; i++) { const item = AppendList[i] if (!item.isDir) { fileCount++ fileSize += item.size } fileList.push(item) } fileList.push(...dirList) task.ChildTotalCount += fileCount task.ChildTotalSize += fileSize task.Children = fileList if (task.Children.length == 0) { UploadingTaskList.delete(TaskID) SaveTaskList.delete(TaskID) await DBUpload.deleteUploadTask(TaskID) UploadingTaskStop.delete(TaskID) await DBUpload.saveUploadedBatch([task]) UploadDAL.aReloadUploaded() PanDAL.aReLoadOneDirToRefreshTree(task.user_id, task.drive_id, task.parent_file_id) } else { SaveTaskList.set(task.TaskID, task) SaveTaskToDB() } } } } ================================================ FILE: src/renderer/user/UserInfo.vue ================================================ ================================================ FILE: src/renderer/user/UserLogin.vue ================================================ ================================================ FILE: src/renderer/user/UserSpaceModal.vue ================================================ ================================================ FILE: src/renderer/user/userdal.ts ================================================ import DB from '../utils/db' import AliUser from '../aliapi/user' import message from '../utils/message' import useUserStore, { ITokenInfo } from './userstore' import { usePanTreeStore, usePanFileStore, useMyShareStore, useMyFollowingStore, useOtherFollowingStore, useAppStore, useFootStore } from '../store' import PanDAL from '../pan/pandal' import DebugLog from '../utils/debuglog' export const UserTokenMap = new Map() export default class UserDAL { static async aLoadFromDB() { const tokenList = await DB.getUserAll() const defaultUser = await DB.getValueString('uiDefaultUser') let defaultUserAdd = false UserTokenMap.clear() if (defaultUser) { try { for (let i = 0, maxi = tokenList.length; i < maxi; i++) { const token = tokenList[i] if (token.user_id == defaultUser && token.user_id) { const isLogin = await AliUser.ApiTokenRefreshAccount(token, false) if (isLogin) { defaultUserAdd = true await this.UserLogin(token).catch(() => {}) break } } } } catch (err: any) { DebugLog.mSaveDanger('aLoadFromDB defaultUser', err) } } for (let i = 0, maxi = tokenList.length; i < maxi; i++) { const token = tokenList[i] try { if (token.user_id != defaultUser && token.user_id) { const isLogin = await AliUser.ApiTokenRefreshAccount(token, false) if (isLogin) { if (defaultUserAdd == false) { defaultUserAdd = true await this.UserLogin(token).catch(() => {}) } } } } catch (err: any) { DebugLog.mSaveDanger('aLoadFromDB allUser ' + i + ' ' + token.user_id, err) } } console.log('defaultUserAdd', defaultUserAdd) if (defaultUserAdd == false) { useUserStore().userShowLogin = true } } static async aRefreshAllUserToken() { const tokenList = await DB.getUserAll() const dateNow = new Date().getTime() for (let i = 0, maxi = tokenList.length; i < maxi; i++) { const token = tokenList[i] try { const expire_time = new Date(token.expire_time).getTime() if (expire_time - dateNow < 1800000) await AliUser.ApiTokenRefreshAccount(token, false) } catch (err: any) { DebugLog.mSaveDanger('aRefreshAllUserToken', err) } } } static GetUserToken(user_id: string): ITokenInfo { if (user_id && UserTokenMap.has(user_id)) return UserTokenMap.get(user_id)! return { tokenfrom: 'token', access_token: '', refresh_token: '', expires_in: 0, token_type: '', user_id: '', user_name: '', avatar: '', nick_name: '', default_drive_id: '', default_sbox_drive_id: '' , role: '', status: '', expire_time: '', state: '', pin_setup: false, is_first_login: false, need_rp_verify: false, name: '', spu_id: '', is_expires: false, used_size: 0, total_size: 0, spaceinfo: '', vipname: '', vipexpire: '', pic_drive_id: '' } } static async GetUserTokenFromDB(user_id: string) { if (!user_id) return undefined if (UserTokenMap.has(user_id)) return UserTokenMap.get(user_id) const user = await DB.getUser(user_id) if (user) UserTokenMap.set(user.user_id, user) return user } static async ClearUserTokenMap() { UserTokenMap.clear() } static GetUserList() { const list: ITokenInfo[] = [] // eslint-disable-next-line no-unused-vars for (const [_, token] of UserTokenMap) { list.push(token) } return list.sort((a, b) => a.name.localeCompare(b.name)) } static SaveUserToken(token: ITokenInfo) { if (token.user_id) { UserTokenMap.set(token.user_id, token) DB.saveUser(token) .then(() => { window.WinMsgToUpload({ cmd: 'ClearUserToken' }) window.WinMsgToDownload({ cmd: 'ClearUserToken' }) }) .catch(() => {}) } } static async UserLogin(token: ITokenInfo) { const loadingKey = 'userlogin_' + Date.now().toString() message.loading('加载用户信息中...', 0, loadingKey) UserTokenMap.set(token.user_id, token) await Promise.all([AliUser.ApiUserInfo(token), AliUser.ApiUserPic(token), AliUser.ApiUserVip(token)]).catch(() => {}) useUserStore().userLogin(token.user_id) await DB.saveValueString('uiDefaultUser', token.user_id) UserDAL.SaveUserToken(token) window.WebUserToken({ user_id: token.user_id, name: token.user_name, access_token: token.access_token, login: true }) useAppStore().resetTab() useMyShareStore().$reset() useMyFollowingStore().$reset() useOtherFollowingStore().$reset() useFootStore().mSaveUserInfo(token) PanDAL.aReLoadDrive(token.user_id, token.default_drive_id) PanDAL.aReLoadQuickFile(token.user_id) // PanDAL.aReLoadDirSizeFromDB(token.user_id, token.pic_drive_id) // PanDAL.GetAllDirList(token.user_id, token.pic_drive_id) message.success('加载用户成功!', 2, loadingKey) } static async UserLogOff(user_id: string): Promise { DB.deleteUser(user_id) UserTokenMap.delete(user_id) let newUserID = '' for (const [user_id, token] of UserTokenMap) { const isLogin = token.user_id && (await AliUser.ApiTokenRefreshAccount(token, false)) if (isLogin) { await this.UserLogin(token).catch(() => {}) newUserID = user_id break } } if (!newUserID) { useUserStore().userLogOff() usePanTreeStore().$reset() usePanFileStore().$reset() useUserStore().userShowLogin = true } return newUserID != '' } static async UserClearFromDB(user_id: string): Promise { DB.deleteUser(user_id) UserTokenMap.delete(user_id) } static async UserChange(user_id: string): Promise { if (UserTokenMap.has(user_id) == false) return false const token = UserTokenMap.get(user_id)! const isLogin = token.user_id && (await AliUser.ApiTokenRefreshAccount(token, false)) if (isLogin == false) { message.warning('该账号需要重新登陆[' + token.name + ']') DB.deleteUser(user_id) UserTokenMap.delete(user_id) return false } await this.UserLogin(token).catch(() => {}) return true } static async UserRefreshByUserFace(user_id: string, force: boolean): Promise { const token = UserDAL.GetUserToken(user_id) if (!token || !token.access_token) { return false } let time = Date.now() - (new Date(token.expire_time).getTime() - token.expires_in * 1000) time = time / 1000 if (force === false || time < 600) { await Promise.all([AliUser.ApiUserInfo(token), AliUser.ApiUserPic(token), AliUser.ApiUserVip(token)]).catch(() => {}) return true } else { const isLogin = token.user_id && (await AliUser.ApiTokenRefreshAccount(token, true)) if (isLogin == false) return false await Promise.all([AliUser.ApiUserInfo(token), AliUser.ApiUserPic(token), AliUser.ApiUserVip(token)]).catch(() => {}) useUserStore().userLogin(token.user_id) return true } } static CurrUserToken(): string { return '' } } ================================================ FILE: src/renderer/user/userstore.ts ================================================ import { defineStore } from 'pinia' import UserDAL from './userdal' export interface ITokenInfo { tokenfrom: 'token' | 'account' access_token: string refresh_token: string expires_in: number token_type: string user_id: string user_name: string avatar: string nick_name: string default_drive_id: string default_sbox_drive_id: string role: string status: string expire_time: string state: string pin_setup: boolean is_first_login: boolean need_rp_verify: boolean name: string spu_id: string is_expires: boolean used_size: number total_size: number spaceinfo: string vipname: string vipexpire: string pic_drive_id: string } export interface UserState { user_id: string userLogined: boolean userShowLogin: boolean } const useUserStore = defineStore('user', { state: (): UserState => ({ user_id: '', userLogined: false, userShowLogin: false }), getters: { GetUserToken(state: UserState): ITokenInfo { return UserDAL.GetUserToken(state.user_id) } }, actions: { userLogin(user_id: string) { this.user_id = user_id this.userLogined = true }, userLogOff() { this.user_id = '' this.userLogined = false } } }) export default useUserStore ================================================ FILE: src/renderer/utils/antdtree.ts ================================================ import { EventDataNode } from 'ant-design-vue/es/tree' export function treeSelectToExpand(keys: any[], info: { event: string; selected: Boolean; nativeEvent: MouseEvent; node: EventDataNode }) { let parent = info.nativeEvent.target as HTMLElement if (parent) { for (let i = 0; i < 10; i++) { if (parent.nodeName == 'DIV' && (parent.className == 'ant-tree-treenode' || parent.className.indexOf('ant-tree-treenode ') >= 0)) break if (parent.parentElement) parent = parent.parentElement } const children = parent.children if (children) { for (let i = 0, maxi = children.length; i < maxi; i++) { if (info.node.isLeaf) { if (children[i].className.indexOf('ant-tree-checkbox') >= 0) (children[i] as HTMLElement).click() } else { if (children[i].className.indexOf('ant-tree-switcher') >= 0) (children[i] as HTMLElement).click() } } } } } ================================================ FILE: src/renderer/utils/appcache.ts ================================================ import { useSettingStore } from '../store' import DebugLog from './debuglog' import { getUserData } from './electronhelper' import { FileSystemErrorMessage } from './filehelper' import { humanSize, Sleep } from './format' import message from './message' const path = window.require('path') const fspromises = window.require('fs/promises') export default class AppCache { static async LoadDirSize(dir: string): Promise { try { const childFiles = await fspromises.readdir(dir, { withFileTypes: true }).catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('LoadDirSize失败:' + dir, err) message.error(err + ' ' + dir) return [] }) let total = 0 for (let i = 0, maxi = childFiles.length; i < maxi; i++) { if (childFiles[i].isFile()) { const stat = await fspromises.lstat(path.join(dir, childFiles[i].name)).catch(() => { return { size: 0 } }) total += stat.size } else if (childFiles[i].isDirectory()) { total += await AppCache.LoadDirSize(path.join(dir, childFiles[i].name)) } } return total } catch { return 0 } } static DeleteDir(dir: string): Promise { return fspromises .rm(dir, { force: true, recursive: true }) .then(() => {}) .catch(() => {}) } static async aLoadCacheSize(): Promise { const userData = getUserData() if (!userData) return const dirSize = await AppCache.LoadDirSize(userData) if (dirSize > 800 * 1024 * 1024) message.warning('缓存文件夹体积较大,该去 设置 里清理了') useSettingStore().debugCacheSize = humanSize(dirSize) } static async aClearCache(delby: string): Promise { const dir = getUserData() // await AppCache.DeleteDir(path.join(dir, 'Cache')) if (delby == 'all') { // window.WebClearCache({ cache: true }) if (window.WebClearCache) window.WebClearCache({ storages: ['appcache', 'cookies', 'filesystem', 'shadercache', 'serviceworkers', 'cachestorage', 'indexdb', 'localstorage', 'websql'], quotas: ['temporary', 'persistent', 'syncable'] }) } else { // window.WebClearCache({ cache: true }) if (window.WebClearCache) window.WebClearCache({ storages: ['appcache', 'cookies', 'filesystem', 'shadercache', 'serviceworkers', 'cachestorage'], quotas: ['temporary', 'persistent', 'syncable'] }) } if (delby == 'all') { await AppCache.DeleteDir(path.join(dir, 'databases')).catch(() => {}) await AppCache.DeleteDir(path.join(dir, 'IndexedDB')).catch(() => {}) await AppCache.DeleteDir(path.join(dir, 'Local Storage')).catch(() => {}) await AppCache.DeleteDir(path.join(dir, 'Session Storage')).catch(() => {}) } else if (delby == 'db') { await AppCache.DeleteDir(path.join(dir, 'databases')).catch(() => {}) } await AppCache.DeleteDir(path.join(dir, 'Code Cache', 'js')).catch(() => {}) await AppCache.DeleteDir(path.join(dir, 'Code Cache', 'wasm')).catch(() => {}) await Sleep(4000) if (delby == 'all') { message.success('删除全部数据成功,自动重启小白羊') Sleep(3000).then(() => { window.WebRelaunch() }) } else if (delby == 'db') { message.success('删除数据库成功,自动重启小白羊') Sleep(3000).then(() => { window.WebRelaunch() }) } else { message.success('清理缓存成功,自动重启小白羊') Sleep(3000).then(() => { // window.WebReload() window.WebRelaunch() }) } } } ================================================ FILE: src/renderer/utils/config.ts ================================================ export default class Config { static appVersion = 'v3.05.23' static referer = 'https://www.aliyundrive.com/' static downAgent = 'okhttp/4.2.2' static userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Edg/102.0.1245.33' static loginUrl = 'https://auth.aliyundrive.com/v2/oauth/authorize?login_type=custom&response_type=code&redirect_uri=https%3A%2F%2Fwww.aliyundrive.com%2Fsign%2Fcallback&client_id=25dzX3vbYqktVxyX&state=%7B%22origin%22%3A%22https%3A%2F%2Fwww.aliyundrive.com%2F%22%7D' static loginUrlAccount = 'https://passport.aliyundrive.com/mini_login.htm?lang=zh_cn&appName=aliyun_drive&appEntrance=web&styleType=auto&bizParams=¬LoadSsoView=false¬KeepLogin=false&isMobile=false&&rnd=0.1100330129139' } ================================================ FILE: src/renderer/utils/db.ts ================================================ import Dexie from 'dexie' import { ITokenInfo } from '../user/userstore' import { IOtherShareLinkModel } from '../share/share/OtherShareStore' export interface ICache { key: string time: number value: object } class XBYDB3 extends Dexie { iobject: Dexie.Table istring: Dexie.Table inumber: Dexie.Table ibool: Dexie.Table itoken: Dexie.Table iothershare: Dexie.Table constructor() { super('XBYDB3') this.version(1) .stores({ iobject: '', istring: '', inumber: '', ibool: '', itoken: '', iothershare: '' }) .upgrade((tx: any) => { console.log('upgrade', tx) }) this.iobject = this.table('iobject') this.istring = this.table('istring') this.inumber = this.table('inumber') this.ibool = this.table('ibool') this.itoken = this.table('itoken') this.iothershare = this.table('iothershare') } async getValueString(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.istring.get(key) if (val) return val else return '' } async saveValueString(key: string, value: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.istring.put(value || '', key) } async saveValueStringBatch(keys: string[], values: string[]): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.istring.bulkPut(values, keys) } async getValueNumber(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.inumber.get(key) if (val) return val return 0 } async saveValueNumber(key: string, value: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.inumber.put(value, key) } async getValueBool(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.ibool.get(key) if (val) return true return false } async saveValueBool(key: string, value: boolean): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.ibool.put(value || false, key) } async getValueObject(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.iobject.get(key) if (val) return val else return undefined } async saveValueObject(key: string, value: object): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iobject.put(value, key).catch(() => {}) } async saveValueObjectBatch(keys: string[], values: object[]): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iobject.bulkPut(values, keys) } async deleteValueObject(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iobject.delete(key) } async getUser(user_id: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.itoken, () => { return this.itoken.get(user_id) }) } async getUserAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const list = await this.transaction('r', this.itoken, () => { return this.itoken.toArray() }) return list.sort((a: ITokenInfo, b: ITokenInfo) => b.used_size - a.used_size) } async deleteUser(user_id: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.itoken.delete(user_id) } async saveUser(token: ITokenInfo): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.itoken.put(token, token.user_id).catch(() => {}) } async getOtherShare(share_id: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.iothershare.get(share_id) } async getOtherShareAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const list = await this.iothershare.toArray() return list.sort((a: IOtherShareLinkModel, b: IOtherShareLinkModel) => b.saved_time - a.saved_time) } async deleteOtherShareBatch(share_id_list: string[]): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iothershare.bulkDelete(share_id_list) } async saveOtherShare(share: IOtherShareLinkModel): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iothershare.put(share, share.share_id).catch(() => {}) } } const DB = new XBYDB3() export default DB ================================================ FILE: src/renderer/utils/dbcache.ts ================================================ import Dexie from 'dexie' import { IStateDebugLog } from './debuglog' export interface IStateFileHash { size: number mtime: number presha1: string sha1: string name: string } class XBYDB3Cache extends Dexie { ilog: Dexie.Table ifilehash: Dexie.Table iobject: Dexie.Table constructor() { super('XBYDB3Cache') this.version(1) .stores({ ilog: '&logid', ifilehash: '++id,[size+mtime]', iobject: '' }) .upgrade((tx: any) => { console.log('upgrade', tx) }) this.ilog = this.table('ilog') this.ifilehash = this.table('ifilehash') this.iobject = this.table('iobject') } async saveLog(value: IStateDebugLog) { if (!this.isOpen()) await this.open().catch(() => {}) return this.ilog.put(value).catch(() => {}) } async getLogAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.ilog, () => { return this.ilog.reverse().limit(500).toArray() }) } async deleteLogAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.ilog.clear() } async deleteLogOutCount(max: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const count = await this.ilog.count() if (count > max) { return this.ilog.limit(max - count).delete() } return 0 } async getFileHashList(size: number, mtime: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.ifilehash.where({ size, mtime }).toArray() } async getFileHash(size: number, mtime: number, prehash: string, name: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const hashList = await this.ifilehash.where({ size, mtime }).toArray() for (let i = 0, maxi = hashList.length; i < maxi; i++) { if (hashList[i].presha1 == prehash && hashList[i].name == name) { return hashList[i].sha1 } } return '' } async saveFileHash(value: IStateFileHash) { if (!this.isOpen()) await this.open().catch(() => {}) return this.ifilehash.put(value).catch(() => {}) } } const DBCache = new XBYDB3Cache() export default DBCache ================================================ FILE: src/renderer/utils/dbdown.ts ================================================ import Dexie from 'dexie' export interface IDowningInfo { key: string time: number fileCount: number fileSize: number dirCount: number } class XBYDB3Down extends Dexie { downingProgress: Dexie.Table downingInfo: Dexie.Table downingGzip: Dexie.Table downedGzip: Dexie.Table constructor() { super('XBYDB3Down') this.version(1) .stores({ downingProgress: '', downingInfo: 'key', downingGzip: '', downedGzip: '' }) .upgrade((tx: any) => { console.log('upgrade', tx) }) this.downingProgress = this.table('downingProgress') this.downingInfo = this.table('downingInfo') this.downingGzip = this.table('downingGzip') this.downedGzip = this.table('downedGzip') } async getDowningGzip(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.downingGzip.get(key) if (val) return val else return undefined } async deleteDowningGzip(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingGzip.delete(key) } async saveDowningGzip(key: string, value: Buffer): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingGzip.put(value, key).catch(() => {}) } async deleteDowningGzipAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingGzip.clear() } async getDownedGzip(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.downedGzip.get(key) if (val) return val else return undefined } async deleteDownedGzip(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downedGzip.delete(key) } async saveDownedGzip(key: string, value: Buffer): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downedGzip.put(value, key).catch(() => {}) } async deleteDownedGzipAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downedGzip.clear() } async getDowningInfo(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.downingInfo.get(key) if (val) return val else return undefined } async deleteDowningInfo(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingInfo.delete(key) } async saveDowningInfo(key: string, value: IDowningInfo): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingInfo.put(value, key).catch(() => {}) } async deleteDowningInfoAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingInfo.clear() } async getDowningProgress(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const val = await this.downingProgress.get(key) if (val) return val else return undefined } async deleteDowningProgress(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingProgress.delete(key) } async saveDowningProgress(key: string, value: object): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingProgress.put(value, key).catch(() => {}) } async deleteDowningProgressAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.downingProgress.clear() } } const DB = new XBYDB3Down() export default DB ================================================ FILE: src/renderer/utils/dbupload.ts ================================================ import Dexie from 'dexie' export interface IStateUploadTaskFile { TaskID: number UploadID: number partPath: string name: string size: number sizeStr: string mtime: number isDir: boolean IsRoot: boolean uploaded_is_rapid: boolean uploaded_file_id: string } export interface IStateUploadTask { TaskID: number TaskName: string TaskFileID: string user_id: string parent_file_id: string drive_id: string check_name_mode: string isDir: boolean localFilePath: string Children: IStateUploadTaskFile[] ChildTotalCount: number ChildFinishCount: number ChildTotalSize: number ChildFinishSize: number } export declare type UploadState = | '排队中' // 排队中, 等待上传 | '读取中' // 读取文件夹包含的文件列表 | 'hashing' // 计算hash,预秒传,秒传 | 'running' // 上传中 | '已暂停' // 已暂停 | 'success' // 上传成功 | 'error' // 上传失败 export interface IStateUploadInfo { UploadID: number uploadState: UploadState up_upload_id: string up_file_id: string uploadSize: number fileSize: number Speed: number speedStr: string Progress: number failedCode: number failedMessage: string autoTryTime: number autoTryCount: number } export interface IUploadingUI { IsRunning: boolean TaskID: number UploadID: number user_id: string parent_file_id: string drive_id: string check_name_mode: string localFilePath: string File: IStateUploadTaskFile Info: IStateUploadInfo } class XBYDB3Upload extends Dexie { iuploadtask: Dexie.Table iuploadinfo: Dexie.Table iuploaded: Dexie.Table iobject: Dexie.Table constructor() { super('XBYDB3Upload1024') this.version(1) .stores({ iuploadtask: '&TaskID', iuploadinfo: '&UploadID', iuploaded: '++,&TaskID', iobject: '' }) .upgrade((tx: any) => { console.log('upgrade', tx) }) this.iuploadtask = this.table('iuploadtask') this.iuploadinfo = this.table('iuploadinfo') this.iuploaded = this.table('iuploaded') this.iobject = this.table('iobject') } async getUploadTask(key: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploadtask, () => { return this.iuploadtask.get(key) }) } async getUploadTaskAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploadtask, () => { return this.iuploadtask.toArray() }) } async getUploadTaskAllKeys(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploadtask, () => { return this.iuploadtask.toCollection().primaryKeys() }) } async getUploadTaskCount(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploadtask, () => { return this.iuploadtask.count() }) } async deleteUploadTask(key: number): Promise { console.log('deleteUploadTask', key) if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadtask.delete(key) } async deleteUploadTaskBatch(keys: number[]): Promise { console.log('deleteUploadTaskBatch', keys) if (keys.length == 0) return if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadtask.bulkDelete(keys) } async deleteUploadInfo(key: number): Promise { console.log('deleteUploadInfo', key) if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadinfo.delete(key) } async deleteUploadInfoBatch(keys: number[]): Promise { console.log('deleteUploadInfoBatch', keys) if (keys.length == 0) return if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadinfo.bulkDelete(keys) } async saveUploadTask(value: IStateUploadTask) { console.log('saveUploadTask', value.TaskID) if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadtask.put(value).catch(() => {}) } async saveUploadTaskBatch(values: IStateUploadTask[]) { console.log('saveUploadTaskBatch', values.length) if (values.length == 0) return if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadtask.bulkPut(values).catch(() => {}) } async clearUploadTaskAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) await this.iuploadinfo.clear() await this.iuploadtask.clear() await this.iobject.delete('UploadingStop') } async saveUploadInfo(value: IStateUploadInfo) { console.log('saveUploadInfo', value.UploadID) if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadinfo.put(value).catch(() => {}) } async saveUploadInfoBatch(values: IStateUploadInfo[]) { console.log('saveUploadInfoBatch', values.length) if (values.length == 0) return if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploadinfo.bulkPut(values).catch(() => {}) } async getUploadInfoAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploadinfo, () => { return this.iuploadinfo.toArray() }) } async getUploaded(key: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploaded, () => { return this.iuploaded.where('TaskID').equals(key).first() }) } async getUploadedByTop(limit: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploaded, () => { return this.iuploaded.reverse().limit(limit).toArray() }) } async getUploadedCount(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iuploaded, () => { return this.iuploaded.count() }) } async deleteUploaded(key: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploaded.where('TaskID').equals(key).delete() } async deleteUploadedBatch(keys: number[]): Promise { if (keys.length == 0) return 0 if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploaded.where('TaskID').anyOf(keys).delete() } async saveUploaded(value: IStateUploadTask) { console.log('saveUploaded', value.TaskID) if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploaded.put(value).catch(() => {}) } async saveUploadedBatch(values: IStateUploadTask[]) { console.log('saveUploadedBatch', values.length) if (values.length == 0) return if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploaded.bulkPut(values).catch(() => {}) } async deleteUploadedOutCount(max: number): Promise { if (!this.isOpen()) await this.open().catch(() => {}) const count = await this.iuploaded.count() if (count > max) { return this.iuploaded.limit(max - count).delete() } return 0 } async clearUploadedAll(): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iuploaded.clear() } async getUploadObj(key: string): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return await this.transaction('r', this.iobject, () => { return this.iobject.get(key) }) } async saveUploadObj(key: string, value: object): Promise { if (!this.isOpen()) await this.open().catch(() => {}) return this.iobject.put(value, key).catch(() => {}) } } const DBUpload = new XBYDB3Upload() export default DBUpload ================================================ FILE: src/renderer/utils/debounce.ts ================================================ import message from './message' export function debounce(func: Function, wait: number, immediate: boolean = true, lastCall: boolean = true, leakCall: boolean = false) { if (lastCall !== false) lastCall = true if (immediate !== false) immediate = true let previous = 0 let timer: any return function (...args: any) { // @ts-ignore const context = this const now = Date.now() const timeoutToCall = function timeoutToCall() { if (!leakCall && timer) { clearTimeout(timer) timer = undefined } if (!timer) { timer = setTimeout(function () { timer = undefined func.apply(context, args) }, wait) } } if (now - previous > wait) { previous = now if (immediate) { func.apply(context, args) } else if (lastCall) { timeoutToCall() } } else { previous = now if (lastCall) timeoutToCall() } } } export function throttle(func: Function, wait: number, immediate: boolean = true, lastCall: boolean = true) { return debounce(func, wait, immediate, lastCall, true) } const clkcimap = new Set() export function clickWait(cmdkey: string, wait: number = -1): boolean { if (clkcimap.has(cmdkey)) { message.info('上一个操作还在执行中,稍等1秒再点') return true } clkcimap.add(cmdkey) if (wait > 0) { setTimeout(() => { clkcimap.delete(cmdkey) }, wait) } return false } export function clickWaitDelete(cmdkey: string): void { clkcimap.delete(cmdkey) } ================================================ FILE: src/renderer/utils/debuglog.ts ================================================ import { useLogStore } from '../store' import DBCache from './dbcache' export interface IStateDebugLog { logid: number logtime: string logtype: string logmessage: string } class DebugLogC { public logList: IStateDebugLog[] = [] public logTime: number = 0 mSaveLogClear() { this.logList = [] this.logTime = Date.now() try { DBCache.deleteLogAll().catch(() => {}) useLogStore().logRefresh(this.logTime) } catch {} } mSaveDanger(logmessage: string, err: any = undefined) { this.mSaveLog('danger', logmessage, err) } mSaveWarning(logmessage: string, err: any = undefined) { this.mSaveLog('warning', logmessage, err) } mSaveSuccess(logmessage: string, err: any = undefined) { this.mSaveLog('success', logmessage, err) } mSaveLog(logtype: string, logmessage: string, err: any) { if (!logmessage && !err) return if (logmessage && typeof logmessage == 'string' && logmessage.length > 500) logmessage = logmessage.substring(0, 500) + '...' const time = new Date() if (this.logList.length > 500) { this.logList.splice(400) DBCache.deleteLogOutCount(400) } const log = { logid: time.getTime(), logtime: time.getDate().toString().padStart(2, '0') + ' ' + time.getHours().toString().padStart(2, '0') + ':' + time.getMinutes().toString().padStart(2, '0') + ':' + time.getSeconds().toString().padStart(2, '0'), logtype: logtype, logmessage: logmessage } if (err) { if (typeof err == 'string') { log.logmessage = logmessage + ' \n//== Error ==//\n ' + err } else if (err.message) { let m = err.message + (err.stack ? ' \n//== Stack ===//\n ' + err.stack : '') if (m.length > 500) m = m.substring(0, 500) + '...' log.logmessage = logmessage + ' \n//== Error ==//\n ' + m } else { try { log.logmessage = logmessage + ' \n//== Error ==//\n ' + JSON.stringify(err) } catch { log.logmessage = logmessage + ' \n//== Error ==//\n stringify failed' } } } this.logList = [log].concat(this.logList) this.logTime = time.getTime() try { DBCache.saveLog(log).catch(() => {}) useLogStore().logRefresh(this.logTime) } catch {} } async aLoadFromDB() { const logList2 = await DBCache.getLogAll() if (logList2) this.logList = logList2 as IStateDebugLog[] this.logTime = Date.now() } } const DebugLog = new DebugLogC() export default DebugLog ================================================ FILE: src/renderer/utils/electronhelper.ts ================================================ import { throttle } from './debounce' export function getFromClipboard(): string { return window.Electron.clipboard.readText() as string } export function copyToClipboard(text: string): void { window.Electron.clipboard.writeText(text, 'clipboard') } export function openExternal(url: string): void { window.Electron.shell.openExternal(url) } const ElectronPath = { AppUserData: '', AppResourcesPath: '', AppPlatform: '', AppArch: '', AppExecPath: '', AppUserName: '', env: '' } function LoadElectronPath(): void { if (!ElectronPath.AppUserData) { ElectronPath.AppPlatform = process.platform ElectronPath.AppArch = process.arch ElectronPath.AppExecPath = process.execPath ElectronPath.env = JSON.stringify(process.env) ElectronPath.AppUserName = process.env.USERNAME || process.env.USER || '' ElectronPath.AppResourcesPath = (process as any).resourcesPath if (window.WebPlatformSync) { window.WebPlatformSync((data: { appPath: string; execPath: string }) => { ElectronPath.AppUserData = data.appPath ElectronPath.AppExecPath = data.execPath window.Electron.WebPlatformSync = data }) } window.Electron.ElectronPath = ElectronPath } } export function getUserData(): string { LoadElectronPath() return ElectronPath.AppUserData } const path = window.require('path') export function getResourcesPath(fileName: string): string { try { LoadElectronPath() return path.join(ElectronPath.AppResourcesPath, fileName) as string } catch { return '' } } export function getAppNewPath(): string { try { LoadElectronPath() return path.join(ElectronPath.AppResourcesPath, 'app.new') as string } catch { return '' } } let ProgressBarBy = '' let ProgressBarValue = -1 let ProgressBarNew = -1 const setProgressBar = throttle(() => { ProgressBarValue = ProgressBarNew const mode = ProgressBarValue < 0 ? 'none' : ProgressBarBy == 'download' ? 'normal' : 'paused' if (window.WebSetProgressBar) window.WebSetProgressBar({ pro: ProgressBarValue, mode }) }, 5000) export function SetProgressBar(value: number, by: string): void { if (value < 0) value = -1 if (ProgressBarValue == value && ProgressBarBy == by) return ProgressBarNew = value ProgressBarBy = by if (value < 0 || (ProgressBarValue < 0 && value > 0)) { const mode = value < 0 ? 'none' : ProgressBarBy == 'download' ? 'normal' : 'paused' ProgressBarValue = value if (window.WebSetProgressBar) window.WebSetProgressBar({ pro: ProgressBarValue, mode: mode }) } else { setProgressBar() } } ================================================ FILE: src/renderer/utils/filehelper.ts ================================================ import DebugLog from './debuglog' const fspromises = window.require('fs/promises') export async function OpenFileHandle(filepath: string): Promise<{ handle: any; error: string }> { const result: { handle: any; error: string } = { handle: undefined, error: '' } const fileHandle = await fspromises.open(filepath, 'r').catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('UpOne上传文件失败:' + filepath, err) result.error = err return undefined }) if (fileHandle) result.handle = fileHandle return result } export function FileSystemErrorMessage(code: string, message: string): string { if (!code && !message) return '读取文件失败' if (code) { switch (code) { case 'EACCES': return '没有权限访问' case 'EEXIST': return '存在重名文件' case 'EISDIR': return '不能是文件夹' case 'EMFILE': return '同时打开文件过多' case 'ENFILE': return '同时打开文件过多' case 'ENOENT': return '该路径不存在' case 'ENOTDIR': return '不能是文件' case 'ENOTEMPTY': return '文件夹不为空' case 'EPERM': return '没有权限访问' case 'EBUSY': return '文件被其他程序占用' case 'ETIMEDOUT': return '操作超时' case 'EDQUOT': return '超出磁盘配额' case 'EFBIG': return '文件太大' case 'EIDRM': return '文件已被删除' case 'EIO': return 'IO错误' case 'ELOOP': return '路径级别过多' case 'ENAMETOOLONG': return '文件名太长' case 'ENODEV': return '找不到设备' case 'ENOMEM': return '没有足够的空间' case 'ENOSPC': return '没有可用空间' case 'EROFS': return '只读文件' } } if (message && typeof message == 'string' && message.indexOf('EACCES') >= 0) return '没有权限访问' const err = (code || '') + (message || '') if (err) return err return '读取文件失败' } export function ClearFileName(fileName: string): string { if (!fileName) return '' fileName = fileName.replace(/[<>:"/\\|?*]+/g, '') fileName = fileName.replace(/[\f\n\r\t\v]/g, '') while (fileName.endsWith(' ') || fileName.endsWith('.')) fileName = fileName.substring(0, fileName.length - 1) while (fileName.startsWith(' ')) fileName = fileName.substring(1) if (window.platform == 'win32') { // donothing } else if (window.platform == 'darwin') { while (fileName.startsWith('.')) fileName = fileName.substring(1) } else if (window.platform == 'linux') { // donothing } return fileName } export function CheckFileName(fileName: string): string { if (!fileName) return '不能为空' if (fileName.match(/[<>:"/\\|?*]+/g)) return '不能包含 < > : " / \\ | ? * ' if (fileName.match(/[\f\n\r\t\v]/g)) return '不能包含 \\f \\n \\r \\t \\v' if (fileName.endsWith(' ') || fileName.endsWith('.')) return '不能以空格或.结尾' if (fileName.startsWith(' ')) return '不能以空格开头' if (window.platform == 'win32') { // donothing } else if (window.platform == 'darwin') { if (fileName.startsWith('.')) return '不能以.开头' } else if (window.platform == 'linux') { // donothing } return '' } export function CleanStringForCmd(title: string) { title = title.replace(/[<>"/\\|?* '&%$^`,;=()![\]\-~#]+/g, '') return title } export function CheckWindowsBreakPath(filePath: string) { if (filePath.endsWith('$RECYCLE.BIN')) return true if (filePath.endsWith('$Recycle.Bin')) return true if (filePath.endsWith('$LOGFILE')) return true if (filePath.endsWith('$VOLUME')) return true if (filePath.endsWith('$BITMAP')) return true if (filePath.endsWith('$MFT')) return true if (filePath.endsWith('$WINDOWS.~BT')) return true if (filePath.endsWith('$WinREAgent')) return true if (filePath.endsWith('$GetCurrent')) return true if (filePath.endsWith('$SysReset')) return true if (filePath.endsWith('$Windows.~WS')) return true if (filePath.endsWith('System Volume Information')) return true if (filePath.endsWith('Documents and Settings')) return true if (filePath.endsWith('Config.Msi')) return true if (filePath.endsWith('pagefile.sys')) return true if (filePath.endsWith('swapfile.sys')) return true if (filePath.endsWith('hiberfil.sys')) return true return false } ================================================ FILE: src/renderer/utils/filenameorder.ts ================================================ import { IAliGetFileModel } from '../aliapi/alimodels' import { DirData } from '../store/treestore' export function OrderNode(order: string, list: DirData[]) { const orders = order.split(' ') const orderby = orders[0].toLowerCase() order = orders[1].toLowerCase() if (orderby == 'size' && order == 'asc') return OrderBySizeAsc(list) if (orderby == 'size' && order == 'desc') return OrderBySizeDesc(list) if (orderby == 'updated_at' && order == 'asc') return OrderByTimeAsc(list) if (orderby == 'updated_at' && order == 'desc') return OrderByTimeDesc(list) if (orderby == 'name' && order == 'asc') return OrderByNameAsc(list) if (orderby == 'name' && order == 'desc') return OrderByNameDesc(list) return list } export function OrderDir(orderby: string, order: string, list: IAliGetFileModel[]) { orderby = orderby.toLowerCase() order = order.toLowerCase() if (orderby == 'size' && order == 'asc') return OrderBySizeAsc(list) if (orderby == 'size' && order == 'desc') return OrderBySizeDesc(list) if (orderby == 'updated_at' && order == 'asc') return OrderByTimeAsc(list) if (orderby == 'updated_at' && order == 'desc') return OrderByTimeDesc(list) if (orderby == 'name' && order == 'asc') return OrderByNameAsc(list) if (orderby == 'name' && order == 'desc') return OrderByNameDesc(list) return list } export function OrderFile(orderby: string, order: string, list: IAliGetFileModel[]) { orderby = orderby.toLowerCase() order = order.toLowerCase() if (orderby == 'size' && order == 'asc') return OrderBySizeAsc(list) if (orderby == 'size' && order == 'desc') return OrderBySizeDesc(list) if (orderby == 'updated_at' && order == 'asc') return OrderByTimeAsc(list) if (orderby == 'updated_at' && order == 'desc') return OrderByTimeDesc(list) if (orderby == 'name' && order == 'asc') return OrderByNameAsc(list) if (orderby == 'name' && order == 'desc') return OrderByNameDesc(list) return list } function OrderByTimeAsc(list: { time: number; name: string }[]) { let t = 0 return list.sort(function (a, b) { t = a.time - b.time if (t == 0) return _OrderName(a.name, b.name) else return t }) } function OrderByTimeDesc(list: { time: number; name: string }[]) { return list.sort(function (b, a) { const t = a.time - b.time if (t == 0) return _OrderName(a.name, b.name) else return t }) } function OrderBySizeAsc(list: { size: number; name: string }[]) { return list.sort(function (a, b) { const t = a.size - b.size if (t == 0) return _OrderName(a.name, b.name) else return t }) } function OrderBySizeDesc(list: { size: number; name: string }[]) { return list.sort(function (b, a) { const t = a.size - b.size if (t == 0) return _OrderName(a.name, b.name) else return t }) } function OrderByNameAsc(list: { name: string }[]) { return list.sort(function (a, b) { return _OrderName(a.name, b.name) }) } function OrderByNameDesc(list: { name: string }[]) { return list.sort(function (b, a) { return _OrderName(a.name, b.name) }) } const intlcn = new Intl.Collator(['zh-CN-u-co-pinyin', 'jp', 'en'], { numeric: true }) const intlen = new Intl.Collator(['en', 'zh-CN-u-co-pinyin', 'jp'], { numeric: true }) const azreg = new RegExp('[a-zA-Z]') function _OrderName(a: string, b: string) { a = replaceHanNumber(a) b = replaceHanNumber(b) if (azreg.test(a.charAt(0)) || azreg.test(b.charAt(0))) return intlen.compare(a, b) return intlcn.compare(a, b) } function replaceHanNumber(a: string): string { let b = '' let c = '' for (let i = 0, maxi = a.length; i < maxi; i++) { c = a[i] switch (c) { case '零': b += '0' break case '一': b += '1' break case 'Ⅰ': b += '1' break case '壹': b += '1' break case '二': b += '2' break case 'Ⅱ': b += '2' break case '贰': b += '2' break case '三': b += '3' break case 'Ⅲ': b += '3' break case '叁': b += '3' break case '四': b += '4' break case 'Ⅳ': b += '4' break case '肆': b += '4' break case '五': b += '5' break case 'Ⅴ': b += '5' break case '伍': b += '5' break case '六': b += '6' break case 'Ⅵ': b += '6' break case '陆': b += '6' break case '七': b += '7' break case 'Ⅶ': b += '7' break case '柒': b += '7' break case '八': b += '8' break case 'Ⅷ': b += '8' break case '捌': b += '8' break case '九': b += '9' break case 'Ⅸ': b += '9' break case '玖': b += '9' break case '十': b += '' break case 'Ⅹ': b += '' break case '拾': b += '' break case '百': b += '' break case '佰': b += '' break case '千': b += '' break case '仟': b += '' break case '万': b += '' break default: b += c } } return b } ================================================ FILE: src/renderer/utils/foot.ts ================================================ const FootMap = new Map() export function FootLoading(msg: string, key: string) { console.log('FootLoading', key, msg) if (msg != '') FootMap.set(key, msg) else FootMap.delete(key) let info = '' FootMap.forEach(function (value, key) { const item = '' + value + '' if (info.includes(item) == false) info += item }) const doc = document.getElementById('footLoading') if (doc) { if (!info) { doc.innerHTML = '' } else { doc.innerHTML = '
' + info } } } ================================================ FILE: src/renderer/utils/format.ts ================================================ const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] export function humanSize(bytes: number | string | undefined): string { if (!bytes && bytes != 0) return '' if (typeof bytes === 'string') bytes = parseInt(bytes) let u = 0 while (bytes >= 1024 && u < units.length - 1) { bytes /= 1024 ++u } return `${bytes.toFixed(2)}${units[u]}` } const speedunits = ['B', 'KB', 'M', 'G'] export function humanSizeSpeed(bytes: number | string | undefined): string { if (!bytes && bytes != 0) return '' if (typeof bytes === 'string') bytes = parseInt(bytes) let u = 0 while (bytes >= 1024 && u < speedunits.length - 1) { bytes /= 1024 ++u } if (bytes > 100) return `${bytes.toFixed(0)}${speedunits[u]}/s` if (bytes > 10) return `${bytes.toFixed(1)}${speedunits[u]}/s` return `${bytes.toFixed(2)}${units[u]}/s` } export function humanCount(bytes: number) { if (bytes < 1000) return bytes if (bytes < 10000) return (bytes / 1000).toFixed(2) + 'K' return (bytes / 10000).toFixed(2) + '万' } const byTime = [365 * 24 * 60 * 60 * 1000, 24 * 60 * 60 * 1000, 60 * 60 * 1000, 60 * 1000, 1000] const unit = ['年', '天', '小时', '分钟', '秒'] export function humanTimeAgo(value: number | string | undefined): string { if (!value) return '' if (typeof value === 'string') value = parseInt(value) if (value > 1000000000 && value < 10000000000) value = value * 1000 const date = new Date(value) let ct = new Date().getTime() - date.getTime() if (ct < 0) return '' const sb = [] for (let i = 0; i < byTime.length; i++) { if (ct < byTime[i]) { continue } const temp = Math.floor(ct / byTime[i]) ct = ct % byTime[i] if (temp > 0) { sb.push(temp + unit[i]) } /* sb.length控制最多输出几个时间单位: 一个时间单位如:N分钟前 两个时间单位如:M分钟N秒前 三个时间单位如:M年N分钟X秒前 */ if (sb.length >= 1) { break } } return sb.join('') + '前' } export function humanDateTime(value: number | string | undefined): string { if (!value) return '' if (typeof value === 'string') value = parseInt(value) if (value > 1000000000 && value < 10000000000) value = value * 1000 const date = new Date(value) const y = date.getFullYear().toString() if (y == 'NaN') return '' let m: number | string = date.getMonth() + 1 m = m < 10 ? '0' + m.toString() : m.toString() let d: number | string = date.getDate() d = d < 10 ? '0' + d.toString() : d.toString() let h: number | string = date.getHours() h = h < 10 ? '0' + h.toString() : h.toString() let minute: number | string = date.getMinutes() minute = minute < 10 ? '0' + minute.toString() : minute.toString() let second: number | string = date.getSeconds() second = second < 10 ? '0' + second.toString() : second.toString() return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second } export function humanDateTimeYMD(value: number | string | undefined): string { if (!value) return '' if (typeof value === 'string') value = parseInt(value) if (value > 1000000000 && value < 10000000000) value = value * 1000 const date = new Date(value) const y = date.getFullYear().toString() if (y == 'NaN') return '' let m: number | string = date.getMonth() + 1 m = m < 10 ? '0' + m.toString() : m.toString() let d: number | string = date.getDate() d = d < 10 ? '0' + d.toString() : d.toString() return y + '-' + m + '-' + d } export function humanDateTimeDateStr(value: string | undefined): string { if (!value) return '' const date = new Date(value) const y = date.getFullYear().toString() if (y == 'NaN') return '' let m: number | string = date.getMonth() + 1 m = m < 10 ? '0' + m.toString() : m.toString() let d: number | string = date.getDate() d = d < 10 ? '0' + d.toString() : d.toString() let h: number | string = date.getHours() h = h < 10 ? '0' + h.toString() : h.toString() let minute: number | string = date.getMinutes() minute = minute < 10 ? '0' + minute.toString() : minute.toString() let second: number | string = date.getSeconds() second = second < 10 ? '0' + second.toString() : second.toString() return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second } export function humanDateTimeDateStrYMD(value: string | undefined): string { if (!value) return '' const date = new Date(value) const y = date.getFullYear().toString() if (y == 'NaN') return '' let m: number | string = date.getMonth() + 1 m = m < 10 ? '0' + m.toString() : m.toString() let d: number | string = date.getDate() d = d < 10 ? '0' + d.toString() : d.toString() return y + '-' + m + '-' + d } export function humanTime(value: number | string | undefined): string { if (!value) return '' if (typeof value === 'string') value = parseInt(value) const hours = Math.floor(value / 3600) value = value % 3600 const minutes = Math.floor(value / 60) value = value % 60 const seconds = Math.floor(value) const hourStr = (hours < 10 ? '0' : '') + String(hours) const minStr = (minutes < 10 ? '0' : '') + String(minutes) const secStr = (seconds < 10 ? '0' : '') + String(seconds) return hourStr + ':' + minStr + ':' + secStr } export function humanTimeFM(value: number | string | undefined): string { if (!value) return '' if (typeof value === 'string') value = parseInt(value) if (value <= 0) return '00:00' const minutes = Math.floor(value / 60) value = value % 60 const seconds = Math.floor(value) const minStr = (minutes < 10 ? '0' : '') + String(minutes) const secStr = (seconds < 10 ? '0' : '') + String(seconds) return minStr + ':' + secStr } export function humanExpiration(expiration: string | undefined, timenow: number = new Date().getTime()): string { if (expiration) { const date = Math.floor((new Date(expiration).getTime() - timenow) / 1000) if (date <= 0) return '过期失效' else if (date < 60) return date + '秒后' else if (date < 3600) return (date / 60).toFixed(1) + '分钟' else if (date < 3600 * 24) return (date / 3600).toFixed(1) + '小时' else return (date / 3600 / 24).toFixed(1) + '天后' } else { return '永久' } } export function GetKeyHashHex(full: string): string { const buffa = Buffer.from(full) let h1b, k1 const remainder = buffa.length & 3 const bytes = buffa.length - remainder let h1 = 0 const c1 = 0xcc9e2d51 const c2 = 0x1b873593 let i = 0 while (i < bytes) { k1 = buffa.readUInt8(i) | (buffa.readUInt8(++i) << 8) | (buffa.readUInt8(++i) << 16) | (buffa.readUInt8(++i) << 24) ++i k1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff k1 = (k1 << 15) | (k1 >>> 17) k1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff h1 ^= k1 h1 = (h1 << 13) | (h1 >>> 19) h1b = ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16) } k1 = 0 switch (remainder) { case 3: k1 ^= buffa.readUInt8(i + 2) << 16 break case 2: k1 ^= buffa.readUInt8(i + 1) << 8 break case 1: k1 ^= buffa.readUInt8(i) k1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff k1 = (k1 << 15) | (k1 >>> 17) k1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff h1 ^= k1 break } h1 ^= buffa.length h1 ^= h1 >>> 16 h1 = ((h1 & 0xffff) * 0x85ebca6b + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff h1 ^= h1 >>> 13 h1 = ((h1 & 0xffff) * 0xc2b2ae35 + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff h1 ^= h1 >>> 16 return (h1 >>> 0).toString(16).padStart(8, '0') } export function GetKeyHashNumber(full: string): number { const buffa = Buffer.from(full) let h1b, k1 const remainder = buffa.length & 3 const bytes = buffa.length - remainder let h1 = 0 const c1 = 0xcc9e2d51 const c2 = 0x1b873593 let i = 0 while (i < bytes) { k1 = buffa.readUInt8(i) | (buffa.readUInt8(++i) << 8) | (buffa.readUInt8(++i) << 16) | (buffa.readUInt8(++i) << 24) ++i k1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff k1 = (k1 << 15) | (k1 >>> 17) k1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff h1 ^= k1 h1 = (h1 << 13) | (h1 >>> 19) h1b = ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16) } k1 = 0 switch (remainder) { case 3: k1 ^= buffa.readUInt8(i + 2) << 16 break case 2: k1 ^= buffa.readUInt8(i + 1) << 8 break case 1: k1 ^= buffa.readUInt8(i) k1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff k1 = (k1 << 15) | (k1 >>> 17) k1 = ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff h1 ^= k1 break } h1 ^= buffa.length h1 ^= h1 >>> 16 h1 = ((h1 & 0xffff) * 0x85ebca6b + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff h1 ^= h1 >>> 13 h1 = ((h1 & 0xffff) * 0xc2b2ae35 + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff h1 ^= h1 >>> 16 return h1 >>> 0 } export function StringsToMap(list: string[]): Map { const map = new Map() try { for (let i = 0, maxi = list.length; i < maxi; i++) { map.set(list[i], true) } } catch {} return map } export function guid(): string { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0 const v = c == 'x' ? r : (r & 0x3) | 0x8 return v.toString(16) }) } const pk = 'abcDEfgFGHJIdeoOPQpyzABqwxC5678KLhijklmnMNWXYZ012rstuv34RSTUV99' export function randomSharePassword(): string { return 'xxxx'.replace(/[x]/g, function (c) { const r = Math.floor((Math.random() * 169) | 0) % (pk.length - 1) return pk.substring(r, r + 1) }) } export function b64encode(str: string): string { try { return Buffer.from(str).toString('base64') } catch { return '' } } export function b64decode(base64: string): string { try { return Buffer.from(base64, 'base64').toString() } catch { return '' } } export function B64decode(b64str: string): string { if (!b64str) return '' try { b64str = b64str.replaceAll('-', '+') b64str = b64str.replaceAll('_', '/') b64str = b64str.replaceAll('*', '=') return b64decode(b64str) } catch { return '' } } export function B64encode(str: string): string { if (!str) return '' try { let b64str = b64encode(str) b64str = b64str.replaceAll('+', '-') b64str = b64str.replaceAll('/', '_') b64str = b64str.replaceAll('=', '*') return b64str } catch { return '' } } export function Sleep(msTime: number) { return new Promise((resolve) => setTimeout( () => resolve({ success: true, time: msTime }), msTime ) ) } export function Unicode(str: string): string { const v = str.split('') let ascii = '' for (let i = 0, maxi = v.length; i < maxi; i++) { const code = Number(v[i].charCodeAt(0)) ascii += '\\u' + code.toString(16).padStart(4, '0') } return ascii } ================================================ FILE: src/renderer/utils/idhelper.ts ================================================ ================================================ FILE: src/renderer/utils/keyboardhelper.ts ================================================ import { KeyboardMessage } from '../store/keyboardstore' import { throttle } from './debounce' export function TestCtrlShift(key: string, event: KeyboardMessage, fun: any): boolean { if (event.Key.toLowerCase() == key.toLowerCase() && event.Ctrl && event.Shift && event.Repeat == false) { fun() return true } return false } export function TestCtrl(key: string, event: KeyboardMessage, fun: any): boolean { if (event.Key.toLowerCase() == key.toLowerCase() && event.Ctrl && event.Repeat == false) { fun() return true } return false } export function TestShift(key: string, event: KeyboardMessage, fun: any): boolean { if (event.Key.toLowerCase() == key.toLowerCase() && event.Shift && event.Repeat == false) { fun() return true } return false } export function TestAlt(key: string, event: KeyboardMessage, fun: any): boolean { if (event.Key.toLowerCase() == key.toLowerCase() && event.Alt && event.Repeat == false) { fun() return true } return false } export function TestKey(key: string, event: KeyboardMessage, fun: any): boolean { if (event.Key.toLowerCase() == key.toLowerCase() && event.Repeat == false && event.Ctrl == false && event.Shift == false && event.Alt == false) { fun() return true } return false } export function TestKeyboardScroll(event: KeyboardMessage, vlist: any, store: any): boolean { try { if (!vlist) return false if (event.Key.toLowerCase() == 'pagedown') { if (vlist.virtualListRef && vlist.virtualListRef.containerRef) { const containerRef = vlist.virtualListRef.containerRef const top = Math.min(containerRef.scrollHeight, containerRef.scrollTop + containerRef.clientHeight) vlist.scrollIntoView(top) const index = Math.min(Math.ceil(top / vlist.virtualListProps.estimatedSize), vlist.data.length - 1) const key = vlist.data[index][vlist.virtualListProps.itemKey] store.mSetFocus(key) return true } } if (event.Key.toLowerCase() == 'pageup') { if (vlist.virtualListRef && vlist.virtualListRef.containerRef) { const containerRef = vlist.virtualListRef.containerRef const top = Math.max(0, containerRef.scrollTop - containerRef.clientHeight) vlist.scrollIntoView(top) const index = Math.min(Math.ceil(top / vlist.virtualListProps.estimatedSize), vlist.data.length - 1) const key = vlist.data[index][vlist.virtualListProps.itemKey] store.mSetFocus(key) return true } } if (event.Key.toLowerCase() == 'home') { vlist.scrollIntoView({ index: 0, align: 'top' }) const key = store.mGetFocusNext('top') store.mSetFocus(key) return true } if (event.Key.toLowerCase() == 'end') { vlist.scrollIntoView({ index: vlist.data.length - 1, align: 'bottom' }) const key = store.mGetFocusNext('end') store.mSetFocus(key) return true } } catch { return true } return false } export function TestKeyboardSelect(event: KeyboardMessage, viewlist: any, store: any, enterFun: any): boolean { const tselect = () => { const key = store.mGetFocusNext('top') store.mKeyboardSelect(key, false, false) viewlist.scrollIntoView({ key: key, align: 'top' }) } if (TestCtrl('home', event, tselect)) return true const eselect = () => { const key = store.mGetFocusNext('end') store.mKeyboardSelect(key, false, false) viewlist.scrollIntoView({ key: key, align: 'bottom' }) } if (TestCtrl('end', event, eselect)) return true const cdown = () => { const key = store.mGetFocusNext('next') store.mSetFocus(key) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestCtrl('arrowdown', event, cdown)) return true const sdown = () => { const key = store.mGetFocusNext('next') store.mKeyboardSelect(key, false, true) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestShift('arrowdown', event, sdown)) return true const down = () => { const key = store.mGetFocusNext('next') store.mKeyboardSelect(key, false, false) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestKey('arrowdown', event, down)) return true const cup = () => { const key = store.mGetFocusNext('prev') store.mSetFocus(key) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestCtrl('arrowup', event, cup)) return true const sup = () => { const key = store.mGetFocusNext('prev') store.mKeyboardSelect(key, false, true) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestShift('arrowup', event, sup)) return true const up = () => { const key = store.mGetFocusNext('prev') store.mKeyboardSelect(key, false, false) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestKey('arrowup', event, up)) return true const enter = () => { const key = store.mGetFocus() store.mKeyboardSelect(key, false, false) viewlist.scrollIntoView({ key: key, align: 'auto' }) if (enterFun) enterFun(key) } if (TestKey('enter', event, enter)) return true const esc = () => { store.mKeyboardSelect('', false, false) } if (TestKey('escape', event, esc)) return true const space = () => { const key = store.mGetFocus() store.mKeyboardSelect(key, false, true) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestShift(' ', event, space)) return true const cspace = () => { const key = store.mGetFocus() store.mKeyboardSelect(key, true, false) viewlist.scrollIntoView({ key: key, align: 'auto' }) } if (TestCtrl(' ', event, cspace)) return true return false } const menulist = ['leftpansubmove', 'leftpansubzhankai', 'leftpanmenu', 'rightpansubmove', 'rightpansubbiaoji', 'rightpansubmore', 'rightpanmenu', 'rightpantrashmenu', 'rightmysharemenu', 'rightothersharemenu', 'rightuploadingmenu', 'rightuploadedmenu'] const menuliststate = new Set() export function onHideRightMenu(): void { for (let i = 0; i < menulist.length; i++) { const menukey = menulist[i] const menu = document.getElementById(menukey) if (menu && (menuliststate.has(menukey) || menu.style.left != '-200px')) { menu.style.left = '-200px' menu.style.opacity = '0' menu.style.zIndex = '-1' menuliststate.delete(menukey) } } } const hideMenu = throttle(() => { for (let i = 0; i < menulist.length; i++) { const menukey = menulist[i] if (menuliststate.has(menukey)) { const menu = document.getElementById(menukey) if (menu) { menu.style.left = '-200px' menu.style.opacity = '0' menu.style.zIndex = '-1' } menuliststate.delete(menukey) } } }, 200) export function onHideRightMenuScroll() { hideMenu() } export function onShowRightMenu(menukey: string, clientX: number, clientY: number): void { onHideRightMenuScroll() const menu = document.getElementById(menukey) if (menu) { menuliststate.add(menukey) const screenY = window.innerHeight const screenX = window.innerWidth if (menu.offsetHeight + clientY + 30 > screenY) { menu.style.top = (clientY - menu.offsetHeight).toString() + 'px' } else { menu.style.top = clientY.toString() + 'px' } if (menu.offsetWidth + clientX + 10 > screenX) { menu.style.left = (clientX - menu.offsetWidth).toString() + 'px' } else { menu.style.left = clientX.toString() + 'px' } menu.style.opacity = '1' menu.style.zIndex = '1001' } } ================================================ FILE: src/renderer/utils/levemap.ts ================================================ /* eslint-disable no-unused-vars */ import { message } from 'ant-design-vue' import DB from './db' interface Dir { file_id: string } // 1122334455667788 // datamap // 11 // 62ad76cd1f7dfdc28ad64c1eb6f22492a672a510 function GetDirSize(file_id: string) { let obj = DirSizeDataMap let i = 0 const maxi = file_id.length - 4 while (i < maxi) { const key = file_id.substring(i, i + 4) obj = obj.get(key) if (!obj) return 0 i += 4 } return obj.get(file_id.substring(i)) || 0 } let DirSizeDataMap: Map = new Map() function SetDirSizeMap(file_id: string, size: number) { let obj = DirSizeDataMap let i = 0 const maxi = file_id.length - 8 while (i < maxi) { const key = file_id.substring(i, i + 8) let find = obj.get(key) if (!find) { find = new Map() obj.set(key, find) } obj = find i += 8 } obj.set(file_id.substring(i), size) } let DirSizeDataObj: { [key: string]: any } = Object.create(null) function SetDirSizeObject(file_id: string, size: number) { let obj = DirSizeDataObj let i = 0 const maxi = file_id.length - 8 while (i < maxi) { const key = file_id.substring(i, i + 8) let find = obj[key] if (!find) { find = Object.create(null) obj[key] = find } obj = find i += 8 } obj[file_id.substring(i)] = size } export async function LoadObject() { console.time('LoadObject') window.openDatabase = {} const drive_id = '8699982' const jsonsize = await DB.getValueObject('DirFileSize_' + drive_id) window.openDatabase.sizemap = jsonsize ? (jsonsize as { [key: string]: number }) : {} // const jsonsizetime = await DB.getValueObject('DirFileSizeTime_' + drive_id) // window.openDatabase.sizetimemap = jsonsizetime ? (jsonsizetime as { [key: string]: number }) : {} console.timeEnd('LoadObject') message.success('LoadObject') } export async function CreatMap() { console.time('CreatMap') DirSizeDataMap = new Map() const sizemap = window.openDatabase.sizemap as { [key: string]: number } const keys = Object.keys(sizemap) for (let i = 0, maxi = keys.length; i < maxi; i++) { // SetDirSizeMap(keys[i], sizemap[keys[i]]) DirSizeDataMap.set(keys[i], [sizemap[keys[i]], 'size', true]) } window.openDatabase.DirSizeDataMap = DirSizeDataMap DirSizeDataMap = new Map() console.timeEnd('CreatMap') message.success('CreatMap') } export async function CreatObject() { console.time('CreatObject') DirSizeDataObj = Object.create(null) const sizemap = window.openDatabase.sizemap as { [key: string]: number } const keys = Object.keys(sizemap) for (let i = 0, maxi = keys.length; i < maxi; i++) { // SetDirSizeObject(keys[i], sizemap[keys[i]]) DirSizeDataObj[keys[i]] = [sizemap[keys[i]], 'size', true] } window.openDatabase.DirSizeDataObj = DirSizeDataObj DirSizeDataObj = Object.create(null) console.timeEnd('CreatObject') message.success('CreatObject') } ================================================ FILE: src/renderer/utils/message.ts ================================================ import { Message } from '@arco-design/web-vue' import { h } from 'vue' const MessageMap = new Map() function getCount(msg: string) { let count = MessageMap.get(msg) || 0 count++ MessageMap.set(msg, count) return count } export default class message { static info(msg: string, duration: number = 3, key: string = '') { const count = getCount(key || msg) return Message.info({ id: key || msg, content: count > 1 ? () => h('div', { innerHTML: msg + '' + count + '' }) : msg, position: 'bottom', duration: duration * 1000, onClose: (id) => MessageMap.delete(key || msg) }) } static error(msg: string, duration: number = 3, key: string = '') { const count = getCount(key || msg) return Message.error({ id: key || msg, content: count > 1 ? () => h('div', { innerHTML: msg + '' + count + '' }) : msg, position: 'bottom', duration: duration * 1000, onClose: (id) => MessageMap.delete(key || msg) }) } static success(msg: string, duration: number = 3, key: string = '') { const count = getCount(key || msg) return Message.success({ id: key || msg, content: count > 1 ? () => h('div', { innerHTML: msg + '' + count + '' }) : msg, position: 'bottom', duration: duration == 0 ? 1 : duration * 1000, onClose: (id) => MessageMap.delete(key || msg) }) } static warning(msg: string, duration: number = 3, key: string = '') { const count = getCount(key || msg) return Message.warning({ id: key || msg, content: count > 1 ? () => h('div', { innerHTML: msg + '' + count + '' }) : msg, position: 'bottom', duration: duration * 1000, onClose: (id) => MessageMap.delete(key || msg) }) } static loading(msg: string, duration: number = 3, key: string = '') { const count = 0 return Message.loading({ id: key || msg, content: count > 1 ? () => h('div', { innerHTML: msg + '' + count + '' }) : msg, position: 'bottom', duration: duration * 1000 }) } } ================================================ FILE: src/renderer/utils/modal.ts ================================================ import { IAliGetFileModel, IAliShareItem } from '../aliapi/alimodels' import { useModalStore } from '../store' export function modalCloseAll() { useModalStore().showModal('', {}) } export function modalUserSpace() { useModalStore().showModal('userspace', {}) } export function modalCreatNewFile() { useModalStore().showModal('creatfile', {}) } export function modalCreatNewDir(dirtype: string, parentdirid: string = '', callback: any = undefined) { useModalStore().showModal('creatdir', { dirtype, parentdirid, callback }) } export function modalCreatNewShareLink(sharetype: string, filelist: IAliGetFileModel[]) { useModalStore().showModal('creatshare', { sharetype, filelist }) } export function modalDaoRuShareLink() { useModalStore().showModal('daorushare', {}) } export function modalDaoRuShareLinkMulti() { useModalStore().showModal('daorusharemulti', {}) } export function modalRename(istree: boolean, ismulti: boolean) { useModalStore().showModal(ismulti ? 'renamemulti' : 'rename', { istree }) } export function modalEditShareLink(sharelist: IAliShareItem[]) { useModalStore().showModal('editshare', { sharelist }) } export function modalShowShareLink(share_id: string, share_pwd: string, share_token: string, withsave: boolean, file_id_list: string[]) { useModalStore().showModal('showshare', { share_id, share_pwd, share_token, withsave, file_id_list }) } export function modalSelectPanDir(selecttype: string, selectid: string, callback: (user_id: string, drive_id: string, dirID: string, dirName: string) => void) { useModalStore().showModal('selectpandir', { selecttype, selectid, callback }) } export function modalShuXing(istree: boolean, ismulti: boolean) { ismulti = false useModalStore().showModal(ismulti ? 'shuxingmulti' : 'shuxing', { istree }) } export function modalSearchPan() { useModalStore().showModal('searchpan', {}) } export function modalDLNAPlayer() { useModalStore().showModal('dlna', {}) } export function modalM3U8Download() { useModalStore().showModal('m3u8download', {}) } export function modalCopyFileTree(filelist: IAliGetFileModel[]) { useModalStore().showModal('copyfiletree', { filelist }) } export function modalArchive(user_id: string, drive_id: string, file_id: string, file_name: string, parent_file_id: string, password: string) { useModalStore().showModal('archive', { user_id, drive_id, file_id, file_name, parent_file_id, password }) } export function modalArchivePassword(user_id: string, drive_id: string, file_id: string, file_name: string, parent_file_id: string, domain_id: string, ext: string) { useModalStore().showModal('archivepassword', { user_id, drive_id, file_id, file_name, parent_file_id, domain_id, ext }) } export function modalUpload(file_id: string, filelist: string[]) { useModalStore().showModal('upload', { file_id, filelist }) } export function modalDownload(istree: boolean) { useModalStore().showModal('download', { istree }) } ================================================ FILE: src/renderer/utils/openfile.ts ================================================ import { IAliGetFileModel } from '../aliapi/alimodels' import AliArchive from '../aliapi/archive' import AliFile from '../aliapi/file' import AliFileCmd from '../aliapi/filecmd' import ServerHttp from '../aliapi/server' import { useFootStore, usePanFileStore, useSettingStore, useUserStore } from '../store' import { IPageCode, IPageImage, IPageOffice, IPageVideo } from '../store/appstore' import UserDAL from '../user/userdal' import Config from './config' import { clickWait } from './debounce' import DebugLog from './debuglog' import { CleanStringForCmd } from './filehelper' import message from './message' import { modalArchive, modalArchivePassword } from './modal' export async function menuOpenFile(file: IAliGetFileModel): Promise { if (clickWait('menuOpenFile', 500)) return const file_id = file.file_id const drive_id = file.drive_id if (file.ext == 'zip' || file.ext == 'rar' || file.ext == '7z') { Archive(file.drive_id, file.file_id, file.name, file.parent_file_id, file.icon == 'iconweifa') return } if (file.ext == 'djvu' || file.ext == 'epub' || file.ext == 'azw3' || file.ext == 'mobi' || file.ext == 'cbr' || file.ext == 'cbz' || file.ext == 'cbt' || file.ext == 'fb2') { } if (file.category.startsWith('doc')) { Office(drive_id, file_id, file.name) return } if (file.category == 'image' || file.category == 'image2') { Image(drive_id, file_id, file.name) return } if (file.category == 'image3') { message.info('此格式暂不支持预览') return } if (file.category.startsWith('video')) { Video(drive_id, file_id, file.name, file.icon == 'iconweifa', file.description) return } if (file.category.startsWith('audio')) { Audio(drive_id, file_id, file.name, file.icon == 'iconweifa') return } const codeExt = PrismExt(file.ext) if (file.size < 100 * 1024 || (file.size < 5 * 1024 * 1024 && codeExt)) { Code(drive_id, file_id, file.name, codeExt, file.size) return } message.info('此格式暂不支持预览') } async function Archive(drive_id: string, file_id: string, file_name: string, parent_file_id: string, weifa: boolean): Promise { if (weifa) { message.error('违规文件,操作取消') return } message.loading('Loading...', 2) const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } const info = await AliFile.ApiFileInfo(user_id, drive_id, file_id) if (!info) { message.error('在线预览失败 获取文件信息出错,操作取消') return } let password = '' let resp = await AliArchive.ApiArchiveList(user_id, drive_id, file_id, info.domain_id, info.file_extension || '', password) if (!resp) { message.error('在线预览失败 获取解压信息出错,操作取消') return } if (resp.state == '密码错误' && useSettingStore().yinsiZipPassword) { password = await ServerHttp.PostToServer({ cmd: 'GetZipPwd', sha1: info.content_hash, size: info.size }).then((serdata) => { if (serdata.password) return serdata.password return '' }) if (password) resp = await AliArchive.ApiArchiveList(user_id, drive_id, file_id, info.domain_id, info.file_extension || '', password) } if (!resp) { message.error('在线预览失败 获取解压信息出错,操作取消') return } if (resp.state == '密码错误') { modalArchivePassword(user_id, drive_id, file_id, file_name, parent_file_id, info.domain_id, info.file_extension || '') } else if (resp.state == 'Succeed' || resp.state == 'Running') { modalArchive(user_id, drive_id, file_id, file_name, parent_file_id, password) } else { message.error('在线解压失败 ' + resp.state + ',操作取消') DebugLog.mSaveDanger('在线解压失败 ' + resp.state, drive_id + ' ' + file_id) } } async function Video(drive_id: string, file_id: string, name: string, weifa: boolean, dec: string): Promise { const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } if (weifa) { message.error('在线预览失败 无法预览违规文件') return } message.loading('Loading...', 2) const settingStore = useSettingStore() if (settingStore.uiAutoColorVideo && !dec) { AliFileCmd.ApiFileColorBatch(user_id, drive_id, 'c5b89b8', [file_id]).then((success) => { usePanFileStore().mColorFiles('c5b89b8', success) }) } if (settingStore.uiVideoPlayer == 'web') { const pageVideo: IPageVideo = { user_id: token.user_id, drive_id, file_id, file_name: name } window.WebOpenWindow({ page: 'PageVideo', data: pageVideo, theme: 'dark' }) return } let url = '' let mode = '' if (weifa || settingStore.uiVideoMode == 'online') { const data = await AliFile.ApiVideoPreviewUrl(user_id, drive_id, file_id) if (data && data.url != '') { url = data.url mode = '转码视频模式_没有字幕请切换原始文件模式' } } if (!url && weifa == false) { const data = await AliFile.ApiFileDownloadUrl(user_id, drive_id, file_id, 14400) if (typeof data !== 'string' && data.url && data.url != '') { url = data.url mode = '原始文件模式' } } if (!url) { message.error('视频地址解析失败,操作取消') return } const title = mode + '__' + name if (settingStore.uiVideoPlayer == 'mpv') { let ag2: string[] = [] if (window.platform == 'win32') { ag2 = ['"' + url + '"', '--title="' + CleanStringForCmd(title) + '"', '--user-agent="' + CleanStringForCmd(Config.userAgent) + '"'] } else if (window.platform == 'darwin') { ag2 = ["'" + url + "'", "--title='" + CleanStringForCmd(title) + "'", "--user-agent='" + CleanStringForCmd(Config.userAgent) + "'"] } else if (window.platform == 'linux') { ag2 = ["'" + url + "'", "--title='" + CleanStringForCmd(title) + "'", "--user-agent='" + CleanStringForCmd(Config.userAgent) + "'"] } else { message.error('不支持的系统,操作取消') return } window.WebExecSync( { command: 'mpv', args: ['--referrer=https://www.aliyundrive.com/', '--force-window=immediate', '--hwdec=auto', '--geometry=80%', '--autofit-larger=100%x100%', '--autofit-smaller=640', ...ag2] }, (rdata: any) => {} ) } else { let command = settingStore.uiVideoPlayerPath let args = ['"' + url + '"'] if (window.platform == 'win32') { command = '"' + settingStore.uiVideoPlayerPath + '"' args = ['"' + url + '"'] if (command.toLowerCase().indexOf('potplayer') > 0) { args = ['"' + url + '"', '/new', '/referer=https://www.aliyundrive.com/'] } else if (command.toLowerCase().indexOf('mpv') > 0) { args = ['"' + url + '"', '--referrer=https://www.aliyundrive.com/', '--title="' + CleanStringForCmd(title) + '"'] } else { if (url.indexOf('x-oss-additional-headers=referer') > 0) { message.error('用户token已过期,请点击头像里退出按钮后重新登录账号') return } } } else if (window.platform == 'darwin') { command = "open -a '" + command + "'" args = ["'" + url + "'"] if (url.indexOf('x-oss-additional-headers=referer') > 0) { message.error('用户token已过期,请点击头像里退出按钮后重新登录账号') return } } else if (window.platform == 'linux') { command = settingStore.uiVideoPlayerPath args = ["'" + url + "'"] if (url.indexOf('x-oss-additional-headers=referer') > 0) { message.error('用户token已过期,请点击头像里退出按钮后重新登录账号') return } } else { message.error('不支持的系统,操作取消') return } window.WebExecSync( { command, args }, (rdata: any) => {} ) } } async function Image(drive_id: string, file_id: string, name: string): Promise { const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } message.loading('Loading...', 2) const imageidList: string[] = [] const imagenameList: string[] = [] const fileList = usePanFileStore().ListDataRaw for (let i = 0, maxi = fileList.length; i < maxi; i++) { if (fileList[i].category == 'image' || fileList[i].category == 'image2') { imageidList.push(fileList[i].file_id) imagenameList.push(fileList[i].name) } } if (imageidList.length == 0) { message.error('获取文件预览链接失败,操作取消') return } const pageImage: IPageImage = { user_id: token.user_id, drive_id, file_id, file_name: name, mode: useSettingStore().uiImageMode, imageidlist: imageidList, imagenamelist: imagenameList } window.WebOpenWindow({ page: 'PageImage', data: pageImage, theme: 'dark' }) } async function Office(drive_id: string, file_id: string, name: string): Promise { const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } message.loading('Loading...', 2) const data = await AliFile.ApiOfficePreViewUrl(user_id, drive_id, file_id) if (!data || !data.preview_url) { message.error('获取文件预览链接失败,操作取消') return } const pageOffice: IPageOffice = { user_id: token.user_id, drive_id, file_id, file_name: name, preview_url: data.preview_url, access_token: data.access_token } window.WebOpenWindow({ page: 'PageOffice', data: pageOffice }) } async function Audio(drive_id: string, file_id: string, name: string, weifa: boolean): Promise { if (weifa) { message.error('在线预览失败 无法预览违规文件') return } message.loading('Loading...', 2) const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } const data = await AliFile.ApiAudioPreviewUrl(user_id, drive_id, file_id) if (data && data.url != '') { useFootStore().mSaveAudioUrl(data.url) } } async function Code(drive_id: string, file_id: string, name: string, codeExt: string, fileSize: number): Promise { const user_id = useUserStore().user_id const token = await UserDAL.GetUserTokenFromDB(user_id) if (!token || !token.access_token) { message.error('在线预览失败 账号失效,操作取消') return } message.loading('Loading...', 2) const data = await AliFile.ApiFileDownloadUrl(user_id, drive_id, file_id, 14400) if (typeof data == 'string') { message.error('获取文件预览链接失败,操作取消') return } const pageCode: IPageCode = { user_id: token.user_id, drive_id, file_id, file_name: name, code_ext: codeExt, file_size: fileSize, download_url: data.url } window.WebOpenWindow({ page: 'PageCode', data: pageCode, theme: 'dark' }) } export function PrismExt(fileExt: string): string { const ext = '.' + fileExt.toLowerCase() + '.' const fext = fileExt.toLowerCase() let iscode = false let codeext = '' iscode = iscode || ';.markup.html.xml.svg.mathml.ssml.atom.rss.css.clike.javascript.js.abap.'.indexOf(ext) > 0 iscode = iscode || ';.actionscript.ada.agda.al.antlr4.g4.apacheconf.apex.apl.applescript.abnf.'.indexOf(ext) > 0 iscode = iscode || ';.aql.arduino.arff.asciidoc.adoc.aspnet.asm6502.autohotkey.autoit.bash.shell.'.indexOf(ext) > 0 iscode = iscode || ';.basic.batch.bbcode.shortcode.birb.bison.bnfrbnf.brainfuck.brightscript.'.indexOf(ext) > 0 iscode = iscode || ';.bro.bsl.oscript.c.csharp.cs.dotnet.cpp.cfscript.cfc.chaiscript.cil.clojure.cmake.'.indexOf(ext) > 0 iscode = iscode || ';.cobol.coffeescript.coffee.concurnas.conc.csp.coq.crystal.css-extras.csv.cypher.n4jsd.'.indexOf(ext) > 0 iscode = iscode || ';.d.dart.dataweave.dax.dhall.diff.django.jinja2.dns-zone-file.dns-zone..purs.purescript.'.indexOf(ext) > 0 iscode = iscode || ';.docker.dockerfile.dot.gv.ebnf.editorconfig.eiffel.ejs.eta.elixir.elm.etlua.erb.erlang.'.indexOf(ext) > 0 iscode = iscode || ';.fsharp.factor.false.firestore-security-rules.flow.fortran.ftl.gml.gamemakerlanguage.'.indexOf(ext) > 0 iscode = iscode || ';.gcode.gdscript.gedcom.gherkin.git.glsl.go.graphql.groovy.haml.handlebars.hbs.'.indexOf(ext) > 0 iscode = iscode || ';.haskell.hs.haxe.hcl.hlsl.hoon.http.hpkp.hsts.ichigojam.icon.icu-message-format.'.indexOf(ext) > 0 iscode = iscode || ';.idris.idr.ignore.gitignore.hgignore.npmignore.inform7.ini.io.j.java.javadoc.javadoclike.'.indexOf(ext) > 0 iscode = iscode || ';.javastacktrace.jexl.jolie.jq.jsdoc.js-extras.json.webmanifest.json5.jsonp.jsstacktrace.px.'.indexOf(ext) > 0 iscode = iscode || ';.js-templates.julia.keyman.kotlin.kt.kts.kumir.kum.latex.tex.context.latte.less.lilypond.ly.'.indexOf(ext) > 0 iscode = iscode || ';.liquid.lisp.emacs.elisp.emacs-lisp.livescript.llvm.log.lolcode.lua.makefile.markdown.md.'.indexOf(ext) > 0 iscode = iscode || ';.markup-templating.matlab.mel.mizar.mongodb.monkey.moonscript.moon.n1ql.n4js.'.indexOf(ext) > 0 iscode = iscode || ';.nand2tetris-hdl.naniscript.nani.nasm.neon.nevod.nginx.nim.nix.nsis.objectivec.objc.'.indexOf(ext) > 0 iscode = iscode || ';.ocaml.opencl.openqasm.qasm.oz.parigp.parser.pascal.objectpascal.pascaligo.psl.pcaxis.'.indexOf(ext) > 0 iscode = iscode || ';.peoplecode.pcode.perl.php.phpdoc.php-extras.plsql.powerquery.pq.mscript.powershell.'.indexOf(ext) > 0 iscode = iscode || ';.processing.prolog.promql.properties.protobuf.pug.puppet.pure.purebasic.pbfasm.twig.'.indexOf(ext) > 0 iscode = iscode || ';.python.py.qsharp.qs.q.qml.qore.r.racket.rkt.jsx.tsx.reason.regex.rego.renpy.rpy.rest.rip.'.indexOf(ext) > 0 iscode = iscode || ';.robotframework.robot.ruby.rb.rust.sas.sass.scss.scala.scheme.shell-session.sh-session.sql.'.indexOf(ext) > 0 iscode = iscode || ';.smali.smalltalk.smarty.sml.smlnj.solidity.sol.solution-file.sln.soy.sparql.rq.splunk-spl.sqf.'.indexOf(ext) > 0 iscode = iscode || ';.squirrel.stan.iecst.stylus.swift.t4-templating.t4-cs.t4.t4-vb.tap.tcl.tt2.textile.toml.turtle.trig.'.indexOf(ext) > 0 iscode = iscode || ';.typescript.ts.typoscript.tsconfig.unrealscript.uscript.uc.uri.url.v.vala.vbnet.velocity.verilog.'.indexOf(ext) > 0 iscode = iscode || ';.vim.visual-basic.vb.vba.warpscript.wasm.wiki.wolfram.mathematica.nb.wl.xeora.xeoracube.'.indexOf(ext) > 0 iscode = iscode || ';.xml-doc.xojo.xquery.yaml.yml.yang.zig.excel-formula.xlsx.xls.shellsession.roboconf.vhdl.'.indexOf(ext) > 0 if (iscode) { codeext = fext } else { switch (fext) { case 'prettierrc': codeext = 'json' break case 'vue': codeext = 'javascript' break case 'h': codeext = 'c' break case 'as': codeext = 'actionscript' break case 'sh': codeext = 'bash' break case 'zsh': codeext = 'bash' break case 'bf': codeext = 'brainfuck' break case 'hpp': codeext = 'cpp' break case 'cc': codeext = 'cpp' break case 'hh': codeext = 'cpp' break case 'c++': codeext = 'cpp' break case 'h++': codeext = 'cpp' break case 'cxx': codeext = 'cpp' break case 'hxx': codeext = 'cpp' break case 'cson': codeext = 'coffeescript' break case 'iced': codeext = 'coffeescript' break case 'dns': codeext = 'dns-zone' break case 'zone': codeext = 'dns-zone' break case 'bind': codeext = 'dns-zone' break case 'plist': codeext = 'xml' break case 'xhtml': codeext = 'html' break case 'iml': codeext = 'xml' break case 'mk': codeext = 'makefile' break case 'mak': codeext = 'makefile' break case 'make': codeext = 'makefile' break case 'mkdown': codeext = 'markdown' break case 'mkd': codeext = 'markdown' break case 'nginxconf': codeext = 'nginx' break case 'nimrod': codeext = 'nim' break case 'mm': codeext = 'objectivec' break case 'obj-c': codeext = 'objectivec' break case 'obj-c++': codeext = 'objectivec' break case 'objective-c++': codeext = 'objectivec' break case 'ps': codeext = 'powershell' break case 'ps1': codeext = 'powershell' break case 'gyp': codeext = 'python' break case 'rs': codeext = 'rust' break case 'vb': codeext = 'vbnet' break case 'conf': codeext = 'ini' break } } return codeext } ================================================ FILE: src/renderer/utils/selecthelper.ts ================================================ import { MapValueToArray } from './utils' export function GetSelectedList(list: T[], keyName: string, selectedMap: Set): T[] { const selectedList: Map = new Map() let key: K for (let i = 0, maxi = list.length; i < maxi; i++) { key = (list[i] as any)[keyName] if (selectedMap.has(key)) selectedList.set(key, list[i]) } return MapValueToArray(selectedList) } export function GetSelectedListID(list: T[], keyName: string, selectedMap: Set): K[] { const selectedList: Set = new Set() let key: K for (let i = 0, maxi = list.length; i < maxi; i++) { key = (list[i] as any)[keyName] if (selectedMap.has(key)) selectedList.add(key) } return Array.from(selectedList) } export function SelectAll(list: T[], keyName: string, selectedOld: Set): Set { const selectedNew = new Set() if (selectedOld.size == list.length) { } else { for (let i = 0, maxi = list.length; i < maxi; i++) { selectedNew.add((list[i] as any)[keyName]) } } return selectedNew } export function GetFocusNext(list: any[], keyName: string, focusKey: T, position: string, defaultValue: T): T { if (list.length <= 0) return defaultValue if (position == 'top') return list[0][keyName] if (position == 'end') return list[list.length - 1][keyName] if (!focusKey) return list[0][keyName] let key: T for (let i = 0, maxi = list.length; i < maxi; i++) { key = list[i][keyName] if (key == focusKey) { if (position == 'next') { if (i + 1 < maxi) return list[i + 1][keyName] else return list[maxi - 1][keyName] } else { if (i > 0) return list[i - 1][keyName] else return list[0][keyName] } } } return defaultValue } export function MouseSelectOne(list: any[], keyName: string, selectedOld: Set, focusKey: T, selectKey: T, Key: T, Ctrl: boolean, Shift: boolean, defaultValue: T): { selectedNew: Set; selectedLast: T; focusLast: T } { if (Key == defaultValue) return { selectedNew: new Set(), selectedLast: defaultValue, focusLast: defaultValue } if (Shift) { if (!selectKey) selectKey = list[0][keyName] let posToSelect = -1 let posLastSelect = -1 let posFocus = -1 let tempKey: T for (let i = 0, maxi = list.length; i < maxi; i++) { tempKey = list[i][keyName] if (tempKey == Key) posToSelect = i if (tempKey == selectKey) posLastSelect = i if (tempKey == focusKey) posFocus = i if (posToSelect >= 0 && posLastSelect >= 0 && posFocus >= 0) break } const selectedNew = new Set(selectedOld) if (posToSelect >= 0 && posLastSelect >= 0) { for (let n = Math.min(posToSelect, posLastSelect), maxn = Math.max(posToSelect, posLastSelect); n <= maxn; n++) { selectedNew.add(list[n][keyName]) } } if (posToSelect >= 0 && posFocus >= 0 && posLastSelect >= 0) { if (posLastSelect <= posToSelect && posToSelect <= posFocus) { for (let n = posToSelect + 1; n <= posFocus; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posToSelect <= posLastSelect && posLastSelect <= posFocus) { for (let n = posLastSelect + 1; n <= posFocus; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posFocus <= posLastSelect && posLastSelect <= posToSelect) { for (let n = posFocus; n <= posLastSelect - 1; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posFocus <= posToSelect && posToSelect <= posLastSelect) { for (let n = posFocus; n <= posToSelect - 1; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } } return { selectedNew: selectedNew, selectedLast: selectKey, focusLast: Key } } if (Ctrl) { if (selectedOld.has(Key)) { selectedOld.delete(Key) } else { selectedOld.add(Key) } return { selectedNew: selectedOld, selectedLast: Key, focusLast: Key } } if (selectedOld.has(Key) && selectedOld.size == 1) return { selectedNew: new Set(), selectedLast: Key, focusLast: Key } return { selectedNew: new Set([Key]), selectedLast: Key, focusLast: Key } } export function KeyboardSelectOne(list: any[], keyName: string, selectedOld: Set, focusKey: T, selectKey: T, Key: T, Ctrl: boolean, Shift: boolean, defaultValue: T): { selectedNew: Set; selectedLast: T; focusLast: T } { if (Key == defaultValue) return { selectedNew: new Set(), selectedLast: defaultValue, focusLast: Key } if (Shift) { if (!selectKey) selectKey = list[0][keyName] let posToSelect = -1 let posLastSelect = -1 let posFocus = -1 let tempKey: T for (let i = 0, maxi = list.length; i < maxi; i++) { tempKey = list[i][keyName] if (tempKey == Key) posToSelect = i if (tempKey == selectKey) posLastSelect = i if (tempKey == focusKey) posFocus = i if (posToSelect >= 0 && posLastSelect >= 0 && posFocus >= 0) break } const selectedNew = new Set(selectedOld) if (posToSelect >= 0 && posLastSelect >= 0) { for (let n = Math.min(posToSelect, posLastSelect), maxn = Math.max(posToSelect, posLastSelect); n <= maxn; n++) { selectedNew.add(list[n][keyName]) } } if (posToSelect >= 0 && posFocus >= 0 && posLastSelect >= 0) { if (posLastSelect <= posToSelect && posToSelect <= posFocus) { for (let n = posToSelect + 1; n <= posFocus; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posToSelect <= posLastSelect && posLastSelect <= posFocus) { for (let n = posLastSelect + 1; n <= posFocus; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posFocus <= posLastSelect && posLastSelect <= posToSelect) { for (let n = posFocus; n <= posLastSelect - 1; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } else if (posFocus <= posToSelect && posToSelect <= posLastSelect) { for (let n = posFocus; n <= posToSelect - 1; n++) { if (selectedNew.has(list[n][keyName])) selectedNew.delete(list[n][keyName]) } } } return { selectedNew: selectedNew, selectedLast: selectKey, focusLast: Key } } if (Ctrl) { if (selectedOld.has(Key)) { selectedOld.delete(Key) } else { selectedOld.add(Key) } return { selectedNew: selectedOld, selectedLast: Key, focusLast: Key } } return { selectedNew: new Set([Key]), selectedLast: Key, focusLast: Key } } ================================================ FILE: src/renderer/utils/sha1workerpool.ts ================================================ const MAXSIZE = Math.max(2, navigator.hardwareConcurrency - 1) export interface Sha1Model { hash: string localFilePath: string access_token: string } export default class Sha1WorkerPool { queueWithCallback: [args: any, callback: (result: any, worker: Worker) => void, error: (err: any, worker: Worker) => void][] = [] freeWorkers: Worker[] = [] workers: Set = new Set() public Init() { if (this.workers.size > 0) return for (let i = 0; i < MAXSIZE; i++) { const worker = new Worker('./sha1filework.js') this.freeWorkers.push(worker) this.workers.add(worker) } } public StartWithCallback(args: Sha1Model, callback: (result: any, worker: Worker) => void, error: (err: any, worker: Worker) => void) { this.Init() if (this.freeWorkers.length > 0) { const worker = this.freeWorkers.pop()! worker.onmessage = (e: any) => { callback(e.data, worker) } worker.onerror = (e: any) => { error(e, worker) } worker.postMessage(args) } else { this.queueWithCallback.push([args, callback, error]) } } public FinishWithCallback(worker: Worker) { worker.onmessage = null worker.onerror = null this.freeWorkers.push(worker) if (this.queueWithCallback.length > 0) { const item = this.queueWithCallback.shift()! this.StartWithCallback(item[0], item[1], item[2]) } } } ================================================ FILE: src/renderer/utils/shareurl.ts ================================================ import { useSettingStore } from '../store' export function GetShareUrlFormate(share_name: string, share_url: string, share_pwd: string): string { let Formate = useSettingStore().uiShareFormate.replaceAll('\\n', '\n') const s1 = Formate.indexOf('URL') if (!share_pwd) { const s2 = Formate.indexOf('PWD') if (s1 >= 0 && s2 > s1) Formate = Formate.substring(0, s1 + 3) + Formate.substring(s2 + 3) console.log(Formate) } const url = Formate.replace('URL', share_url).replace('PWD', share_pwd).replace('NAME', share_name) if (url && s1 >= 0) return url return share_name + ' ' + share_url + (share_pwd ? ' 提取码:' + share_pwd : '') } export interface IID { id: string pwd: string } export function ParseShareIDList(txt: string): IID[] { txt = txt.replaceAll('密码', '提取码').replaceAll('password', '提取码').replaceAll('pwd', '提取码').replaceAll('PWD', '提取码') txt = txt.replaceAll('\n提取码', '提取码') const list: IID[] = [] txt.split('\n').map((t) => { const p = GetShareID(t) if (p.id) list.push(p) return true }) return list } export function ParseShareIDOne(txt: string): IID { txt = txt.replaceAll('密码', '提取码').replaceAll('password', '提取码').replaceAll('pwd', '提取码').replaceAll('PWD', '提取码') txt = txt.replaceAll('\n提取码', '提取码') return GetShareID(txt) } function GetShareID(txt: string): IID { const ret = { id: '', pwd: '' } const id = txt.match(/(?<=\/s\/)[0-9a-zA-Z]{11,12}/) if (id && id.length > 0) ret.id = id[0] const pwd = txt.match(/(?<=提取码[^0-9a-zA-Z]{0,6})[0-9a-zA-Z]{4}/) if (pwd && pwd.length > 0) ret.pwd = pwd[0] return ret } ================================================ FILE: src/renderer/utils/utils.ts ================================================ export function ArrayCopyReverse(arr: any[]): any[] { const copy: any[] = [] for (let i = arr.length - 1; i >= 0; i--) { copy.push(arr[i]) } return copy } export function ArrayCopy(arr: any[]): any[] { const copy: any[] = [] for (let i = 0, maxi = arr.length; i < maxi; i++) { copy.push(arr[i]) } return copy } export function MapKeyToArray(map: Map): T[] { const arr: T[] = [] const keys = map.keys() for (let i = 0, maxi = map.size; i < maxi; i++) { arr.push(keys.next().value) } return arr } export function MapValueToArray(map: Map): T[] { const arr: T[] = [] const keys = map.values() for (let i = 0, maxi = map.size; i < maxi; i++) { arr.push(keys.next().value) } return arr } export function ArrayToMap(keyname: string, arr: T[]) { const map = new Map() let item: any for (let i = 0, maxi = arr.length; i < maxi; i++) { item = arr[i] map.set(item[keyname], item) } return map } export function ArrayKeyList(keyname: string, arr: any[]): T[] { const selectkeys: T[] = [] for (let i = 0, maxi = arr.length; i < maxi; i++) { selectkeys.push(arr[i][keyname]) } return selectkeys } export function BlobToString(body: Blob, encoding: string): Promise { return new Promise((resolve) => { const reader = new FileReader() reader.readAsText(body, encoding) reader.onload = function () { resolve((reader.result as string) || '') } }) } export function BlobToBuff(body: Blob): Promise { return new Promise((resolve) => { const reader = new FileReader() reader.readAsArrayBuffer(body) reader.onload = function () { resolve(reader.result as ArrayBuffer) } }) } const { deflateRawSync, inflateRawSync } = window.require('zlib') export function GzipObject(input: object): Buffer { return deflateRawSync(JSON.stringify(input)) } export function UnGzipObject(input: Buffer): object { return JSON.parse(inflateRawSync(input).toString()) } export function HanToPin(input: string): string { if (!input) return '' // eslint-disable-next-line no-undef const arr = pinyinlite(input, { keepUnrecognized: true }) const strarr = new Array(arr.length * 2 + 1) let l = false for (let p = 1, i = 0, maxi = arr.length; i < maxi; p += 2, i++) { strarr[p] = arr[i].join(' ') l = strarr[p].length > 1 if (l) { strarr[p - 1] = ' ' strarr[p + 1] = ' ' } else { strarr[p + 1] = '' } } strarr[0] = '' return strarr.join('') } export function GetOssExpires(downUrl: string) { if (!downUrl || downUrl.includes('x-oss-expires=') == false) return 0 try { let expires = downUrl.substring(downUrl.indexOf('x-oss-expires=') + 'x-oss-expires='.length) expires = expires.substring(0, expires.indexOf('&')) const lastTime = parseInt(expires) - Math.floor(Date.now() / 1000) return lastTime } catch { return 0 } } export function hashCode(key: string) { let hash = 0 for (let i = 0, maxi = key.length; i < maxi; i++) { hash = ((hash << 5) - hash + key.charCodeAt(i++)) << 0 } return (hash >>> 0).toString(16).padStart(8, '0') } const crypto = window.require('crypto') export function md5Code(key: string) { const buffa = Buffer.from(key) const md5a = crypto.createHash('md5').update(buffa).digest('hex') return md5a } ================================================ FILE: src/renderer/utils/worker.ts ================================================ export async function WorkerUploadFiles(ingoredList: string[], user_id: string, drive_id: string, parent_file_id: string, files: string[]) { let worker: any let result: any await new Promise((resolve) => { worker = new Worker('uploadfilesworker.js') worker.addEventListener('message', (event: any) => { if (event.data.state == 'success') { console.log(event) result = event.data.result resolve() } }) worker.addEventListener('error', function (event: any) { resolve() }) worker.postMessage({ ingoredList, user_id, drive_id, parent_file_id, files }) }) .catch(() => {}) .then(() => { if (worker) worker.terminate() }) return result } ================================================ FILE: src/renderer/workerpage/uidownload.ts ================================================ export function DownloadTrigger() { } ================================================ FILE: src/renderer/workerpage/uiupload.ts ================================================ import AliUploadDisk from '../aliapi/uploaddisk' import DBUpload, { IStateUploadInfo, IUploadingUI, IStateUploadTaskFile } from '../utils/dbupload' import { humanSizeSpeed } from '../utils/format' import { ArrayKeyList } from '../utils/utils' import { StartUpload } from './uploader' import { useSettingStore } from '../store' import AliUploadHashPool from '../aliapi/uploadhashpool' export const RuningList: Map = new Map() export async function UploadCmd(Command: string, IsAll: boolean, UploadIDList: number[], TaskIDList: number[]): Promise { if (UploadIDList.length > 0) { const map = new Set(UploadIDList) if (Command == 'stop' || Command == 'delete') { const keys = RuningList.values() for (let i = 0, maxi = RuningList.size; i < maxi; i++) { const item = keys.next().value as IUploadingUI if (map.has(item.UploadID)) item.IsRunning = false } } } if (TaskIDList.length > 0) { const map = new Set(TaskIDList) if (Command == 'stop' || Command == 'delete') { const keys = RuningList.values() for (let i = 0, maxi = RuningList.size; i < maxi; i++) { const item = keys.next().value as IUploadingUI if (map.has(item.TaskID)) item.IsRunning = false } } } if (IsAll) { if (Command == 'stop' || Command == 'delete') { const keys = RuningList.values() for (let i = 0, maxi = RuningList.size; i < maxi; i++) { const item = keys.next().value as IUploadingUI item.IsRunning = false } } } } export function UploadAdd(UploadList: IUploadingUI[]) { for (let i = 0, maxi = UploadList.length; i < maxi; i++) { const item = UploadList[i] item.IsRunning = true item.Info.uploadState = 'running' item.Info.autoTryCount = 0 item.Info.autoTryTime = 0 item.Info.failedCode = 0 item.Info.failedMessage = '' item.Info.Speed = 0 item.Info.speedStr = '' // item.Info.Loaded = 0 // item.Info.uploadSize = 0 if (RuningList.has(item.UploadID)) { } else { RuningList.set(item.UploadID, item) StartUpload(item) } } } let saveTime = 0 export async function UploadReport(): Promise { const settingStore = useSettingStore() if (settingStore.uploadGlobalSpeed) { let speedLimte = 0 if (settingStore.uploadGlobalSpeedM == 'MB') speedLimte = settingStore.uploadGlobalSpeed * 1024 * 1024 else speedLimte = settingStore.uploadGlobalSpeed * 1024 window.speedLimte = speedLimte } else window.speedLimte = Number.MAX_VALUE const saveList: IStateUploadInfo[] = [] const reportList: IStateUploadInfo[] = [] const successList: IStateUploadTaskFile[] = [] const errorList: IStateUploadInfo[] = [] const runingList: IStateUploadInfo[] = [] const stopList: IStateUploadInfo[] = [] const loadingList: IStateUploadInfo[] = [] const keys = RuningList.values() for (let i = 0, maxi = RuningList.size; i < maxi; i++) { const item = keys.next().value as IUploadingUI const uploadState = item.Info.uploadState // "hashing" | "running" | "已暂停" | "success" | "error" (排队中 状态不可能出现) if (item.IsRunning == false || uploadState == '已暂停') { stopList.push(item.Info) AliUploadDisk.DelFileUploadSpeed(item.UploadID) } else if (uploadState == 'success') { successList.push(item.File) } else if (uploadState == 'error') { errorList.push(item.Info) } else if (uploadState == 'hashing') { const posNow = AliUploadHashPool.GetFileHashProofSpeed(item.UploadID) let speed = posNow - item.Info.uploadSize item.Info.uploadSize = posNow item.Info.Progress = Math.floor((posNow * 100) / (item.File.size + 1)) % 100 if (speed < 0) speed = 0 item.Info.Speed = speed item.Info.speedStr = humanSizeSpeed(speed) reportList.push(item.Info) runingList.push(item.Info) } else if (uploadState == 'running') { const posNow = AliUploadDisk.GetFileUploadSpeed(item.UploadID) let speed = posNow - item.Info.uploadSize item.Info.uploadSize = posNow item.Info.Progress = Math.floor((posNow * 100) / (item.File.size + 1)) % 100 if (speed < 0) speed = 0 item.Info.Speed = speed item.Info.speedStr = humanSizeSpeed(speed) reportList.push(item.Info) runingList.push(item.Info) if (item.File.isDir == false && item.File.size > 3 * 1024 * 1024) saveList.push(item.Info) } else if (uploadState == '读取中') { item.Info.uploadSize = 0 item.Info.Progress = 0 item.Info.Speed = 0 item.Info.speedStr = humanSizeSpeed(0) reportList.push(item.Info) runingList.push(item.Info) loadingList.push(item.Info) } } if (stopList.length > 0) stopList.map((t) => RuningList.delete(t.UploadID)) if (successList.length > 0) successList.map((t) => RuningList.delete(t.UploadID)) if (errorList.length > 0) errorList.map((t) => RuningList.delete(t.UploadID)) saveTime++ if (saveTime > 10) { saveTime = 0 if (saveList.length > 0) await DBUpload.saveUploadInfoBatch(saveList) } const uploadSpeedTotal = AliUploadDisk.GetFileUploadSpeedTotal() window.WinMsgToMain({ cmd: 'MainUploadEvent', ReportList: reportList, ErrorList: errorList, SuccessList: successList, RunningKeys: ArrayKeyList('UploadID', runingList), StopKeys: ArrayKeyList('UploadID', stopList), LoadingKeys: ArrayKeyList('UploadID', loadingList), SpeedTotal: runingList.length > 0 ? humanSizeSpeed(uploadSpeedTotal) : '' }) } ================================================ FILE: src/renderer/workerpage/uploader.ts ================================================ import { Dirent, Stats } from 'fs' import AliFileCmd from '../aliapi/filecmd' import { IUploadInfo } from '../aliapi/models' import AliUpload from '../aliapi/upload' import AliUploadDisk from '../aliapi/uploaddisk' import AliUploadHashPool from '../aliapi/uploadhashpool' import { useSettingStore } from '../store' import UserDAL from '../user/userdal' import { IStateUploadInfo, IStateUploadTaskFile, IUploadingUI } from '../utils/dbupload' import DebugLog from '../utils/debuglog' import { CheckWindowsBreakPath, FileSystemErrorMessage } from '../utils/filehelper' import { humanSize, Sleep } from '../utils/format' import { RuningList } from './uiupload' const path = window.require('path') const fspromises = window.require('fs/promises') export async function StartUpload(fileui: IUploadingUI): Promise { const token = await UserDAL.GetUserTokenFromDB(fileui.user_id) if (!token || token.user_id !== fileui.user_id) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 402 fileui.Info.failedMessage = '找不到账号,无法继续' return } const expire_time = new Date(token.expire_time).getTime() if (expire_time - new Date().getTime() < 60000) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 402 fileui.Info.failedMessage = 'token过期失效,无法继续' return } if (fileui.File.isDir) return creatDirAndReadChildren(fileui) await checkFileSize(fileui) const uploadInfo: IUploadInfo = { token_type: token.token_type, access_token: token.access_token, sha1: '', isexist: false, israpid: false, part_info_list: [] } if (fileui.Info.up_upload_id != '' && fileui.Info.up_file_id != '') { let isok = await reloadUploadUrl(uploadInfo, fileui) if (isok == 'neterror') { Sleep(8000) isok = await reloadUploadUrl(uploadInfo, fileui) } if (isok == 'neterror') { Sleep(8000) isok = await reloadUploadUrl(uploadInfo, fileui) } if (isok == 'neterror') { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 705 fileui.Info.failedMessage = '网络连接失败' return } if (isok == 'codeerror') { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 706 fileui.Info.failedMessage = '程序运行出错' return } if (isok == 'error') { fileui.Info.up_file_id = '' fileui.Info.up_upload_id = '' uploadInfo.part_info_list = [] } } if (!fileui.Info.up_upload_id) { const needupload = await checkPreHashAndGetPartlist(uploadInfo, fileui) if (!needupload) return } if (useSettingStore().downUploadBreakFile) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 505 fileui.Info.failedMessage = '跳过不能秒传的文件' return } if (fileui.Info.uploadState == 'error') return if (uploadInfo.part_info_list.length == 0) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 505 fileui.Info.failedMessage = '获取上传地址失败1' return } const uploadResult = await AliUploadDisk.UploadOneFile(uploadInfo, fileui) if (uploadResult == 'success') { fileui.Info.uploadState = 'success' } else if (!fileui.IsRunning) { console.log('已暂停', fileui.Info.uploadState, fileui.Info) fileui.Info.uploadState = '已暂停' } else if (fileui.Info.uploadState == 'running') { console.log(fileui.Info.uploadState, fileui.Info) fileui.Info.uploadState = 'error' fileui.Info.failedCode = 505 fileui.Info.failedMessage = uploadResult } else { console.log(fileui.Info.uploadState, fileui.Info) } } interface ReadConfig { TaskID: number user_id: string drive_id: string parent_file_id: string localFilePath: string filetime: number ingoredList: string[] } async function creatDirAndReadChildren(fileui: IUploadingUI): Promise { fileui.Info.uploadState = '读取中' let uploaded_file_id = '' if (fileui.File.IsRoot) { const data = await AliFileCmd.ApiCreatNewForder(fileui.user_id, fileui.drive_id, fileui.parent_file_id, fileui.File.name) if (data.error) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 503 fileui.Info.failedMessage = data.error return } uploaded_file_id = data.file_id } let childList: IStateUploadTaskFile[] = [] const settingStore = useSettingStore() const timeStr = Date.now().toString().substring(5, 13) + '00000' const fileTime = parseInt(timeStr) const readConfig: ReadConfig = { TaskID: fileui.TaskID, user_id: fileui.user_id, drive_id: fileui.drive_id, parent_file_id: fileui.parent_file_id, localFilePath: fileui.localFilePath, filetime: fileTime, ingoredList: [...settingStore.downIngoredList] } const read = await readChildren(fileui.File.partPath, fileui.File.name, readConfig, fileui.Info) if (read.error) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 703 fileui.Info.failedMessage = read.error return } childList = read.fileList if (read.dirList.length > 0) childList.push(...read.dirList) window.WinMsgToMain({ cmd: 'MainUploadAppendFiles', TaskID: fileui.TaskID, UploadID: fileui.UploadID, AppendList: childList, CreatedDirID: uploaded_file_id }) RuningList.delete(fileui.UploadID) } async function readChildren(parentDirPartPath: string, parentDirName: string, readConfig: ReadConfig, Info: IStateUploadInfo) { const localDirPath = path.join(readConfig.localFilePath, parentDirPartPath, path.sep) const files = await readDir(localDirPath, readConfig.ingoredList) if (files.error) return { error: files.error, fileList: [] as IStateUploadTaskFile[], dirList: [] as IStateUploadTaskFile[] } const addFileList: IStateUploadTaskFile[] = [] const addDirList: IStateUploadTaskFile[] = [] await AddFiles(addFileList, files.fileList, parentDirPartPath, parentDirName, readConfig) Info.failedMessage = '读取中 ' + addFileList.length + '个' await AddDirs(addFileList, addDirList, files.dirList, parentDirPartPath, parentDirName, readConfig, Info) return { error: '', fileList: addFileList, dirList: addDirList } } async function AddFiles(addFileList: IStateUploadTaskFile[], fileList: string[], parentDirPartPath: string, parentDirName: string, readConfig: ReadConfig): Promise { const localDirPath = path.join(readConfig.localFilePath, parentDirPartPath, path.sep) let plist: Promise[] = [] for (let i = 0, maxi = fileList.length; i < maxi; i++) { const fileName = fileList[i] const filePath = localDirPath + fileName plist.push( fspromises .lstat(filePath) .then((stat: Stats) => { return stat }) .catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('上传文件出错 ' + err + ' ' + filePath) return undefined }) .then((stat: Stats | undefined) => { readConfig.filetime += 1 const fileItem: IStateUploadTaskFile = { TaskID: readConfig.TaskID, UploadID: readConfig.filetime, partPath: path.join(parentDirPartPath, fileName), name: parentDirName + '/' + fileName, size: stat ? stat.size : 1, sizeStr: humanSize(stat ? stat.size : 1), mtime: stat ? stat.mtime.getTime() : 0 , isDir: false, IsRoot: false, uploaded_is_rapid: false, uploaded_file_id: '' } addFileList.push(fileItem) }) ) if (plist.length >= 10) { await Promise.all(plist).catch(() => {}) plist = [] } } if (plist.length > 0) await Promise.all(plist).catch(() => {}) } async function AddDirs(addFileList: IStateUploadTaskFile[], addDirList: IStateUploadTaskFile[], dirList: string[], parentDirPartPath: string, parentDirName: string, readConfig: ReadConfig, Info: IStateUploadInfo): Promise { const plist: Promise<{ file_id: string; error: string }>[] = [] for (let i = 0, maxi = dirList.length; i < maxi; i++) { const dirName = dirList[i] readConfig.filetime += 1 const dirItem: IStateUploadTaskFile = { TaskID: readConfig.TaskID, UploadID: readConfig.filetime, partPath: path.join(parentDirPartPath, dirName), name: parentDirName + '/' + dirName, size: 0, sizeStr: humanSize(0), mtime: 0 , isDir: true, IsRoot: false, uploaded_is_rapid: false, uploaded_file_id: '' } await readChildrenDiGui(addFileList, addDirList, dirItem, readConfig, Info, plist) Info.failedMessage = '读取中 ' + addFileList.length + '个' if (plist.length >= 10) { await Promise.all(plist).catch(() => {}) plist.splice(0, plist.length) } } if (plist.length > 0) await Promise.all(plist).catch(() => {}) } const MAXFILE = 20 const MAXDIR = 20 async function readChildrenDiGui(addFileList: IStateUploadTaskFile[], addDirList: IStateUploadTaskFile[], diritem: IStateUploadTaskFile, readConfig: ReadConfig, Info: IStateUploadInfo, plist: Promise<{ file_id: string; error: string }>[]): Promise { const localDirPath = path.join(readConfig.localFilePath, diritem.partPath, path.sep) const dirFiles = await readDir(localDirPath, readConfig.ingoredList) if (dirFiles.error) { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) addDirList.push(diritem) return } if (dirFiles.fileList.length == 0) { if (dirFiles.dirList.length == 0) { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) return } else if (dirFiles.dirList.length <= MAXDIR) { await AddDirs(addFileList, addDirList, dirFiles.dirList, diritem.partPath, diritem.name, readConfig, Info) return } else { addDirList.push(diritem) return } } if (dirFiles.fileList.length == 1) { if (dirFiles.dirList.length == 0) { await AddFiles(addFileList, dirFiles.fileList, diritem.partPath, diritem.name, readConfig) return } else if (dirFiles.dirList.length <= MAXDIR) { await AddFiles(addFileList, dirFiles.fileList, diritem.partPath, diritem.name, readConfig) await AddDirs(addFileList, addDirList, dirFiles.dirList, diritem.partPath, diritem.name, readConfig, Info) return } else { addDirList.push(diritem) return } } if (dirFiles.fileList.length <= MAXFILE) { if (dirFiles.dirList.length == 0) { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) await AddFiles(addFileList, dirFiles.fileList, diritem.partPath, diritem.name, readConfig) } else if (dirFiles.dirList.length <= MAXDIR) { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) await AddFiles(addFileList, dirFiles.fileList, diritem.partPath, diritem.name, readConfig) await AddDirs(addFileList, addDirList, dirFiles.dirList, diritem.partPath, diritem.name, readConfig, Info) } else { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) addDirList.push(diritem) } } else { if (dirFiles.dirList.length == 0) { plist.push(AliFileCmd.ApiCreatNewForder(readConfig.user_id, readConfig.drive_id, readConfig.parent_file_id, diritem.name)) addDirList.push(diritem) } else if (dirFiles.dirList.length <= MAXDIR) { addDirList.push(diritem) } else { addDirList.push(diritem) } } } async function readDir(fullDirPath: string, ingoredList: string[]): Promise<{ error: string; fileList: string[]; dirList: string[] }> { let errorMessage = '' const fileList: string[] = [] const dirList: string[] = [] await fspromises .readdir(fullDirPath, { withFileTypes: true }) .then((files: Dirent[]) => { for (let i = 0, maxi = files.length; i < maxi; i++) { const stat = files[i] if (stat.isSymbolicLink()) continue if (CheckWindowsBreakPath(stat.name)) continue if (stat.isDirectory()) dirList.push(stat.name) else if (stat.isFile()) { const filePathLower = stat.name.toLowerCase() let ingored = false for (let j = 0, maxj = ingoredList.length; j < maxj; j++) { if (filePathLower.endsWith(ingoredList[j])) { ingored = true break } } if (!ingored) fileList.push(stat.name) } } }) .catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('UploadLocalDir失败:' + fullDirPath, err) errorMessage = err }) return { error: errorMessage, fileList, dirList } } async function checkFileSize(fileui: IUploadingUI): Promise { let errorMessage = '' const stat = await fspromises.lstat(path.join(fileui.localFilePath, fileui.File.partPath)).catch((err: any) => { err = FileSystemErrorMessage(err.code, err.message) DebugLog.mSaveDanger('StartUpload失败:' + path.join(fileui.localFilePath, fileui.File.partPath), err) errorMessage = err return undefined }) if (!stat) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 102 fileui.Info.failedMessage = errorMessage return } if (fileui.File.size != stat.size) { fileui.File.size = stat.size fileui.Info.up_upload_id = '' fileui.Info.up_file_id = '' } if (fileui.File.mtime != stat.mtime.getTime()) { fileui.File.mtime = stat.mtime.getTime() fileui.Info.up_upload_id = '' fileui.Info.up_file_id = '' } } async function reloadUploadUrl(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise<'success' | 'error' | 'neterror' | 'codeerror'> { uploadInfo.part_info_list = [] let isOk = await AliUpload.UploadFilePartUrl(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo).catch(() => {}) if (isOk != 'success') return isOk || 'codeerror' if (uploadInfo.part_info_list.length > 0) { isOk = await AliUpload.UploadFileListUploadedParts(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, 0, uploadInfo).catch(() => {}) if (isOk == 'success') { const part_info_list = uploadInfo.part_info_list let isUpload = true for (let i = 0, maxi = part_info_list.length; i < maxi; i++) { if (isUpload && part_info_list[i].isupload == false) { isUpload = false } if (isUpload === false && part_info_list[i].isupload == true) part_info_list[i].isupload = false } return 'success' } else if (isOk == 'error') { fileui.Info.up_file_id = '' fileui.Info.up_upload_id = '' uploadInfo.part_info_list = [] return 'success' } else return isOk || 'codeerror' } else { return 'error' } } async function checkPreHashAndGetPartlist(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise { let prehash = '' if (fileui.File.size >= 1024000) { prehash = await AliUploadHashPool.GetFilePreHash(path.join(fileui.localFilePath, fileui.File.partPath)) if (prehash.startsWith('error')) { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 504 fileui.Info.failedMessage = prehash.substring('error'.length) return false } else { const matched = await AliUpload.UploadCreatFileWithPreHash(fileui.user_id, fileui.drive_id, fileui.parent_file_id, fileui.File.name, fileui.File.size, prehash, fileui.check_name_mode) if (!matched.errormsg) { fileui.Info.up_upload_id = matched.upload_id fileui.Info.up_file_id = matched.file_id uploadInfo.part_info_list = matched.part_info_list uploadInfo.israpid = false return true } else if (matched.errormsg != 'PreHashMatched') { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 504 fileui.Info.failedMessage = matched.errormsg return false } } } fileui.Info.uploadState = 'hashing' const proof = await AliUploadHashPool.GetFileHashProofWorker(prehash, uploadInfo.access_token, fileui) fileui.Info.uploadState = 'running' if (!fileui.IsRunning) { fileui.Info.uploadState = '已暂停' fileui.Info.failedCode = 0 fileui.Info.failedMessage = '' return false } if (proof.sha1 == 'error') { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 503 fileui.Info.failedMessage = '计算sha1出错' + proof.error return false } uploadInfo.sha1 = proof.sha1 const miaoChuan = await AliUpload.UploadCreatFileWithFolders(fileui.user_id, fileui.drive_id, fileui.parent_file_id, fileui.File.name, fileui.File.size, proof.sha1, proof.proof_code, fileui.check_name_mode) if (miaoChuan.errormsg != '') { fileui.Info.uploadState = 'error' fileui.Info.failedCode = 504 fileui.Info.failedMessage = miaoChuan.errormsg return false } else if (miaoChuan.israpid || miaoChuan.isexist) { fileui.Info.uploadState = 'success' fileui.File.uploaded_file_id = miaoChuan.file_id fileui.File.uploaded_is_rapid = true fileui.Info.up_file_id = '' fileui.Info.up_upload_id = '' return false } else { fileui.Info.up_upload_id = miaoChuan.upload_id fileui.Info.up_file_id = miaoChuan.file_id uploadInfo.part_info_list = miaoChuan.part_info_list uploadInfo.israpid = false return true } } ================================================ FILE: src/renderer/workerpage/workercmd.ts ================================================ import AliDirList from '../aliapi/dirlist' import { useSettingStore } from '../store' import TreeStore from '../store/treestore' import UserDAL from '../user/userdal' import DebugLog from '../utils/debuglog' import { DownloadTrigger } from './uidownload' import { UploadAdd, UploadCmd, UploadReport } from './uiupload' // eslint-disable-next-line no-unused-vars let workerTimer: any export function WorkerPage(type: string) { if (window.WinMsg) return if (type == 'upload') { window.WinMsg = WinMsgUpload const func = () => { try { UploadReport().catch() } catch {} workerTimer = setTimeout(func, 1000) } workerTimer = setTimeout(func, 6000) const element = document.createElement('div') element.innerHTML = '

上传进程

' document.body.append(element) } if (type == 'download') { window.WinMsg = WinMsgDownload const func = () => { try { DownloadTrigger() } catch {} workerTimer = setTimeout(func, 1000) } workerTimer = setTimeout(func, 6000) const element = document.createElement('div') element.innerHTML = '

下载进程

' document.body.append(element) } } const AllDirLock = new Map() export const WinMsgUpload = function (arg: any) { // console.log(arg) try { if (arg.cmd == 'SettingRefresh') { useSettingStore().$reset() } else if (arg.cmd == 'ClearUserToken') { UserDAL.ClearUserTokenMap() } else if (arg.cmd == 'UploadAdd') { UploadAdd(arg.UploadList) } else if (arg.cmd == 'UploadCmd') { UploadCmd(arg.Command, arg.IsAll, arg.UploadIDList, arg.TaskIDList) } else if (arg.cmd == 'AllDirList') { LoadAllDirList(arg.user_id, arg.drive_id) } } catch {} } function LoadAllDirList(user_id: string, drive_id: string): void { console.time('AllDirList') const lock = AllDirLock.get(drive_id) || 0 const time = Date.now() / 1000 console.log('AllDirList', 'lock=', lock, 'time=', time) if (lock) { if (time - lock < 300) { console.log('AllDirList Break') window.WinMsgToMain({ cmd: 'MainSaveAllDir', OneDriver: undefined, ErrorMessage: 'time' }) return } } AllDirLock.set(drive_id, time) AliDirList.ApiFastAllDirListByPID(user_id, drive_id) .then((data) => { console.timeEnd('AllDirList') AllDirLock.delete(drive_id) if (!data.next_marker) { TreeStore.ConvertToOneDriver(drive_id, data.items, true, false).then((one) => { window.WinMsgToMain({ cmd: 'MainSaveAllDir', OneDriver: one, ErrorMessage: '' }) }) } else { DebugLog.mSaveWarning('列出文件夹失败file_id=all' + ' next_marker=' + data.next_marker) window.WinMsgToMain({ cmd: 'MainSaveAllDir', OneDriver: undefined, ErrorMessage: data.next_marker }) } }) .catch((err: any) => { DebugLog.mSaveWarning('列出文件夹失败file_id=all', err) window.WinMsgToMain({ cmd: 'MainSaveAllDir', OneDriver: undefined, ErrorMessage: err.message || '未知错误' }) }) } export const WinMsgDownload = function (arg: any) { // console.log(arg) try { if (arg.cmd == 'SettingRefresh') { useSettingStore().$reset() } else if (arg.cmd == 'ClearUserToken') { UserDAL.ClearUserTokenMap() } } catch {} } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "node", "importHelpers": true, "jsx": "preserve", "esModuleInterop": true, "resolveJsonModule": true, "sourceMap": false, "strict": true, "paths": {}, "allowSyntheticDefaultImports": true, "skipLibCheck": true } } ================================================ FILE: types.d.ts ================================================ declare namespace NodeJS { interface ProcessEnv { NODE_ENV: 'development' | 'production' readonly VITE_DEV_SERVER_HOST: string readonly VITE_DEV_SERVER_PORT: string } } declare interface Window { Electron: any platform: any WebToElectron: any WebToElectronCB: any WebSpawnSync: any WebExecSync: any WebShowOpenDialogSync: any WebShowSaveDialogSync: any WebShowItemInFolder: any WebPlatformSync: any WebClearCookies: any WebClearCache: any WebSaveTheme: any WebUserToken: any WebReload: any WebRelaunch: any WebRelaunchAria: any WebSetProgressBar: any WebSetCookies: any WebOpenWindow: any WebShutDown: any openDatabase: any loginfn: any postdataFunc: any Prism: any winmain: number winworker: number WinMsg: any WinMsgToMain: any WinMsgToUI: any getDvaApp: any dark: boolean test: any } ================================================ FILE: v2.10.19性能测试.md ================================================ 阿里云盘小白羊版性能测试 ==== 阿里云盘小白羊版 v2.10.19做个能测试 >测试方法,就是简单的选择文件上传下载,人工计时 > >测试平台:18年产联想Y7000笔记本,i5-8300H,16G内存,512GB M2 西数固态硬盘 #### 补充说明 1. 所有测试上传的文件都是可以秒传的,既只测试程序性能,不测试网络性能。 2. 只测试一遍没有多次测试取平均值,测试期间电脑不运行其他程序,上传中不操作电脑 3. 测试基于特定程序版本,人工计时有误差。结果并不能说明什么 ------
### 测试结果 小白羊占用较低的CPU和内存,但对比阿里云盘官方PC客户端更快

------ #### 测试方案一:大量小文件 M2.SSD硬盘上的 4.4万个json格式小文件(共24GB) 上传到网盘再从网盘下载到本地 | 程序 | CPU | 内存 | 总用时 | 用时基准 | | --- | :---: | :---: | ---: | ---: | | 上传 | | | | | | 小白羊版 v2.10.19 | 15% | 300MB | 24分钟 | :zap:58% | | PC客户端 v2.2.6 | [20%-39%]() | [860MB-1.7GB]() | 41分钟 | 100% | | 下载 | | | | | | 小白羊版 v2.10.19 | 15% | 220MB | 25分钟 | :zap:42% | | PC客户端 v2.2.6 | [40%-66%]() | 400MB | 59分钟 | 100% |
注: 1. 小白羊在设置里设置为60文件同时执行,PC客户端并不支持修改同时执行任务数 1. 上传小文件时PC客户端CPU使用率和内存使用量浮动很大 2. 测试是一次性下载258个文件夹,每个文件夹里包含100-800个文件,PC客户端出现了大量下载失败,手动重新开始,导致总用时记录的不准确
------ #### 测试方案二:批量大文件 M2.SSD硬盘上的 33个大文件(共90GB)上传到网盘再从网盘下载到本地 | 程序 | CPU | 内存 | 总用时 | 用时基准 | | --- | :---: | :---: | ---: | ---: | | 上传 | | | | | | 小白羊版 v2.10.19 | 57% | 200MB | 1分10秒 | :zap:44% | | PC客户端 v2.2.6 | 36% | 190MB | 2分40秒 | 100% | | 下载 | | | | | | 小白羊版 v2.10.19 | 15% | 294MB | 38分钟 | :zap:52% | | PC客户端 v2.2.6 | 26% | 188MB | 72分钟 | 100% |
------ ================================================ FILE: v2.11.11自定义播放软件.md ================================================ 自v2.11.11开始实验性的支持自己选择播放软件 只要播放软件本身支持传入URL后播放,就可以用,下面列出了已测试可用的播放软件,还有很多软件以后会慢慢测试补充上来 支持 windows(7款) mac (3款) linux (8款)如下: # ### windows: 操作:小白羊--设置--UI--自定义播放软件--选择播放软件 在弹窗后,选择桌面上的播放软件的快捷方式(例如:VLC media player) 或者直接选择播放软件的exe文件(例如:C:\Program Files\VideoLAN\VLC\vlc.exe) # 已测试支持的: 1. MPV播放器 2. Potplayer 3. VLC media player 4. KMPlayer 5. 恒星播放器 6. SMPlayer 7. MPC-HC ![Image](https://raw.githubusercontent.com/liupan1890/aliyunpan/main/doc/win%E9%80%89%E6%8B%A9.png) # 不能用的: 1. 影音先锋(只支持原话视频,不支持转码视频) 2. QQ影音播放器(可以复制下载地址后播放) 3. 迅雷影音播放器 4. 搜狐影音 5. 暴风影音 # ### macos: 操作:小白羊--设置--UI--自定义播放软件--选择播放软件 在弹窗后,点击左侧的 应用程序,点击 IINA,点击 选择 已测试支持的: 1. IINA 2. MKPlayer 3. VLC ![Image](https://raw.githubusercontent.com/liupan1890/aliyunpan/main/doc/mac%E9%80%89%E6%8B%A9.png) # 已测试不能直接用,但是可以复制url后在app里打开播放的: 1. 恒星播放器 2. Elmedia Video Player 3. OmniPlayerStore 4. IMVIDEO 5. MAX 播放器 # ### linux 操作:小白羊--设置--UI--自定义播放软件 点击输入框(弹出下拉菜单),直接选择其中一个,最后点击保存按钮! 也可以自己手动输入,其他电脑上已安装的播放软件(需要能在终端通过软件名正常调用) 注意:linux 只测试了ubuntu 20.04 已测试支持的: 1. totem    [sudo apt install totem]() 2. vlc     [sudo apt install vlc]() 3. mpv    [sudo apt install mpv]() 4. kodi    [sudo apt install kodi]() 5. mplayer   [sudo apt install mplayer mplayer-gui]() 6. smplayer  [sudo apt install smplayer]() 7. xine    [sudo apt install xine-ui]() 8. parole   [sudo apt install parole]() ![Image](https://raw.githubusercontent.com/liupan1890/aliyunpan/main/doc/linux%E9%80%89%E6%8B%A9.png) # 已测试不能直接用,但是可以复制url后在app里打开播放的: 1. deepin-movie 2. dragon player ================================================ FILE: 开源代码统计.md ================================================ **v1.0629 -- 21472行 (go + flutter)**
aliserver
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                              56            965            957           8951
-------------------------------------------------------------------------------
SUM:                            56            965            957           8951
-------------------------------------------------------------------------------
xbycode
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Dart                            79           1099            337          12476
YAML                             1             12             45             45
-------------------------------------------------------------------------------
SUM:                            80           1111            382          12521
-------------------------------------------------------------------------------
**v2.0924 -- 18271行 (ts + vue2 + quasar)**
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
TypeScript                      47            574             66           9205
Vuejs Component                 47            392             22           7435
JavaScript                       8            109            106            837
CSS                              2            180              0            702
JSON                             2              0              0             66
HTML                             1              2              2             20
Protocol Buffers                 1              1              0              6
-------------------------------------------------------------------------------
SUM:                           108           1258            196          18271
-------------------------------------------------------------------------------
**v2.1214 -- 25194行 (ts + react + antd)**
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
TypeScript                     104           1391            722          21481
CSS                             10            408              2           3439
JSON                             2              0              0            124
JavaScript                       1              1              0             71
Markdown                         1             11              0             46
EJS                              1              0              0             25
DOS Batch                        5              0              0              8
-------------------------------------------------------------------------------
SUM:                           124           1811            724          25194
-------------------------------------------------------------------------------
**v3.0210 -- 22773行 (ts + react + antd)**
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
TypeScript                     119           1371            683          18950
CSS                             10            415              2           3503
JSON                             3              0              0            143
JavaScript                       2              2              0             91
Markdown                         1             11              0             46
EJS                              1              0              0             25
DOS Batch                        5              0              0              8
HTML                             1              3              0              7
-------------------------------------------------------------------------------
SUM:                           142           1802            685          22773
-------------------------------------------------------------------------------
**v3.0523 -- 26498行 (ts + vue3 + arco-design + ant-design-vue)**
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Vuejs Component                 75            930            170          12396
TypeScript                      80            910            996          11835
CSS                              4            322              3           1935
JSON                             4              0              0            128
JavaScript                       4              8             15            128
HTML                             2              6              0             58
Markdown                         1              2              0             12
DOS Batch                        2              0              0              6
-------------------------------------------------------------------------------
SUM:                           172           2178           1184          26498
-------------------------------------------------------------------------------
**adrive sdk**
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Markdown                        25            735              0           3812
-------------------------------------------------------------------------------
SUM:                            25            735              0           3812
-------------------------------------------------------------------------------
**开源代码近一年时间,统计一共写了( 114000行 11.4万行)** **上面列出的都是大版本,每个版本之间代码重复率很低,并不是复制粘贴的,统计也已经排除了使用的各种第三方类库,写程序会来来回回的反复修改所以真正写的代码比最终结果11.4万还应该多出15%(已经被删除的代码)** ================================================ FILE: 源码开发打包帮助.md ================================================ ### 小白羊v3版本源码帮助 v3采用 ts+vue3+vite+electron 模板开发 #### 1.下载源代码 ``` https://github.com/liupan1890/aliyunpan.git ``` #### 2.打开代码目录,安装依赖 ```cmd yarn install ``` #### 3.开发调试运行 ```cmd yarn run dev ``` 执行命令后会调起electron窗口,配合vscode正常开发调试即可 #### 4.打包发布 ```cmd yarn run build ``` 执行命令后会生成`release\win-unpacked\resources\app.asar`文件。把该文件复制到任意electron版本的`resources`目录下即可打包出安装包