Copy disabled (too large)
Download .txt
Showing preview only (31,777K chars total). Download the full file to get everything.
Repository: chaxus/ran
Branch: main
Commit: 652113ce338a
Files: 919
Total size: 53.0 MB
Directory structure:
gitextract_yjd90j70/
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── ci.yml
│ ├── pages-build-site.yml
│ └── semantic-pull-request.yml
├── .gitignore
├── .jscpd.json
├── .prettierignore
├── .prettierrc.json
├── .vscode/
│ ├── c_cpp_properties.json
│ ├── launch.json
│ ├── markdown.code-snippets
│ ├── ranui-components.code-snippets
│ ├── settings.json
│ └── ts.json.code-snippets
├── LICENSE
├── SECURITY.md
├── bin/
│ ├── build.sh
│ ├── clean.sh
│ ├── install.sh
│ ├── lint.sh
│ ├── nvm.sh
│ ├── preinstall.sh
│ └── test.sh
├── eslint.config.js
├── index.html
├── package.json
├── packages/
│ ├── cpro/
│ │ ├── package.json
│ │ ├── readme.md
│ │ └── sum.cpp
│ ├── debug/
│ │ ├── koaStatic/
│ │ │ ├── index.ts
│ │ │ └── readme.md
│ │ ├── nginxconf/
│ │ │ ├── agency.conf
│ │ │ └── readme.md
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── docs/
│ │ ├── .vitepress/
│ │ │ ├── common/
│ │ │ │ ├── index.ts
│ │ │ │ └── sw.ts
│ │ │ ├── components/
│ │ │ │ ├── Layout.vue
│ │ │ │ └── TOTP.vue
│ │ │ ├── composition/
│ │ │ │ └── useBasic.ts
│ │ │ ├── config.ts
│ │ │ ├── lang/
│ │ │ │ ├── en.json
│ │ │ │ ├── index.ts
│ │ │ │ └── zh-CN.json
│ │ │ ├── langs/
│ │ │ │ ├── cn/
│ │ │ │ │ └── index.ts
│ │ │ │ └── en/
│ │ │ │ └── index.ts
│ │ │ ├── lib/
│ │ │ │ └── constant.ts
│ │ │ ├── plugins/
│ │ │ │ └── env.ts
│ │ │ └── theme/
│ │ │ ├── index.ts
│ │ │ ├── styles/
│ │ │ │ ├── index.less
│ │ │ │ └── vars.less
│ │ │ └── theme.less
│ │ ├── bin/
│ │ │ └── build.sh
│ │ ├── cn/
│ │ │ ├── index.md
│ │ │ └── src/
│ │ │ ├── article/
│ │ │ │ ├── ai/
│ │ │ │ │ └── index.md
│ │ │ │ ├── ast_parse/
│ │ │ │ │ └── tokenizer.md
│ │ │ │ ├── babel.md
│ │ │ │ ├── bundle.md
│ │ │ │ ├── design_mode.md
│ │ │ │ ├── doc_preview.md
│ │ │ │ ├── functional_programming.md
│ │ │ │ ├── imagemin.md
│ │ │ │ ├── javascript/
│ │ │ │ │ └── dom_load.md
│ │ │ │ ├── math/
│ │ │ │ │ └── linear_algebra.md
│ │ │ │ ├── sort/
│ │ │ │ │ ├── bubble/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── bucket/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── count/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── heap/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── index.md
│ │ │ │ │ ├── insert/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── merge/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── quick/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── radix/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── select/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ └── shell/
│ │ │ │ │ └── index.md
│ │ │ │ ├── system_design.md
│ │ │ │ ├── typescript/
│ │ │ │ │ ├── calculate.md
│ │ │ │ │ ├── index.md
│ │ │ │ │ ├── pattern.md
│ │ │ │ │ ├── reconstruction.md
│ │ │ │ │ ├── recursion.md
│ │ │ │ │ └── union_type.md
│ │ │ │ ├── video.md
│ │ │ │ └── visual.md
│ │ │ ├── blockchain/
│ │ │ │ ├── index.md
│ │ │ │ └── web3.md
│ │ │ ├── note/
│ │ │ │ ├── centos.md
│ │ │ │ ├── docker.md
│ │ │ │ ├── libreoffice2wasm.md
│ │ │ │ └── ubuntu.md
│ │ │ ├── ranui/
│ │ │ │ ├── button/
│ │ │ │ │ └── index.md
│ │ │ │ ├── checkbox/
│ │ │ │ │ └── index.md
│ │ │ │ ├── icon/
│ │ │ │ │ └── index.md
│ │ │ │ ├── image/
│ │ │ │ │ └── index.md
│ │ │ │ ├── index.md
│ │ │ │ ├── input/
│ │ │ │ │ └── index.md
│ │ │ │ ├── loading/
│ │ │ │ │ └── index.md
│ │ │ │ ├── math/
│ │ │ │ │ └── index.md
│ │ │ │ ├── message/
│ │ │ │ │ └── index.md
│ │ │ │ ├── modal/
│ │ │ │ │ └── index.md
│ │ │ │ ├── player/
│ │ │ │ │ └── index.md
│ │ │ │ ├── popover/
│ │ │ │ │ └── index.md
│ │ │ │ ├── preview/
│ │ │ │ │ └── index.md
│ │ │ │ ├── progress/
│ │ │ │ │ └── index.md
│ │ │ │ ├── radar/
│ │ │ │ │ └── index.md
│ │ │ │ ├── select/
│ │ │ │ │ └── index.md
│ │ │ │ ├── skeleton/
│ │ │ │ │ └── index.md
│ │ │ │ ├── tab/
│ │ │ │ │ └── index.md
│ │ │ │ └── tabs/
│ │ │ │ └── index.md
│ │ │ ├── ranuts/
│ │ │ │ ├── binary_tree/
│ │ │ │ │ └── index.md
│ │ │ │ ├── bundler/
│ │ │ │ │ └── index.md
│ │ │ │ ├── file/
│ │ │ │ │ ├── append_file.md
│ │ │ │ │ ├── file_info.md
│ │ │ │ │ ├── read_dir.md
│ │ │ │ │ ├── read_file.md
│ │ │ │ │ ├── watch_file.md
│ │ │ │ │ └── write_file.md
│ │ │ │ ├── index.md
│ │ │ │ ├── mime_type/
│ │ │ │ │ └── mime_type.md
│ │ │ │ ├── mode/
│ │ │ │ │ └── subscribe.md
│ │ │ │ └── utils/
│ │ │ │ ├── add_class_to_element.md
│ │ │ │ ├── add_num_sym.md
│ │ │ │ ├── append_url.md
│ │ │ │ ├── chain.md
│ │ │ │ ├── change_hump_to_lower_case.md
│ │ │ │ ├── check_encoding.md
│ │ │ │ ├── clear_br.md
│ │ │ │ ├── clear_str.md
│ │ │ │ ├── clone_deep.md
│ │ │ │ ├── compose.md
│ │ │ │ ├── connection.md
│ │ │ │ ├── convert_image_to_base64.md
│ │ │ │ ├── create.md
│ │ │ │ ├── create_document_fragment.md
│ │ │ │ ├── create_object_url.md
│ │ │ │ ├── create_signal.md
│ │ │ │ ├── current_device.md
│ │ │ │ ├── debounce.md
│ │ │ │ ├── duration_handler.md
│ │ │ │ ├── encode_url.md
│ │ │ │ ├── escape_html.md
│ │ │ │ ├── filter_obj.md
│ │ │ │ ├── format_json.md
│ │ │ │ ├── get_all_query_string.md
│ │ │ │ ├── get_cookie.md
│ │ │ │ ├── get_cookie_by_name.md
│ │ │ │ ├── get_extensions.md
│ │ │ │ ├── get_frame.md
│ │ │ │ ├── get_host.md
│ │ │ │ ├── get_matching_sentences.md
│ │ │ │ ├── get_performance.md
│ │ │ │ ├── get_pixel_ratio.md
│ │ │ │ ├── get_query.md
│ │ │ │ ├── get_window.md
│ │ │ │ ├── handle_console.md
│ │ │ │ ├── handle_error.md
│ │ │ │ ├── handle_fetch_hook.md
│ │ │ │ ├── hex_to_rgb.md
│ │ │ │ ├── image_request.md
│ │ │ │ ├── index.md
│ │ │ │ ├── is_bang_device.md
│ │ │ │ ├── is_client.md
│ │ │ │ ├── is_equal.md
│ │ │ │ ├── is_image_size.md
│ │ │ │ ├── is_mobile.md
│ │ │ │ ├── is_safari.md
│ │ │ │ ├── is_string.md
│ │ │ │ ├── is_weixin.md
│ │ │ │ ├── local_storage.md
│ │ │ │ ├── mathjs.md
│ │ │ │ ├── md5.md
│ │ │ │ ├── memoize.md
│ │ │ │ ├── merge.md
│ │ │ │ ├── network_speed.md
│ │ │ │ ├── noop.md
│ │ │ │ ├── ocr.md
│ │ │ │ ├── per_to_num.md
│ │ │ │ ├── performance_time.md
│ │ │ │ ├── querystring.md
│ │ │ │ ├── random_color.md
│ │ │ │ ├── random_string.md
│ │ │ │ ├── range.md
│ │ │ │ ├── remove_class_to_element.md
│ │ │ │ ├── remove_ghosting.md
│ │ │ │ ├── retain.md
│ │ │ │ ├── rgb_to_hex.md
│ │ │ │ ├── script_on_load.md
│ │ │ │ ├── set_attribute_by_global.md
│ │ │ │ ├── set_mime.md
│ │ │ │ ├── str2xml.md
│ │ │ │ ├── str_parse.md
│ │ │ │ ├── sync_hook.md
│ │ │ │ ├── task.md
│ │ │ │ ├── throttle.md
│ │ │ │ ├── time_format.md
│ │ │ │ ├── timestamp_to_time.md
│ │ │ │ ├── to_string.md
│ │ │ │ ├── totp.md
│ │ │ │ ├── transform_number.md
│ │ │ │ └── transform_text.md
│ │ │ └── types/
│ │ │ ├── TS类型.md
│ │ │ ├── 模式匹配.md
│ │ │ ├── 类型运算.md
│ │ │ └── 高级类型.md
│ │ ├── index.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── hls/
│ │ │ │ ├── 5_1701577744714/
│ │ │ │ │ ├── 5.key
│ │ │ │ │ ├── 5.m3u8
│ │ │ │ │ ├── 5_00000.ts
│ │ │ │ │ ├── 5_00001.ts
│ │ │ │ │ ├── 5_00002.ts
│ │ │ │ │ ├── 5_00003.ts
│ │ │ │ │ ├── 5_00004.ts
│ │ │ │ │ ├── 5_00005.ts
│ │ │ │ │ └── 5_00006.ts
│ │ │ │ ├── 5_1701577771368/
│ │ │ │ │ ├── 5.key
│ │ │ │ │ ├── 5.m3u8
│ │ │ │ │ ├── 5_00000.ts
│ │ │ │ │ ├── 5_00001.ts
│ │ │ │ │ ├── 5_00002.ts
│ │ │ │ │ ├── 5_00003.ts
│ │ │ │ │ ├── 5_00004.ts
│ │ │ │ │ ├── 5_00005.ts
│ │ │ │ │ └── 5_00006.ts
│ │ │ │ └── example.m3u8
│ │ │ ├── manifest.json
│ │ │ └── sw.js
│ │ ├── src/
│ │ │ ├── article/
│ │ │ │ ├── ast_parse/
│ │ │ │ │ └── tokenizer.md
│ │ │ │ ├── babel.md
│ │ │ │ ├── bundle.md
│ │ │ │ ├── design_mode.md
│ │ │ │ ├── functional_programming.md
│ │ │ │ ├── imagemin.md
│ │ │ │ ├── javascript/
│ │ │ │ │ └── dom_load.md
│ │ │ │ ├── sort/
│ │ │ │ │ ├── bubble/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── bucket/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── count/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── heap/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── index.md
│ │ │ │ │ ├── insert/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── merge/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── quick/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── radix/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ ├── select/
│ │ │ │ │ │ └── index.md
│ │ │ │ │ └── shell/
│ │ │ │ │ └── index.md
│ │ │ │ └── typescript/
│ │ │ │ ├── calculate.md
│ │ │ │ ├── index.md
│ │ │ │ ├── pattern.md
│ │ │ │ ├── reconstruction.md
│ │ │ │ ├── recursion.md
│ │ │ │ └── union_type.md
│ │ │ ├── ranui/
│ │ │ │ ├── button/
│ │ │ │ │ └── index.md
│ │ │ │ ├── checkbox/
│ │ │ │ │ └── index.md
│ │ │ │ ├── icon/
│ │ │ │ │ └── index.md
│ │ │ │ ├── image/
│ │ │ │ │ └── index.md
│ │ │ │ ├── index.md
│ │ │ │ ├── input/
│ │ │ │ │ └── index.md
│ │ │ │ ├── loading/
│ │ │ │ │ └── index.md
│ │ │ │ ├── math/
│ │ │ │ │ └── index.md
│ │ │ │ ├── message/
│ │ │ │ │ └── index.md
│ │ │ │ ├── modal/
│ │ │ │ │ └── index.md
│ │ │ │ ├── player/
│ │ │ │ │ └── index.md
│ │ │ │ ├── popover/
│ │ │ │ │ └── index.md
│ │ │ │ ├── preview/
│ │ │ │ │ └── index.md
│ │ │ │ ├── progress/
│ │ │ │ │ └── index.md
│ │ │ │ ├── radar/
│ │ │ │ │ └── index.md
│ │ │ │ ├── select/
│ │ │ │ │ └── index.md
│ │ │ │ ├── skeleton/
│ │ │ │ │ └── index.md
│ │ │ │ ├── tab/
│ │ │ │ │ └── index.md
│ │ │ │ └── tabs/
│ │ │ │ └── index.md
│ │ │ ├── ranuts/
│ │ │ │ ├── binary_tree/
│ │ │ │ │ └── index.md
│ │ │ │ ├── bundler/
│ │ │ │ │ └── index.md
│ │ │ │ ├── file/
│ │ │ │ │ ├── append_file.md
│ │ │ │ │ ├── file_info.md
│ │ │ │ │ ├── read_dir.md
│ │ │ │ │ ├── read_file.md
│ │ │ │ │ ├── watch_file.md
│ │ │ │ │ └── write_file.md
│ │ │ │ ├── index.md
│ │ │ │ ├── mime_type/
│ │ │ │ │ └── mime_type.md
│ │ │ │ ├── mode/
│ │ │ │ │ └── subscribe.md
│ │ │ │ └── utils/
│ │ │ │ ├── add_class_to_element.md
│ │ │ │ ├── add_num_sym.md
│ │ │ │ ├── append_url.md
│ │ │ │ ├── chain.md
│ │ │ │ ├── change_hump_to_lower_case.md
│ │ │ │ ├── check_encoding.md
│ │ │ │ ├── clear_br.md
│ │ │ │ ├── clear_str.md
│ │ │ │ ├── clone_deep.md
│ │ │ │ ├── compose.md
│ │ │ │ ├── connection.md
│ │ │ │ ├── convert_image_to_base64.md
│ │ │ │ ├── create.md
│ │ │ │ ├── create_document_fragment.md
│ │ │ │ ├── create_object_url.md
│ │ │ │ ├── create_signal.md
│ │ │ │ ├── current_device.md
│ │ │ │ ├── debounce.md
│ │ │ │ ├── duration_handler.md
│ │ │ │ ├── encode_url.md
│ │ │ │ ├── escape_html.md
│ │ │ │ ├── filter_obj.md
│ │ │ │ ├── format_json.md
│ │ │ │ ├── get_all_query_string.md
│ │ │ │ ├── get_cookie.md
│ │ │ │ ├── get_cookie_by_name.md
│ │ │ │ ├── get_extensions.md
│ │ │ │ ├── get_frame.md
│ │ │ │ ├── get_host.md
│ │ │ │ ├── get_matching_sentences.md
│ │ │ │ ├── get_performance.md
│ │ │ │ ├── get_pixel_ratio.md
│ │ │ │ ├── get_query.md
│ │ │ │ ├── get_window.md
│ │ │ │ ├── handle_console.md
│ │ │ │ ├── handle_error.md
│ │ │ │ ├── handle_fetch_hook.md
│ │ │ │ ├── hex_to_rgb.md
│ │ │ │ ├── image_request.md
│ │ │ │ ├── index.md
│ │ │ │ ├── is_bang_device.md
│ │ │ │ ├── is_client.md
│ │ │ │ ├── is_equal.md
│ │ │ │ ├── is_image_size.md
│ │ │ │ ├── is_mobile.md
│ │ │ │ ├── is_safari.md
│ │ │ │ ├── is_string.md
│ │ │ │ ├── is_weixin.md
│ │ │ │ ├── local_storage.md
│ │ │ │ ├── mathjs.md
│ │ │ │ ├── md5.md
│ │ │ │ ├── memoize.md
│ │ │ │ ├── merge.md
│ │ │ │ ├── network_speed.md
│ │ │ │ ├── noop.md
│ │ │ │ ├── ocr.md
│ │ │ │ ├── per_to_num.md
│ │ │ │ ├── performance_time.md
│ │ │ │ ├── querystring.md
│ │ │ │ ├── random_color.md
│ │ │ │ ├── random_string.md
│ │ │ │ ├── range.md
│ │ │ │ ├── remove_class_to_element.md
│ │ │ │ ├── remove_ghosting.md
│ │ │ │ ├── retain.md
│ │ │ │ ├── rgb_to_hex.md
│ │ │ │ ├── script_on_load.md
│ │ │ │ ├── set_attribute_by_global.md
│ │ │ │ ├── set_mime.md
│ │ │ │ ├── str2xml.md
│ │ │ │ ├── str_parse.md
│ │ │ │ ├── sync_hook.md
│ │ │ │ ├── task.md
│ │ │ │ ├── throttle.md
│ │ │ │ ├── time_format.md
│ │ │ │ ├── timestamp_to_time.md
│ │ │ │ ├── to_string.md
│ │ │ │ ├── totp.md
│ │ │ │ ├── transform_number.md
│ │ │ │ └── transform_text.md
│ │ │ └── types/
│ │ │ ├── TS类型.md
│ │ │ ├── 模式匹配.md
│ │ │ ├── 类型运算.md
│ │ │ └── 高级类型.md
│ │ ├── tsconfig.json
│ │ ├── typings.d.ts
│ │ ├── variable/
│ │ │ └── SERVICE_WORK_VERSION.ts
│ │ └── vue/
│ │ └── loading.vue
│ ├── im/
│ │ ├── app/
│ │ │ ├── controllers/
│ │ │ │ ├── home.ts
│ │ │ │ ├── im.ts
│ │ │ │ └── user.ts
│ │ │ ├── index.ts
│ │ │ ├── lib/
│ │ │ │ ├── constant.ts
│ │ │ │ ├── context.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── request.ts
│ │ │ │ ├── response.ts
│ │ │ │ └── vite.ts
│ │ │ ├── router.config.ts
│ │ │ ├── routes.ts
│ │ │ └── types/
│ │ │ └── index.ts
│ │ ├── bin/
│ │ │ └── dev.sh
│ │ ├── client/
│ │ │ ├── app.tsx
│ │ │ ├── assets/
│ │ │ │ └── base.css
│ │ │ ├── client.tsx
│ │ │ ├── components/
│ │ │ │ ├── backdrop/
│ │ │ │ │ ├── index.module.less
│ │ │ │ │ └── index.tsx
│ │ │ │ └── loading/
│ │ │ │ ├── index.module.less
│ │ │ │ └── index.tsx
│ │ │ ├── lib/
│ │ │ │ ├── eventSource.ts
│ │ │ │ ├── hook.ts
│ │ │ │ └── index.ts
│ │ │ ├── pages/
│ │ │ │ └── home/
│ │ │ │ └── index.tsx
│ │ │ ├── router/
│ │ │ │ └── index.tsx
│ │ │ └── server.tsx
│ │ ├── package.json
│ │ ├── readme.md
│ │ ├── rest/
│ │ │ └── user.rest
│ │ ├── tsconfig.json
│ │ ├── typings.d.ts
│ │ ├── views/
│ │ │ └── index.html
│ │ └── vite.config.ts
│ ├── image-process/
│ │ ├── .gitignore
│ │ ├── CMakeLists.txt
│ │ ├── CMakeUserPresets.json
│ │ ├── conanfile.txt
│ │ ├── index.ts
│ │ ├── main.c
│ │ ├── makefile
│ │ ├── package.json
│ │ ├── readme.md
│ │ └── src/
│ │ ├── image_processing.c
│ │ └── image_processing.h
│ ├── ml/
│ │ ├── assets/
│ │ │ ├── dataset/
│ │ │ │ ├── ChnSentiCorp_htl_all.csv
│ │ │ │ ├── kc_house_data.csv
│ │ │ │ └── min_label_review.csv
│ │ │ └── ebook/
│ │ │ └── txt/
│ │ │ ├── JaneEyre.txt
│ │ │ ├── TheHunchbackofNotre-Dame.txt
│ │ │ ├── camelXiangzi.txt
│ │ │ ├── princekin.txt
│ │ │ ├── shakespeare.txt
│ │ │ ├── snowWhite.txt
│ │ │ ├── theThreeKingdoms.txt
│ │ │ ├── theWealthOfNations.txt
│ │ │ ├── training_data_1748151735437.json
│ │ │ └── walden.txt
│ │ ├── bin/
│ │ │ └── build.sh
│ │ ├── client/
│ │ │ ├── components/
│ │ │ │ ├── BinaryModel.tsx
│ │ │ │ ├── Emotion.tsx
│ │ │ │ ├── LineModel.tsx
│ │ │ │ └── MultiModel.tsx
│ │ │ ├── index.tsx
│ │ │ └── lib.ts
│ │ ├── config/
│ │ │ ├── build.es.ts
│ │ │ └── build.umd.ts
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── readme.md
│ │ ├── server/
│ │ │ └── index.ts
│ │ ├── src/
│ │ │ └── ebook/
│ │ │ ├── index.ts
│ │ │ └── trainData.ts
│ │ ├── tsconfig.json
│ │ ├── typings.d.ts
│ │ └── vite.config.ts
│ ├── precss/
│ │ └── sass/
│ │ ├── _base.scss
│ │ ├── _function.scss
│ │ └── styles/
│ │ ├── animation.scss
│ │ ├── common.scss
│ │ ├── global.css
│ │ ├── mixin/
│ │ │ ├── bangs.scss
│ │ │ ├── ellipsis.scss
│ │ │ ├── index.scss
│ │ │ ├── make-animation.scss
│ │ │ ├── px2rem.scss
│ │ │ ├── screen.scss
│ │ │ ├── supports-safe-area-insets.scss
│ │ │ └── thinBorder.scss
│ │ ├── themes.scss
│ │ └── variables.scss
│ ├── ranite/
│ │ ├── bin/
│ │ │ └── ranite
│ │ ├── package.json
│ │ ├── readme.md
│ │ ├── src/
│ │ │ ├── client/
│ │ │ │ └── client.ts
│ │ │ └── node/
│ │ │ ├── ModuleGraph.ts
│ │ │ ├── cli.ts
│ │ │ ├── constants.ts
│ │ │ ├── hmr.ts
│ │ │ ├── optimizer/
│ │ │ │ ├── index.ts
│ │ │ │ ├── preBundlePlugin.ts
│ │ │ │ └── scanPlugin.ts
│ │ │ ├── plugin.ts
│ │ │ ├── pluginContainer.ts
│ │ │ ├── plugins/
│ │ │ │ ├── assets.ts
│ │ │ │ ├── clientInject.ts
│ │ │ │ ├── css.ts
│ │ │ │ ├── esbuild.ts
│ │ │ │ ├── importAnalysis.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── react-hmr.ts
│ │ │ │ └── resolve.ts
│ │ │ ├── server/
│ │ │ │ ├── index.ts
│ │ │ │ └── middlewares/
│ │ │ │ ├── indexHtml.ts
│ │ │ │ ├── static.ts
│ │ │ │ └── transform.ts
│ │ │ ├── server.ts
│ │ │ ├── utils.ts
│ │ │ └── ws.ts
│ │ ├── tsconfig.json
│ │ └── tsup.config.ts
│ ├── ranui/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── LICENSE
│ │ ├── README.zh-CN.md
│ │ ├── assets/
│ │ │ ├── image/
│ │ │ │ └── failImage.ts
│ │ │ └── js/
│ │ │ ├── hls.js
│ │ │ └── katex/
│ │ │ ├── katex-es-core.js
│ │ │ └── katex-es.js
│ │ ├── babel.config.cjs
│ │ ├── base.less
│ │ ├── bin/
│ │ │ ├── build.sh
│ │ │ └── test.sh
│ │ ├── build/
│ │ │ ├── config.es.ts
│ │ │ ├── config.sha.ts
│ │ │ ├── config.ts
│ │ │ └── config.umd.ts
│ │ ├── components/
│ │ │ ├── button/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── checkbox/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── colorpicker/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── dropdown/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── form/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── icon/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── image/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── input/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── loading/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── math/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── message/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── modal/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── player/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── popover/
│ │ │ │ ├── content/
│ │ │ │ │ ├── index.less
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── progress/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── radar/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── scratch/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── select/
│ │ │ │ ├── dropdown-item/
│ │ │ │ │ ├── index.less
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.less
│ │ │ │ ├── index.ts
│ │ │ │ └── option/
│ │ │ │ └── index.ts
│ │ │ ├── skeleton/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── tab/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ └── tabpane/
│ │ │ ├── index.less
│ │ │ └── index.ts
│ │ ├── demo/
│ │ │ └── react.tsx
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── playwright.config.ts
│ │ ├── plugins/
│ │ │ ├── auto-import-file.ts
│ │ │ ├── load-style.ts
│ │ │ └── load-svg.ts
│ │ ├── readme.md
│ │ ├── rollup.d.ts
│ │ ├── shadowless/
│ │ │ ├── icon/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ ├── input/
│ │ │ │ ├── index.less
│ │ │ │ └── index.ts
│ │ │ └── select/
│ │ │ ├── index.less
│ │ │ ├── index.ts
│ │ │ └── option/
│ │ │ └── index.ts
│ │ ├── shadowless.ts
│ │ ├── tests/
│ │ │ └── button.spec.ts
│ │ ├── theme/
│ │ │ ├── color.less
│ │ │ ├── font.less
│ │ │ └── index.less
│ │ ├── tsconfig.json
│ │ ├── typings.d.ts
│ │ ├── utils/
│ │ │ ├── color.ts
│ │ │ ├── image.ts
│ │ │ ├── index.ts
│ │ │ ├── math.ts
│ │ │ └── tween.ts
│ │ └── vite.config.ts
│ ├── ranuts/
│ │ ├── .npmignore
│ │ ├── LICENSE
│ │ ├── README.zh-CN.md
│ │ ├── assets/
│ │ │ └── wasm/
│ │ │ └── word/
│ │ │ ├── LICENSE_APACHE
│ │ │ ├── LICENSE_MIT
│ │ │ ├── wasmjieba-web.d.ts
│ │ │ ├── wasmjieba-web.js
│ │ │ ├── wasmjieba-web_bg.wasm
│ │ │ └── wasmjieba-web_bg.wasm.d.ts
│ │ ├── bin/
│ │ │ ├── build.sh
│ │ │ └── test.sh
│ │ ├── build/
│ │ │ ├── build.es.ts
│ │ │ ├── build.umd.ml.ts
│ │ │ ├── build.umd.node.ts
│ │ │ ├── build.umd.ts
│ │ │ ├── build.umd.utils.ts
│ │ │ └── build.umd.wasm.ts
│ │ ├── docs/
│ │ │ ├── binaryTree/
│ │ │ │ └── index.md
│ │ │ ├── file/
│ │ │ │ └── index.md
│ │ │ ├── index.md
│ │ │ ├── sort/
│ │ │ │ ├── bubble/
│ │ │ │ │ └── index.md
│ │ │ │ ├── bucket/
│ │ │ │ │ └── index.md
│ │ │ │ ├── count/
│ │ │ │ │ └── index.md
│ │ │ │ ├── heap/
│ │ │ │ │ └── index.md
│ │ │ │ ├── index.md
│ │ │ │ ├── insert/
│ │ │ │ │ └── index.md
│ │ │ │ ├── merge/
│ │ │ │ │ └── index.md
│ │ │ │ ├── quick/
│ │ │ │ │ └── index.md
│ │ │ │ ├── radix/
│ │ │ │ │ └── index.md
│ │ │ │ └── select/
│ │ │ │ └── index.md
│ │ │ └── utils/
│ │ │ ├── compose.md
│ │ │ ├── index.md
│ │ │ └── task.md
│ │ ├── examples/
│ │ │ ├── clone-deep-example.ts
│ │ │ └── is-equal-example.ts
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── plugins/
│ │ │ └── vite-plugins-banner.ts
│ │ ├── readme.md
│ │ ├── rollup.d.ts
│ │ ├── src/
│ │ │ ├── arithmetic/
│ │ │ │ └── index.ts
│ │ │ ├── ml/
│ │ │ │ ├── index.ts
│ │ │ │ └── ocr.ts
│ │ │ ├── node/
│ │ │ │ ├── appendFile.ts
│ │ │ │ ├── body.ts
│ │ │ │ ├── color.ts
│ │ │ │ ├── command.ts
│ │ │ │ ├── ctx2req.ts
│ │ │ │ ├── fileInfo.ts
│ │ │ │ ├── fs.ts
│ │ │ │ ├── get.ts
│ │ │ │ ├── getIPAdress.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── isColorSupported.ts
│ │ │ │ ├── paresUrl.ts
│ │ │ │ ├── readDir.ts
│ │ │ │ ├── readFile.ts
│ │ │ │ ├── router.ts
│ │ │ │ ├── send.ts
│ │ │ │ ├── server.ts
│ │ │ │ ├── startTask.ts
│ │ │ │ ├── stream.ts
│ │ │ │ ├── taskEnd.ts
│ │ │ │ ├── traverse.ts
│ │ │ │ ├── watchFile.ts
│ │ │ │ ├── websocket.ts
│ │ │ │ ├── writeFile.ts
│ │ │ │ └── ws.ts
│ │ │ ├── optimize/
│ │ │ │ ├── index.ts
│ │ │ │ └── promise.ts
│ │ │ ├── ran/
│ │ │ │ ├── build-react.md
│ │ │ │ ├── commit.ts
│ │ │ │ ├── dom.ts
│ │ │ │ ├── hooks.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── min.ts
│ │ │ │ ├── reconcile.ts
│ │ │ │ └── schedule.ts
│ │ │ ├── sort/
│ │ │ │ ├── bubble.ts
│ │ │ │ ├── bucket.ts
│ │ │ │ ├── count.ts
│ │ │ │ ├── heap.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── insert.ts
│ │ │ │ ├── merge.ts
│ │ │ │ ├── quick.ts
│ │ │ │ ├── radix.ts
│ │ │ │ ├── randomArray.ts
│ │ │ │ ├── select.ts
│ │ │ │ └── shell.ts
│ │ │ ├── utils/
│ │ │ │ ├── audioRecorder.ts
│ │ │ │ ├── behavior.ts
│ │ │ │ ├── bom.ts
│ │ │ │ ├── color.ts
│ │ │ │ ├── compose.ts
│ │ │ │ ├── console.ts
│ │ │ │ ├── debounce.ts
│ │ │ │ ├── device.ts
│ │ │ │ ├── dom.ts
│ │ │ │ ├── error.ts
│ │ │ │ ├── func.ts
│ │ │ │ ├── img.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── memoize.ts
│ │ │ │ ├── mimeType.ts
│ │ │ │ ├── monitor.ts
│ │ │ │ ├── network.ts
│ │ │ │ ├── noop.ts
│ │ │ │ ├── number.ts
│ │ │ │ ├── obj.ts
│ │ │ │ ├── performance.ts
│ │ │ │ ├── queue.ts
│ │ │ │ ├── report.ts
│ │ │ │ ├── request.ts
│ │ │ │ ├── script.ts
│ │ │ │ ├── signal.ts
│ │ │ │ ├── storage.ts
│ │ │ │ ├── str.ts
│ │ │ │ ├── subscribe.ts
│ │ │ │ ├── throttle.ts
│ │ │ │ ├── time.ts
│ │ │ │ ├── totp/
│ │ │ │ │ ├── sha/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── common.ts
│ │ │ │ │ │ ├── converters.ts
│ │ │ │ │ │ ├── custom_types.ts
│ │ │ │ │ │ ├── license_header.es3.txt
│ │ │ │ │ │ ├── license_header.es6.txt
│ │ │ │ │ │ ├── primitives_32.ts
│ │ │ │ │ │ ├── primitives_64.ts
│ │ │ │ │ │ ├── sha.ts
│ │ │ │ │ │ ├── sha1.ts
│ │ │ │ │ │ ├── sha256.ts
│ │ │ │ │ │ ├── sha3.ts
│ │ │ │ │ │ └── sha512.ts
│ │ │ │ │ └── totp.ts
│ │ │ │ └── visual/
│ │ │ │ ├── application.ts
│ │ │ │ ├── demo/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── nodeHierarchy.html
│ │ │ │ │ └── sankey.ts
│ │ │ │ ├── enums.ts
│ │ │ │ ├── event/
│ │ │ │ │ ├── boundary.ts
│ │ │ │ │ ├── event.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── graphics/
│ │ │ │ │ ├── graphics.ts
│ │ │ │ │ ├── graphicsData.ts
│ │ │ │ │ ├── graphicsGeometry.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── math/
│ │ │ │ │ ├── bezier.ts
│ │ │ │ │ ├── enums.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── matrix.ts
│ │ │ │ │ └── transform.ts
│ │ │ │ ├── render/
│ │ │ │ │ ├── batchRenderer.ts
│ │ │ │ │ ├── canvasRenderer.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── render.ts
│ │ │ │ │ ├── utils/
│ │ │ │ │ │ ├── batch/
│ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ ├── float.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── verticy.ts
│ │ │ │ │ │ ├── webgl/
│ │ │ │ │ │ │ ├── batchPool.ts
│ │ │ │ │ │ │ ├── initShader.ts
│ │ │ │ │ │ │ └── shaders.ts
│ │ │ │ │ │ └── webgpu/
│ │ │ │ │ │ └── shaders.ts
│ │ │ │ │ ├── webGPURenderer.ts
│ │ │ │ │ └── webGlRenderer.ts
│ │ │ │ ├── shape/
│ │ │ │ │ ├── circle.ts
│ │ │ │ │ ├── ellipse.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── polygon.ts
│ │ │ │ │ ├── rectangle.ts
│ │ │ │ │ ├── roundedRectangle.ts
│ │ │ │ │ └── shape.ts
│ │ │ │ ├── style/
│ │ │ │ │ ├── fill.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── line.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── vertex/
│ │ │ │ ├── container.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── point.ts
│ │ │ │ └── vertex.ts
│ │ │ ├── vnode/
│ │ │ │ ├── chainDom.ts
│ │ │ │ ├── h.ts
│ │ │ │ ├── hooks.ts
│ │ │ │ ├── htmlDomApi.ts
│ │ │ │ ├── init.ts
│ │ │ │ ├── is.ts
│ │ │ │ ├── modules/
│ │ │ │ │ ├── attributes.ts
│ │ │ │ │ ├── class.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── listeners.ts
│ │ │ │ │ ├── props.ts
│ │ │ │ │ └── style.ts
│ │ │ │ └── vnode.ts
│ │ │ ├── wasm/
│ │ │ │ ├── index.ts
│ │ │ │ └── word.ts
│ │ │ └── wicket/
│ │ │ ├── bridge.ts
│ │ │ └── index.ts
│ │ ├── test/
│ │ │ ├── arithmetic.test.ts
│ │ │ ├── cloneDeep.test.ts
│ │ │ ├── encodeUrl.test.ts
│ │ │ ├── escapeHtml.test.ts
│ │ │ ├── is-equal.test.ts
│ │ │ ├── mimeType.test.ts
│ │ │ ├── server.test.ts
│ │ │ ├── sort.test.ts
│ │ │ ├── status.test.ts
│ │ │ ├── totp.test.ts
│ │ │ ├── utils/
│ │ │ │ ├── compose.test.ts
│ │ │ │ ├── mergeObj.test.ts
│ │ │ │ └── ocr.test.ts
│ │ │ ├── visual/
│ │ │ │ └── math.test.ts
│ │ │ ├── vnode/
│ │ │ │ ├── index.html
│ │ │ │ ├── index.ts
│ │ │ │ ├── server.ts
│ │ │ │ └── vnode.ts
│ │ │ ├── websocket.test.ts
│ │ │ └── writeFile.test.ts
│ │ ├── tsconfig.json
│ │ ├── typings.d.ts
│ │ └── vite.config.ts
│ ├── rust/
│ │ ├── index.md
│ │ └── start.md
│ ├── solidity/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── bin/
│ │ │ ├── compile.sh
│ │ │ ├── eth.sh
│ │ │ └── test.sh
│ │ ├── blockchain-data-structure.md
│ │ ├── consensus.md
│ │ ├── contracts/
│ │ │ └── Lock.sol
│ │ ├── encryption.md
│ │ ├── eth/
│ │ │ ├── doc/
│ │ │ │ ├── Foundry.md
│ │ │ │ ├── ethers.md
│ │ │ │ ├── introduce.md
│ │ │ │ └── pragma.md
│ │ │ └── project/
│ │ │ ├── crowdFund/
│ │ │ │ ├── contracts/
│ │ │ │ │ ├── CrowdFund.sol
│ │ │ │ │ └── artifacts/
│ │ │ │ │ ├── CrowdFund.json
│ │ │ │ │ ├── CrowdFund_metadata.json
│ │ │ │ │ ├── IERC20.json
│ │ │ │ │ ├── IERC20_metadata.json
│ │ │ │ │ └── build-info/
│ │ │ │ │ └── 51a87644e167c2c0acbed68604ab9364.json
│ │ │ │ └── readme.md
│ │ │ ├── cryptoKitty/
│ │ │ │ ├── contracts/
│ │ │ │ │ └── cryptoKitty.sol
│ │ │ │ └── readme.md
│ │ │ ├── deploy.md
│ │ │ └── fungibleToken/
│ │ │ ├── .states/
│ │ │ │ └── vm-shanghai/
│ │ │ │ └── state.json
│ │ │ ├── contracts/
│ │ │ │ ├── FungibleToken.sol
│ │ │ │ └── artifacts/
│ │ │ │ ├── FungibleToken.json
│ │ │ │ ├── FungibleToken_metadata.json
│ │ │ │ └── build-info/
│ │ │ │ └── 161b7ad96fda298680715448c4a2ef7f.json
│ │ │ └── readme.md
│ │ ├── hardhat.config.ts
│ │ ├── ignition/
│ │ │ └── modules/
│ │ │ └── Lock.ts
│ │ ├── index.md
│ │ ├── package.json
│ │ ├── pos.md
│ │ ├── pow.md
│ │ ├── program.md
│ │ ├── remix.md
│ │ ├── signature.md
│ │ ├── start.md
│ │ ├── test/
│ │ │ └── Lock.ts
│ │ ├── tsconfig.json
│ │ ├── wallet.md
│ │ └── web3-wallet.md
│ └── visual/
│ ├── bin/
│ │ └── build.sh
│ ├── build/
│ │ ├── build.es.ts
│ │ └── build.umd.ts
│ ├── components/
│ │ ├── bar/
│ │ │ └── index.ts
│ │ ├── line/
│ │ │ └── index.ts
│ │ ├── pie/
│ │ │ └── index.ts
│ │ └── sankey/
│ │ ├── data.ts
│ │ └── index.ts
│ ├── docs/
│ │ ├── demo.glsl
│ │ ├── fourColor.glsl
│ │ ├── glsl.md
│ │ ├── index.md
│ │ ├── random.md
│ │ ├── red.glsl
│ │ ├── start.md
│ │ ├── texture.md
│ │ ├── ux.md
│ │ └── yellow.glsl
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src/
│ │ ├── application.ts
│ │ ├── enums.ts
│ │ ├── event/
│ │ │ ├── boundry.ts
│ │ │ ├── enums.ts
│ │ │ ├── event.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── graphics/
│ │ │ ├── geometry.ts
│ │ │ ├── graphics.ts
│ │ │ ├── graphicsData.ts
│ │ │ └── index.ts
│ │ ├── render/
│ │ │ ├── canvasRender.ts
│ │ │ ├── index.ts
│ │ │ ├── render.ts
│ │ │ ├── webGLRender.ts
│ │ │ └── webGPURender.ts
│ │ ├── shape/
│ │ │ ├── bezier.ts
│ │ │ ├── circle.ts
│ │ │ ├── ellipse.ts
│ │ │ ├── enums.ts
│ │ │ ├── fill.ts
│ │ │ ├── index.ts
│ │ │ ├── line.ts
│ │ │ ├── polygon.ts
│ │ │ ├── rectangle.ts
│ │ │ ├── roundedRectangle.ts
│ │ │ ├── shape.ts
│ │ │ └── types.ts
│ │ ├── transform/
│ │ │ ├── enums.ts
│ │ │ ├── index.ts
│ │ │ ├── matrix.ts
│ │ │ ├── transform.ts
│ │ │ └── types.ts
│ │ ├── types.ts
│ │ └── vertex/
│ │ ├── container.ts
│ │ ├── index.ts
│ │ ├── point.ts
│ │ └── vertex.ts
│ ├── tsconfig.json
│ ├── typings.d.ts
│ └── vite.config.ts
├── pnpm-workspace.yaml
├── readme-zh_CN.md
└── readme.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
day: sunday
time: "01:00"
labels:
- scope:dependency
target-branch: "main"
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
pull_request:
branches: [main]
paths:
- "packages/**"
push:
branches: [main]
paths:
- "packages/**"
permissions:
contents: read
pull-requests: read
jobs:
lint:
if: github.repository == 'chaxus/ran'
timeout-minutes: 30
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node_version: [20, 22]
include:
# Active LTS + other OS
- os: macos-latest
node_version: 22
- os: windows-latest
node_version: 22
fail-fast: false
name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}"
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- uses: pnpm/action-setup@v6
name: Install pnpm
id: pnpm-install
with:
version: 7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: prepare
run: pnpm pre
- name: Install deps
run: pnpm install
- name: build
run: pnpm run build
- name: format
run: pnpm run format
- name: Lint
run: pnpm run lint
- name: Test
run: pnpm run test
================================================
FILE: .github/workflows/pages-build-site.yml
================================================
name: pages-build-site
on:
push:
branches:
- main
permissions:
contents: write
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- uses: pnpm/action-setup@v6
name: Install pnpm
id: pnpm-install
with:
version: 7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v5
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- name: Build ranuts
run: pnpm -F ranuts build
- name: Build ranui
run: pnpm -F ranui build
- name: Build docs
run: pnpm -F docs build
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.RAN_ACTIONS_TOKEN }}
exclude_assets: ""
publish_dir: packages/docs/.vitepress/dist
================================================
FILE: .github/workflows/semantic-pull-request.yml
================================================
name: Semantic Pull Request
on:
pull_request_target:
types:
- opened
- edited
- synchronize
permissions:
pull-requests: write
contents: read
jobs:
main:
if: github.repository == 'chaxus/ran'
runs-on: ubuntu-latest
name: Semantic Pull Request
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.RAN_ACTIONS_TOKEN }}
================================================
FILE: .gitignore
================================================
# npm
node_modules
package-lock.json
npminstall-debug.log
# common
.temp
cache
# mac
.DS_Store
# eslint
.eslintcache
# vite
vite.config.ts.timestamp*
config.ts.timestamp*
dist
# ranui
/test-results/
/playwright-report/
/playwright/.cache/
# jscpd
report
# tesseract
*.traineddata
================================================
FILE: .jscpd.json
================================================
{
"threshold": 10,
"reporters": ["html", "console"],
"ignore": [
"**/__snapshots__/**",
"**.config.ts",
"**.md",
"**.html",
"tsconfig.json",
"node_modules",
"CMakeFiles",
"**.txt"
],
"absolute": true,
"gitignore": true
}
================================================
FILE: .prettierignore
================================================
dist/
LICENSE.md
pnpm-lock.yaml
pnpm-workspace.yaml
report
public
assets
================================================
FILE: .prettierrc.json
================================================
{
"semi": true,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 120,
"trailingComma": "all",
"overrides": [
{
"files": ["*.json5"],
"options": {
"singleQuote": false,
"quoteProps": "preserve"
}
},
{
"files": ["*.yml"],
"options": {
"singleQuote": false
}
}
]
}
================================================
FILE: .vscode/c_cpp_properties.json
================================================
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**",
// 需要设置环境变量 .conan2 的路径,一般是在当前用户目录下,比如 /Users/chaxus/.conan2
// conan install 会将依赖库安装到这个目录下
// 其中 echo $chaxus 可以查看环境变量 chaxus 的值
// export chaxus=/path/to/chaxus 可以设置环境变量 chaxus 的值
"${env:chaxus}/.conan2/**",
"/usr/local/include/**",
// 将 Emscripten 的头文件路径添加到 includePath 中
"/opt/homebrew/Cellar/emscripten/3.1.74/libexec/system/include/**",
"/opt/homebrew/include/**"
],
"defines": [],
"macFrameworkPath": ["/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}
================================================
FILE: .vscode/launch.json
================================================
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问:https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/packages/ranuts/test/write-file.spec.ts",
"outFiles": ["${workspaceFolder}/**/*.js"]
}
]
}
================================================
FILE: .vscode/markdown.code-snippets
================================================
{
// Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"生成参考文献的角标": {
"scope": "markdown",
"prefix": "sup",
"body": ["[<sup>[$2]</sup>]($1)。"],
"description": "生成参考文献的角标",
},
"生成链接": {
"scope": "markdown",
"prefix": "[]",
"body": ["[$2]($1)。"],
"description": "生成链接",
},
"生成图片引用": {
"scope": "markdown",
"prefix": "[]",
"body": ["。"],
"description": "生成图片引用",
},
}
================================================
FILE: .vscode/ranui-components.code-snippets
================================================
{
// Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"print component": {
"scope": "javascript,typescript",
"prefix": "tfc",
"body": [
"function Component() {",
" const template = document.createElement('template');",
" const slot = document.createElement('slot');",
" const div = document.createElement('div');",
" div.setAttribute('class', 'class');",
" slot.setAttribute('name', 'name');",
" div.appendChild(slot);",
" template.appendChild(div);",
" class CustomElement extends HTMLElement {",
" static get observedAttributes() { return ['disabled'] }",
" _div: HTMLElement;",
" constructor() {",
" super();",
" this._div = div.cloneNode(true) as HTMLElement",
" const shadowRoot = this.attachShadow({ mode: 'closed' });",
" shadowRoot.appendChild(this._div);",
" }",
" connectedCallback() {",
"",
" }",
" disconnectCallback() {",
"",
" }",
" attributeChangedCallback (name:string, oldValue:string, newValue:string) {",
"",
" }",
" }",
"window.customElements.define('r-$1', CustomElement)",
"}",
"export default Component()",
// $通过tab切换
],
"description": "ranui component template",
},
"Print sort function": {
"scope": "javascript,typescript",
"prefix": "sf",
"body": ["const $1 = ($2) => {", "", "}", "", "export default $1"],
"description": "Log output to console",
},
"Print to return": {
"scope": "javascript,typescript",
"prefix": "rt",
"body": ["return"],
"description": "Log output to console",
},
"Print to for": {
"scope": "javascript,typescript",
"prefix": "for",
"body": ["for(let i = 0; i < $1; i++) {", "", "}"],
"description": "Log output to console",
},
}
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"abilitys",
"Alloc",
"allowclear",
"ANALYSE",
"analysed",
"binarystring",
"bottombar",
"brotli",
"ccall",
"chaxus",
"classname",
"colorpicker",
"componentization",
"cond",
"cout",
"Crossentropy",
"cstring",
"cwrap",
"dataavailable",
"denormalise",
"Deoptimization",
"DOMAPI",
"dropdownclass",
"embin",
"Embind",
"emcc",
"Emscripten",
"endl",
"esbuild",
"exceljs",
"GLSL",
"HEAPF",
"HEAPU",
"IIFE",
"iostream",
"katex",
"KEEPALIVE",
"keyof",
"lembind",
"lerp",
"localstorage",
"malloc",
"maxlength",
"maxrows",
"memset",
"Metiral",
"minrows",
"normalise",
"normalised",
"nullptr",
"nums",
"originjs",
"Ovride",
"pacman",
"pagefind",
"picocolors",
"playsinline",
"preinstall",
"progressbar",
"pthread",
"PTHREADS",
"RAII",
"ranite",
"rankey",
"ranloadedmetadata",
"ranlog",
"ranml",
"ranpack",
"ranui",
"ranuireact",
"ranuts",
"Reactified",
"Sankey",
"scatterplot",
"showcount",
"simplefy",
"skipsvgo",
"slotchange",
"sqft",
"struct",
"tabpane",
"tailwindcss",
"tesseract",
"tfjs",
"tfvis",
"TOTP",
"treeshake",
"Treeshaking",
"TTFB",
"typeof",
"vitepress",
"vnode",
"vnodes",
"wasmjieba",
"xlabels"
],
"liveServer.settings.port": 5556,
"files.associations": {
"*.cjson": "jsonc",
"*.wxss": "css",
"*.wxs": "javascript",
"vips.h": "c",
"stdio.h": "c",
"gmodule.h": "c",
"glib.h": "c",
"image_processing.h": "c"
},
"cmake.ignoreCMakeListsMissing": true
}
================================================
FILE: .vscode/ts.json.code-snippets
================================================
{
// Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Print to console": {
"scope": "javascript,typescript",
"prefix": "clg",
"body": ["console.log('$1');"],
"description": "Log output to console",
},
"web components class": {
"scope": "typescript",
"prefix": "wc",
"body": [
"import { isDisabled } from '@/utils/index';",
"",
"class Option extends HTMLElement {",
" _option: HTMLDivElement;",
" _optionContent: HTMLDivElement;",
" _shadowDom: ShadowRoot;",
" _slot: HTMLSlotElement;",
" static get observedAttributes() {",
" return ['disabled', 'sheet', 'value'];",
" }",
" constructor() {",
" super();",
" this._slot = document.createElement('slot');",
" this._option = document.createElement('div');",
" this._optionContent = document.createElement('div');",
" this._optionContent.appendChild(this._slot);",
" this._option.appendChild(this._optionContent);",
" const shadowRoot = this.attachShadow({ mode: 'closed' });",
" this._shadowDom = shadowRoot;",
" shadowRoot.appendChild(this._option);",
" }",
" get sheet() {",
" return this.getAttribute('sheet');",
" }",
" set sheet(value) {",
" this.setAttribute('sheet', value || '');",
" }",
" get disabled() {",
" return isDisabled(this);",
" }",
" set disabled(value: boolean | string | undefined | null) {",
" if (!value || value === 'false') {",
" this.removeAttribute('disabled');",
" } else {",
" this.setAttribute('disabled', '');",
" }",
" }",
" handlerExternalCss() {",
" if (this.sheet) {",
" try {",
" const sheet = new CSSStyleSheet();",
" sheet.insertRule(this.sheet);",
" this._shadowDom.adoptedStyleSheets = [sheet];",
" } catch (error) {",
" console.error(",
" `Failed to parse the rule in CSSStyleSheet: ${this.sheet}`",
" );",
" }",
" }",
" }",
" connectedCallback() {}",
" disconnectCallback() {}",
" attributeChangedCallback(name: string, oldValue: string, newValue: string) {",
" if (name === 'disabled' && this._option) {",
" if (!newValue || newValue === 'false') {",
" this._option.setAttribute('disabled', '');",
" } else {",
" this._option.removeAttribute('disabled');",
" }",
" }",
" if (name === 'sheet' && this._shadowDom && oldValue !== newValue)",
" this.handlerExternalCss();",
" }",
"}",
],
"description": "generate web components ts code",
},
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2023 chaxus
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
================================================
FILE: bin/build.sh
================================================
npx pnpm -F ranuts build && pnpm -F ranui build && pnpm -F docs build
================================================
FILE: bin/clean.sh
================================================
rm -rf $(pnpm store path)
rm -rf node_modules
rm -rf packages/ranui/node_modules/
rm -rf packages/ranuts/node_modules/
rm -rf packages/docs/node_modules/
rm -rf packages/ranite/node_modules/
rm -rf packages/ml/node_modules/
npm cache clean --force
rm -rf pnpm-lock.yaml
================================================
FILE: bin/install.sh
================================================
# 子package安装
pnpm i [package] -r --filter smarty-ui-vite
# 或者 直接在 ranui 目录下
pnpm i [package]
# 安装 workspace 中
pnpm i [package] -w
# 检查只能用pnpm安装,用于workspace
`"preinstall": "npx only-allow pnpm"`
# Monorepo
================================================
FILE: bin/lint.sh
================================================
bin=./node_modules/.bin
$bin/prettier --check --cache .
$bin/eslint --cache . && $bin/prettier --check --cache .
# before lint, make sure all packages are built
# pnpm build
pnpm -F docs tsc
pnpm -F image-process tsc
pnpm -F ml tsc
pnpm -F ranui tsc
pnpm -F ranuts tsc
pnpm -F solidity tsc
# pnpm -F read tsc
# $bin/tsc --noEmit
# npm run lint:es && npm run lint:prettier
================================================
FILE: bin/nvm.sh
================================================
nvm alias default node
nvm use node
================================================
FILE: bin/preinstall.sh
================================================
# @tensorflow/tfjs-node in github actions
python3 --version
node --version
================================================
FILE: bin/test.sh
================================================
pnpm -F docs tsc
pnpm -F image-process tsc
pnpm -F ml tsc
pnpm -F ranui tsc
pnpm -F ranuts tsc
pnpm -F solidity tsc
pnpm -F ranuts test
pnpm -F ranuts build
# pnpm -F ranui test
================================================
FILE: eslint.config.js
================================================
// @ts-check
import { builtinModules } from 'node:module';
import eslint from '@eslint/js';
import pluginN from 'eslint-plugin-n';
import pluginImportX from 'eslint-plugin-import-x';
import pluginRegExp from 'eslint-plugin-regexp';
import tseslint from 'typescript-eslint';
import globals from 'globals';
// Some rules work better with typechecking enabled, but as enabling it is slow,
// we only do so when linting in IDEs for now. If you want to lint with typechecking
// explicitly, set this to `true` manually.
const shouldTypeCheck = typeof process.env.VSCODE_PID === 'string';
export default tseslint.config(
{
ignores: [
'packages/solidity/**',
'**/dist/**',
'**/report/**',
'**/assets/**',
'**/temp/**',
'**/public/**',
'**/cache/**',
'**/*.snap',
],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
pluginRegExp.configs['flat/recommended'],
{
name: 'main',
languageOptions: {
parser: tseslint.parser,
parserOptions: {
sourceType: 'module',
ecmaVersion: 2022,
project: shouldTypeCheck ? ['./packages/*/tsconfig.json', './packages/vite/src/*/tsconfig.json'] : undefined,
},
globals: {
...globals.es2021,
...globals.node,
},
},
plugins: {
n: pluginN,
'import-x': pluginImportX,
},
rules: {
'n/no-exports-assign': 'error',
'n/no-unpublished-bin': 'error',
'n/no-unsupported-features/es-builtins': 'error',
'n/no-unsupported-features/node-builtins': 'error',
'n/process-exit-as-throw': 'error',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-namespace': 'off',
'n/hashbang': 'error',
eqeqeq: 'off',
'no-debugger': ['error'],
'no-empty': ['warn', { allowEmptyCatch: true }],
'no-process-exit': 'off',
'prefer-const': [
'warn',
{
destructuring: 'all',
},
],
'n/no-missing-require': [
'error',
{
// for try-catching yarn pnp
allowModules: ['pnpapi', 'vite'],
tryExtensions: ['.ts', '.js', '.jsx', '.tsx', '.d.ts'],
},
],
'n/no-extraneous-import': [
'error',
{
allowModules: ['vite', 'less', 'sass', 'sass-embedded', 'lightningcss', 'vitest', 'unbuild'],
},
],
'n/no-extraneous-require': [
'error',
{
allowModules: ['vite'],
},
],
'@typescript-eslint/ban-ts-comment': 'error',
'@typescript-eslint/no-unsafe-function-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': ['error', { allowArgumentsExplicitlyTypedAsAny: true }],
'@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-extra-semi': 'off',
'@typescript-eslint/no-extra-semi': 'off', // conflicts with prettier
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'@typescript-eslint/no-require-imports': 'off',
'@typescript-eslint/consistent-type-imports': [
'error',
{ prefer: 'type-imports', disallowTypeAnnotations: false },
],
// disable rules set in @typescript-eslint/stylistic which conflict with current code
// we should discuss if we want to enable these as they encourage consistent code
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/prefer-for-of': 'off',
'@typescript-eslint/prefer-function-type': 'off',
'import-x/no-nodejs-modules': ['error', { allow: builtinModules.map((mod) => `node:${mod}`) }],
'import-x/no-duplicates': 'error',
'import-x/order': 'error',
'sort-imports': [
'error',
{
ignoreCase: false,
ignoreDeclarationSort: true,
ignoreMemberSort: false,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
allowSeparatedGroups: false,
},
],
'regexp/prefer-regexp-exec': 'error',
'regexp/prefer-regexp-test': 'error',
// in some cases using explicit letter-casing is more performant than the `i` flag
'regexp/use-ignore-case': 'off',
},
},
{
name: 'disables/playground',
files: ['playground/**/*.?([cm])[jt]s?(x)', 'docs/**/*.?([cm])[jt]s?(x)'],
rules: {
'n/no-extraneous-import': 'off',
'n/no-extraneous-require': 'off',
'n/no-missing-import': 'off',
'n/no-missing-require': 'off',
'n/no-unsupported-features/es-builtins': 'off',
'n/no-unsupported-features/node-builtins': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'no-undef': 'off',
'no-empty': 'off',
'no-constant-condition': 'off',
'@typescript-eslint/no-empty-function': 'off',
},
},
{
name: 'disables/playground/tsconfig-json',
files: [
'playground/tsconfig-json/**/*.?([cm])[jt]s?(x)',
'playground/tsconfig-json-load-error/**/*.?([cm])[jt]s?(x)',
],
ignores: ['**/__tests__/**'],
rules: {
'@typescript-eslint/ban-ts-comment': 'off',
},
},
{
name: 'disables/js',
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
{
name: 'disables/dts',
files: ['**/*.d.ts'],
rules: {
'@typescript-eslint/consistent-indexed-object-style': 'off',
'@typescript-eslint/triple-slash-reference': 'off',
},
},
{
name: 'disables/test',
files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'],
rules: {
'no-console': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
},
},
{
name: 'disables/typechecking',
files: [
'**/*.js',
'**/*.mjs',
'**/*.cjs',
'**/*.d.ts',
'**/*.d.cts',
'**/__tests__/**',
'docs/**',
'playground/**',
'scripts/**',
'vitest.config.ts',
],
languageOptions: {
parserOptions: {
project: false,
},
},
},
);
================================================
FILE: index.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sankey Diagram with Canvas</title>
<style>
canvas {
width: 800px;
height: 400px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="sankeyCanvas"></canvas>
<script>
const canvas = document.getElementById('sankeyCanvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
canvas.width = 800 * dpr;
canvas.height = 400 * dpr;
ctx.scale(dpr, dpr);
const sourceData = {
title: '2020 一季报',
nodes: [
{
label: 'Iphone',
key: 'Iphone',
value: '1.77 亿',
rate: 3,
},
{
label: 'Services',
key: 'services',
value: '1.39 亿',
rate: 3,
},
{
label: 'MAC',
key: 'MAC',
value: '1.21 亿',
rate: 2,
},
{
label: 'Ipad',
key: 'Ipad',
value: '1.21 亿',
rate: 1,
},
{
label: 'Other',
key: 'Other',
value: '1.21 亿',
rate: 1,
},
{
label: '营业收入',
key: '营业收入',
value: '1.77 亿',
rate: 10,
},
{
label: '营业成本',
key: '营业成本',
value: '1.39 亿',
rate: 3,
},
{
label: '毛利',
key: '毛利',
value: '1.21 亿',
rate: 7,
},
],
// 链接可能是一对多的关系,所以需要单独定义
links: [
{
source: 'Iphone',
target: '营业收入',
},
{
source: 'Services',
target: '营业收入',
},
{
source: 'MAC',
target: '营业收入',
},
{
source: 'Ipad',
target: '营业收入',
},
{
source: 'Other',
target: '营业收入',
},
{
source: '营业收入',
target: '营业成本',
},
{
source: '营业成本',
target: '毛利',
},
],
};
// 绘制长方形节点
const createRctAngularNode = (params) => {
const { x, y, width, height, color } = params;
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
};
// 绘制文本
const createText = (params) => {
const { x, y, text, color, textAlign, font } = params;
ctx.fillStyle = color;
textAlign && (ctx.textAlign = textAlign);
font && (ctx.font = font);
ctx.fillText(text, x, y);
};
// y 从 30 开始
// x 从 10 开始
// 第一个节点
createText({
x: 10,
y: 30,
text: '+3%',
color: '#AFB3B6',
});
createText({
x: 36,
y: 30,
text: 'Iphone',
color: '#000000',
});
createText({
x: 36,
y: 44,
text: '1.77 亿',
font: '500 14px',
color: '#37A0FF',
});
createRctAngularNode({
x: 70,
y: 26,
width: 8,
height: 18,
color: '#37A0FF',
});
// 第二个节点
createText({
x: 1,
y: 70,
text: '+3%',
color: '#AFB3B6',
});
createText({
x: 26,
y: 70,
text: 'Services',
color: '#000000',
});
createText({
x: 36,
y: 84,
text: '1.39 亿',
font: '500 14px',
color: '#37A0FF',
});
createRctAngularNode({
x: 70,
y: 64,
width: 8,
height: 18,
color: '#37A0FF',
});
// 第三个节点
createText({
x: 16,
y: 110,
text: '+3%',
color: '#AFB3B6',
});
createText({
x: 40,
y: 110,
text: 'MAC',
color: '#000000',
});
createText({
x: 36,
y: 124,
text: '1.21 亿',
font: '500 14px',
color: '#37A0FF',
});
createRctAngularNode({
x: 70,
y: 104,
width: 8,
height: 18,
color: '#37A0FF',
});
// 第四个节点
createText({
x: 16,
y: 150,
text: '+3%',
color: '#AFB3B6',
});
createText({
x: 40,
y: 150,
text: 'Ipad',
color: '#000000',
});
createText({
x: 36,
y: 164,
text: '1.21 亿',
font: '500 14px',
color: '#37A0FF',
});
createRctAngularNode({
x: 70,
y: 144,
width: 8,
height: 18,
color: '#37A0FF',
});
// 第五个节点
createText({
x: 16,
y: 190,
text: '+3%',
color: '#AFB3B6',
});
createText({
x: 40,
y: 190,
text: 'Other',
color: '#000000',
});
createText({
x: 36,
y: 204,
text: '1.21 亿',
font: '500 14px',
color: '#37A0FF',
});
createRctAngularNode({
x: 70,
y: 184,
width: 8,
height: 18,
color: '#37A0FF',
});
// 链接节点
createText({
x: 206,
y: 74,
text: '营业收入',
font: '500 14px',
color: '#000000',
});
createText({
x: 250,
y: 74,
text: '+3%',
font: '500 14px',
color: '#AFB3B6',
});
createText({
x: 224,
y: 90,
text: '1.77 亿',
font: '500 16px',
color: '#37A0FF',
});
createRctAngularNode({
x: 224,
y: 96,
width: 16,
height: 42,
color: '#37A0FF',
});
// 连线
ctx.beginPath();
// 从第一个节点的长方形 x,y 开始
ctx.strokeStyle = '#37A0FF'; // 线条颜色
ctx.lineWidth = 2; // 线条宽度
// const startX = 78;
// const startY = 26;
// const endX = 224;
// const endY = 96;
// ctx.moveTo(startX, startY);
// // 第一段三次贝塞尔曲线
// ctx.bezierCurveTo(208, 96, 350, 200, (startX + endX) / 2, (startY + endY) / 2);
// // 第二段三次贝塞尔曲线
// ctx.bezierCurveTo(140, 70, 160, 90, endX, endY);
// ctx.stroke();
// 起点和终点坐标
var startX = 78; // 50
var startY = 26; // 150
var endX = 224; // 450
var endY = 96; // 150
// 控制点坐标
var controlX1 = 190; // 150
var controlY1 = 30; // 50
var controlX2 = 98; // 350
var controlY2 = 110; // 250
// 绘制 S 形曲线
ctx.beginPath();
ctx.moveTo(startX, startY);
// 绘制上半部分曲线
ctx.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);
ctx.lineTo(endX, endY + 12);
// 绘制下半部分曲线
ctx.bezierCurveTo(100, 120, 178, 50, startX, startY + 18);
ctx.lineTo(startX, startY);
// 绘制封闭区域
ctx.closePath();
ctx.fillStyle = '#37A0FF88'; // 填充颜色
// 填充颜色
ctx.fill();
ctx.stroke();
</script>
</body>
</html>
================================================
FILE: package.json
================================================
{
"name": "@ran/monorepo",
"version": "1.0.0",
"description": "Monorepo",
"type": "module",
"engines": {
"node": ">=23.10.0"
},
"scripts": {
"pre": "sh ./bin/preinstall.sh",
"preinstall": "npx only-allow pnpm",
"clean": "sh ./bin/clean.sh",
"build": "sh ./bin/build.sh",
"test": "sh ./bin/test.sh",
"lint": "sh ./bin/lint.sh",
"lint:es": "eslint --cache .",
"lint:fix": "eslint --cache --fix",
"lint:prettier": "prettier --check --cache .",
"format": "prettier --write --cache .",
"cpd": "jscpd ./packages"
},
"homepage": "https://chaxus.github.io/ran/",
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"@eslint/js": "^9.39.1",
"@types/node": "^24.10.1",
"@typescript-eslint/parser": "^8.46.4",
"eslint": "^9.39.1",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-n": "^17.23.1",
"eslint-plugin-regexp": "^2.10.0",
"jscpd": "^4.0.5",
"prettier": "^3.6.2",
"terser": "^5.44.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.4",
"vite": "^6.4.1",
"vite-plugin-dts": "^4.5.4",
"vitest": "^4.0.9",
"vue": "^3.5.24",
"vue-tsc": "^3.1.3"
},
"dependencies": {
"globals": "^16.5.0",
"ranui": "0.1.10-alpha-27"
},
"pnpm": {
"ignoredBuiltDependencies": [
"fsevents",
"keccak",
"secp256k1"
]
}
}
================================================
FILE: packages/cpro/package.json
================================================
{
"name": "cpro",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
================================================
FILE: packages/cpro/readme.md
================================================
# C++
如果要为 macOS 进行 C++ 开发,建议安装 Clang 编译器。只需在“终端”窗口中运行以下命令即可安装命令行开发人员工具:
```sh
xcode-select --install
```
然后,要验证已安装 clang,请在“终端”窗口中运行以下命令。你应该会看到一条消息,其中包含有关所使用的 Clang 版本的信息。
```sh
clang --version
```
```c++
#include<iostream>
using namespace std;
int main(){
cout << "Hello~" << endl;
return 0;
}
```
命令行执行:
```sh
clang++ main.cpp
# if meet some error like this: error: non-aggregate type 'vector<int>' cannot be initialized with an initializer list
# g++ -std=c++11
./a.out
```
# WebAssembly
官网:<https://emscripten.org/>
Mac 安装 `Emscripten`
```sh
brew install emscripten
```
安装完成后测试是否存在
```sh
emcc -v
```
编译 `C++` 代码
```sh
emcc main.cpp
```
命令成功执行后,你会发现 `main.cpp` 同级目录下会生成两个文件:`a.out.wasm` 和 `a.out.js`。其中,`a.out.wasm` 就是我们想要的 `Wasm` 模块。
```sh
node a.out.js
```
`Node.js` 是支持 `Wasm` 模块的(自 `Node.js 8` 开始)。
如果你希望到浏览器环境下测试文件,那么你可以在命令行下使用如下指令编译我们的 `C++` 代码:
```sh
emcc main.cpp -o main.html
```
命令成功执行后,`main.cpp` 同级目录下会再多出三个文件:`main.wasm`、`main.js` 和 `main.html`。你可以用`Live Server`打开 `main.html` 文件,就能看到结果了:

## 调试 WebAssembly
我们可以在编译 `WebAssembly` 的时候加入 `-v` 参数来让 `Emscripten` 为我们输出更多编译信息,以辅助我们发现 `C++` 代码中的问题。
如果你想在运行期调试 `WebAssembly` 的代码,那么你需要使用如下指令重新编译 `WebAssembly` 模块以让你的 `.wasm` 文件包含调试信息:
```sh
emcc -g main.cpp -o main.html
```
参数解释:
- `-g`: 编译 + 链接,同时保留调试信息。当编译为目标文件时,这与 Clang 和 gcc 中的相同,它将 DWARF 调试信息添加到目标文件中。
- `-o`: 链接可执行文件时,目标文件扩展名定义要生成的输出类型,默认是 `JavaScript`。如果指定是`html`,会生成一个`html`加`JavaScript`的可运行文件。
接着你需要为你的谷歌浏览器安装一个插件 [`C/C++ DevTools Support (DWARF)`](https://chrome.google.com/webstore/detail/cc%20%20-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb) ,这是 `Chrome DevTools` 开发团队为开发者提供的专门用于调试 `WebAssembly` 的浏览器插件,注意安装过程中要保持良好的网络环境。

安装完成后,打开 `Chrome` 浏览器的调试工具 `DevTools`,点击设置按钮(⚙),打开调试工具的设置面板,勾选实验选项卡下的 `WebAssembly Debugging: Enable DWARF support` 选项。

接着退回到 `DevTools` 主面板,把你的源码路径添加到 `DevTools` 的文件系统中,然后在 `main.cpp` 中下一个断点,刷新 `main.html` 页面,你会发现刚刚下的断点已经命中了,而且调用堆栈也会显示在 `DevTools` 右侧的面板中,如下图所示:

## C++ 与 JS 的交互
### ccall
如果需要调用一个在 C 语言自定义的函数,你可以使用 Emscripten 中的 ccall() 函数,以及 EMSCRIPTEN_KEEPALIVE 声明
> Emscripten 会消除未从编译代码中调用的函数的死代码。虽然这确实最大限度地减少了代码大小,但它可以删除您计划自己调用的函数(在已编译的代码之外)。比如通过 EMSCRIPTEN_KEEPALIVE 和 EXPORTED_FUNCTIONS 去指定需要导出的函数。EMSCRIPTEN_KEEPALIVE 的作用是告诉编译器和链接器保留符号并将其导出,就像将其添加到 EXPORTED_FUNCTIONS 中一样。
默认情况下,Emscripten 生成的代码只会调用 main() 函数,其他的函数将被视为无用代码。在一个函数名之前添加 EMSCRIPTEN_KEEPALIVE 能够防止这样的事情发生。你需要导入 emscripten.h 库来使用 EMSCRIPTEN_KEEPALIVE。
EMSCRIPTEN_KEEPALIVE:
```c++
// EMSCRIPTEN_KEEPALIVE
void EMSCRIPTEN_KEEPALIVE my_function() { printf("I am being kept alive\n"); }
```
EXPORTED_FUNCTIONS:
```sh
# EXPORTED_FUNCTIONS
emcc -sEXPORTED_FUNCTIONS=_main,_my_func ...
```
> 如果您有 main() 函数,则\_main 应该位于导出列表中,如该示例所示。否则,它将作为死代码被删除;默认情况下没有特殊的逻辑来保持 main() 的活动。
```html
<button id="wasm">运行自定义函数</button>
<script type="text/javascript">
document.getElementById('wasm').addEventListener('click', function () {
alert('检查控制台');
var result = Module.ccall(
'main', // name of C function
null, // return type
null, // argument types
null, // arguments
);
});
</script>
```
[](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html)
```sh
emcc -v main.cpp -o main.html -sEXPORTED_FUNCTIONS=_quick_sort,_main -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
```
EXPORTED_RUNTIME_METHODS 是 Emscripten 中一个用于指定哪些运行时方法可以在生成的 JavaScript 文件中被访问的选项。
通过设置 EXPORTED_RUNTIME_METHODS,你可以控制哪些 Emscripten 运行时的 API 函数被导出,使其可以从生成的 JavaScript 文件中访问和调用。这对于需要在 JavaScript 中调用特定 Emscripten 提供的功能非常有用。
假设你有一个简单的 C 文件 hello.c:
```c++
#include <stdio.h>
void say_hello() {
printf("Hello, World!\n");
}
```
你可以使用以下命令编译这个文件,同时导出 cwrap 和 ccall 方法:
```c++
emcc hello.c -o hello.js -s EXPORTED_RUNTIME_METHODS=['cwrap','ccall']
```
在这个例子中,我们导出了 cwrap 和 ccall 方法,这两个方法在 Emscripten 中常用于从 JavaScript 调用 C 函数。生成的 hello.js 文件可以在浏览器中使用。
接下来,你可以在 JavaScript 中这样使用这些导出的方法:
```html
<!doctype html>
<html>
<head>
<title>Hello Emscripten</title>
</head>
<body>
<script src="hello.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 使用 cwrap 创建一个 JavaScript 包装函数
const sayHello = Module.cwrap('say_hello', null, []);
// 调用包装函数
sayHello();
};
</script>
</body>
</html>
```
在这个例子中,我们通过 Module.cwrap 方法创建了一个 JavaScript 包装函数 sayHello,并调用了它。由于 say_hello 是一个无返回值且无参数的 C 函数,因此我们在 cwrap 中传入了 null 和一个空数组 []。
使用 EXPORTED_RUNTIME_METHODS 可以确保 cwrap 和 ccall 方法在生成的 JavaScript 文件中被导出,并且可以在 JavaScript 中访问和使用这些方法。
### Emscripten 运行时的 API 函数
Emscripten 运行时的 API 函数是指在生成的 JavaScript 文件中提供的用于与编译后的 WebAssembly 或 asm.js 代码交互的函数。Emscripten 提供了多种运行时 API 函数,方便开发者在 JavaScript 中调用 C/C++ 代码,处理内存,进行文件系统操作等。
下面是一些常用的 Emscripten 运行时 API 函数及其用途:
#### 1. cwrap:
- 用于创建一个 JavaScript 函数,该函数可以调用编译后的 WebAssembly 函数。
- 语法:
```js
Module.cwrap('function_name', 'return_type', ['arg_type1', 'arg_type2', ...])
```
#### 2. ccall:
- 用于直接调用编译后的 WebAssembly 函数。
语法:
```js
Module.ccall('function_name', 'return_type', ['arg_type1', 'arg_type2', ...], [arg1, arg2, ...])
```
#### 3. UTF8ToString:
- 将指向 UTF-8 编码字符串的指针转换为 JavaScript 字符串。
语法:
```js
UTF8ToString(ptr);
```
#### 4. allocate:
- 在 Emscripten 堆中分配内存。
语法:
```js
Module._malloc(size);
```
#### 5. HEAP8 / HEAP16 / HEAP32 / HEAPU8 / HEAPU16 / HEAPU32 / HEAPF32 / HEAPF64:
- 直接访问 Emscripten 堆内存的视图,允许读取和写入不同类型的数据。
例如:Module.HEAP32[ptr >> 2] 读取 ptr 位置的 32 位整数。
Emscripten 提供了一系列 API 函数和视图,用于直接访问和操作 WebAssembly 内存。这些 API 和视图在处理复杂的数据结构、字符串、数组等方面非常有用。下面是 allocate 和各种 HEAP 视图的用法。
allocate 函数用于在 Emscripten 堆中分配内存。该函数在较新的 Emscripten 版本中已经不推荐使用,通常推荐使用 \_malloc 代替。
```js
// 分配 1024 字节的内存
var ptr = Module._malloc(1024);
// 使用完毕后释放内存
Module._free(ptr);
```
HEAP 视图
Emscripten 提供了多个 HEAP 视图,用于访问 WebAssembly 内存中的数据。这些视图本质上是 TypedArray,它们允许你读取和写入不同类型的数据。
- HEAP8: 8-bit signed integer (Int8Array)
- HEAPU8: 8-bit unsigned integer (Uint8Array)
- HEAP16: 16-bit signed integer (Int16Array)
- HEAPU16: 16-bit unsigned integer (Uint16Array)
- HEAP32: 32-bit signed integer (Int32Array)
- HEAPU32: 32-bit unsigned integer (Uint32Array)
- HEAPF32: 32-bit floating point (Float32Array)
- HEAPF64: 64-bit floating point (Float64Array)
以下是一个完整的示例,展示如何使用 \_malloc 分配内存,并使用 HEAPU8 视图操作数据:
```c++
#include <emscripten.h>
#include <string.h>
EMSCRIPTEN_KEEPALIVE
void set_memory(char* ptr, int size) {
memset(ptr, 42, size); // 将内存区域设置为 42 (即 '*')
}
```
编译:
```sh
emcc memory.c -o memory.js -s EXPORTED_RUNTIME_METHODS=['_malloc', '_free', 'ccall']
```
JavaScript 代码
```html
<!doctype html>
<html>
<head>
<title>Emscripten Memory Example</title>
</head>
<body>
<script src="memory.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 分配 10 字节的内存
var size = 10;
var ptr = Module._malloc(size);
// 调用 C 函数来设置内存
Module.ccall('set_memory', null, ['number', 'number'], [ptr, size]);
// 使用 HEAPU8 视图读取内存
var view = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
for (var i = 0; i < size; i++) {
console.log(view[i]); // 输出 42
}
// 释放内存
Module._free(ptr);
};
</script>
</body>
</html>
```
更复杂的示例
假设你需要传递一个数组到 C 函数,并且函数会修改这个数组。
C 代码 (假设文件名为 array.c)
```c++
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
void double_values(int* array, int size) {
for (int i = 0; i < size; i++) {
array[i] *= 2;
}
}
```
编译
```sh
emcc array.c -o array.js -s EXPORTED_RUNTIME_METHODS=['_malloc', '_free', 'ccall']
```
JavaScript 代码
```html
<!doctype html>
<html>
<head>
<title>Emscripten Array Example</title>
</head>
<body>
<script src="array.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 创建一个 JavaScript 数组
var array = [1, 2, 3, 4, 5];
var size = array.length;
// 分配足够的内存来存储数组
var ptr = Module._malloc(size * 4); // 每个整数占 4 字节
// 使用 HEAP32 视图将数组复制到 Emscripten 堆
Module.HEAP32.set(array, ptr / 4);
// 调用 C 函数来修改数组
Module.ccall('double_values', null, ['number', 'number'], [ptr, size]);
// 使用 HEAP32 视图读取修改后的数组
var doubledArray = new Int32Array(Module.HEAP32.buffer, ptr, size);
console.log(doubledArray); // 输出:[2, 4, 6, 8, 10]
// 释放内存
Module._free(ptr);
};
</script>
</body>
</html>
```
在这个示例中,我们分配了一块足够大的内存以存储一个整数数组,并使用 HEAP32 视图将 JavaScript 数组复制到 Emscripten 堆中。然后,我们调用 C 函数修改数组,并使用 HEAP32 视图读取修改后的数组。
#### 6. addFunction:
将 JavaScript 函数指针添加到 WebAssembly 表中,使其可以从 WebAssembly 代码中调用。
语法:
```js
Module.addFunction(func, 'sig');
```
#### 7. removeFunction:
- 从 WebAssembly 表中移除函数指针。
语法:
```js
Module.removeFunction(func_ptr);
```
下面是一个完整的示例,演示如何使用 addFunction 和 removeFunction:
假设你有一个简单的 C 文件 call_js.c:
```c++
#include <emscripten.h>
// 声明一个外部函数指针
typedef int (*func_ptr)(int, int);
EM_JS(int, call_js_function, (func_ptr f, int a, int b), {
return f(a, b);
});
int main() {
return 0;
}
```
编译这个文件:
```sh
emcc call_js.c -o call_js.js -s EXPORTED_RUNTIME_METHODS=['addFunction','removeFunction']
```
在 JavaScript 中调用这个函数:
```html
<!doctype html>
<html>
<head>
<title>Emscripten addFunction Example</title>
</head>
<body>
<script src="call_js.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 定义一个 JavaScript 函数
function add(a, b) {
return a + b;
}
// 将 JavaScript 函数添加到 WebAssembly 表中
var addPtr = Module.addFunction(add, 'iii');
// 调用 WebAssembly 函数
var result = Module._call_js_function(addPtr, 5, 7);
console.log(result); // 输出:12
// 从 WebAssembly 表中移除函数指针
Module.removeFunction(addPtr);
};
</script>
</body>
</html>
```
在这个示例中,我们首先定义了一个 JavaScript 函数 add,并使用 Module.addFunction 将其添加到 WebAssembly 表中。然后,我们调用 WebAssembly 函数 \_call_js_function,传入函数指针和参数。最后,我们使用 Module.removeFunction 从 WebAssembly 表中移除了函数指针。
#### 8. getValue 和 setValue:
- 用于读取和写入 Emscripten 堆内存中的值。
语法:
```js
Module.getValue(ptr, type) 和 Module.setValue(ptr, value, type)
```
getValue 和 setValue 是 Emscripten 提供的两个 API,用于读取和写入 WebAssembly 内存中的值。这些函数可以处理不同类型的数据,如整数、浮点数和指针。
getValue 用于从指定内存地址读取值。其语法如下:
```js
var value = Module.getValue(ptr, type);
```
ptr 是内存地址(指针)。
type 是值的类型,可以是 'i8', 'i16', 'i32', 'i64', 'float', 'double', 'i8*', 'i16*', 'i32\*' 等。
setValue 用于向指定内存地址写入值。其语法如下:
Module.setValue(ptr, value, type);
ptr 是内存地址(指针)。
value 是要写入的值。
type 是值的类型,可以是 'i8', 'i16', 'i32', 'i64', 'float', 'double', 'i8*', 'i16*', 'i32\*' 等。
下面是一个示例,展示如何使用 getValue 和 setValue 读取和写入内存中的值。
```c++
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int get_value_from_memory(int* ptr) {
return *ptr;
}
EMSCRIPTEN_KEEPALIVE
void set_value_in_memory(int* ptr, int value) {
*ptr = value;
}
```
编译
```sh
emcc values.c -o values.js -s EXPORTED_RUNTIME_METHODS=['getValue', 'setValue', '_malloc', '_free']
```
JavaScript 代码
```js
<!DOCTYPE html>
<html>
<head>
<title>Emscripten getValue and setValue Example</title>
</head>
<body>
<script src="values.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 分配 4 字节的内存
var ptr = Module._malloc(4);
// 使用 setValue 写入值
Module.setValue(ptr, 42, 'i32');
// 使用 getValue 读取值
var value = Module.getValue(ptr, 'i32');
console.log(value); // 输出:42
// 调用 C 函数读取值
var cValue = Module.ccall('get_value_from_memory', 'number', ['number'], [ptr]);
console.log(cValue); // 输出:42
// 调用 C 函数写入值
Module.ccall('set_value_in_memory', null, ['number', 'number'], [ptr, 84]);
// 使用 getValue 读取新的值
var newValue = Module.getValue(ptr, 'i32');
console.log(newValue); // 输出:84
// 释放内存
Module._free(ptr);
};
</script>
</body>
</html>
```
在这个示例中,我们分配了一块 4 字节的内存(用于存储一个 32 位整数),并使用 setValue 写入值 42,然后使用 getValue 读取这个值。接着,我们调用 C 函数 get_value_from_memory 来读取内存中的值,并调用 C 函数 set_value_in_memory 来修改内存中的值。最后,我们使用 getValue 再次读取修改后的值。
假设你需要在 WebAssembly 中处理更复杂的数据结构,如结构体。你可以使用 getValue 和 setValue 来操作结构体的成员。
```c++
#include <emscripten.h>
typedef struct {
int x;
float y;
} Point;
EMSCRIPTEN_KEEPALIVE
void set_point(Point* p, int x, float y) {
p->x = x;
p->y = y;
}
EMSCRIPTEN_KEEPALIVE
void get_point(Point* p, int* x, float* y) {
*x = p->x;
*y = p->y;
}
```
编译
```sh
emcc struct.c -o struct.js -s EXPORTED_RUNTIME_METHODS=['getValue', 'setValue', '_malloc', '_free', 'ccall']
```
JavaScript 代码
```html
<!doctype html>
<html>
<head>
<title>Emscripten Struct Example</title>
</head>
<body>
<script src="struct.js"></script>
<script>
// 在模块加载完成后调用
Module.onRuntimeInitialized = () => {
// 分配 Point 结构体的内存
var pointSize = 8; // 假设 int 和 float 各占 4 字节
var ptr = Module._malloc(pointSize);
// 调用 C 函数设置结构体
Module.ccall('set_point', null, ['number', 'number', 'number'], [ptr, 3, 4.5]);
// 使用 getValue 读取结构体成员
var x = Module.getValue(ptr, 'i32');
var y = Module.getValue(ptr + 4, 'float');
console.log(x, y); // 输出:3 4.5
// 调用 C 函数读取结构体
var xPtr = Module._malloc(4);
var yPtr = Module._malloc(4);
Module.ccall('get_point', null, ['number', 'number', 'number'], [ptr, xPtr, yPtr]);
var xValue = Module.getValue(xPtr, 'i32');
var yValue = Module.getValue(yPtr, 'float');
console.log(xValue, yValue); // 输出:3 4.5
// 释放内存
Module._free(ptr);
Module._free(xPtr);
Module._free(yPtr);
};
</script>
</body>
</html>
```
在这个示例中,我们使用 set_point 函数设置结构体 Point 的值,并使用 get_point 函数读取结构体的值。我们还展示了如何使用 getValue 和 setValue 操作结构体的成员。
#### 9. FS (File System API):
- 用于在 Emscripten 虚拟文件系统中操作文件。
常用方法包括:FS.createDataFile, FS.readFile, FS.writeFile, FS.unlink 等。
#### 10. stackSave, stackRestore, stackAlloc:
用于管理 Emscripten 堆栈指针,帮助分配和释放堆栈空间。
语法:stackSave(), stackRestore(ptr), stackAlloc(size)
以下是一个使用 ccall 和 UTF8ToString 的示例:
```c++
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
const char* get_hello() {
return "Hello from C!";
}
```
编译这个文件:
```sh
emcc hello.c -o hello.js -s EXPORTED_RUNTIME_METHODS=['ccall','UTF8ToString']
```
在 JavaScript 中调用这个函数:
```html
<!doctype html>
<html>
<head>
<title>Hello Emscripten</title>
</head>
<body>
<script src="hello.js"></script>
<script>
Module.onRuntimeInitialized = () => {
// 调用 C 函数 get_hello
const helloPtr = Module.ccall('get_hello', 'number', [], []);
const helloStr = UTF8ToString(helloPtr);
console.log(helloStr); // 输出:"Hello from C!"
};
</script>
</body>
</html>
```
这个例子展示了如何使用 Emscripten 运行时 API 函数 ccall 调用 C 函数,并使用 UTF8ToString 将返回的指针转换为 JavaScript 字符串。
### cwrap
`cwrap`的方式会更加简单
```html
<button id="wasm">运行自定义函数</button>
<script type="text/javascript">
document.getElementById('wasm').addEventListener('click', function () {
var main = Module.cwrap('main', null, null); // function name, return type, argument type
main();
});
</script>
```
### Embind
https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html?highlight=emscripten_bindings
以下代码使用 EMSCRIPTEN_BINDINGS() 块将简单 C++ lerp() function() 公开给 JavaScript。
```cpp
// quick_example.cpp
#include <emscripten/bind.h>
using namespace emscripten;
float lerp(float a, float b, float t) {
return (1 - t) * a + t * b;
}
EMSCRIPTEN_BINDINGS(my_module) {
function("lerp", &lerp);
}
```
为了使用 `embin` 编译上面的示例,我们使用 `bind` 选项调用 `emcc:`
```sh
emcc -lembind -o main.js main.cpp
```
生成的`main.js`文件可以作为节点模块或通过 `<script>` 标记加载:
```html
<!doctype html>
<html>
<script>
var Module = {
onRuntimeInitialized: function () {
console.log('lerp result: ' + Module.lerp(1, 2, 0.5));
},
};
</script>
<script src="main.js"></script>
</html>
```
绑定代码作为静态构造函数运行,并且仅当链接中包含对象文件时,静态构造函数才会运行,因此在为库文件生成绑定时,必须显式指示编译器包含对象文件。
例如,要为一个假设的库生成绑定.a 编译 Emscripten 运行带有编译器标志的 --whole-archive emcc:
```sh
emcc -lembind -o library.js -Wl,--whole-archive library.a -Wl,--no-whole-archive
```
向 JavaScript 公开类需要更复杂的绑定语句。例如:
```cpp
class MyClass {
public:
MyClass(int x, std::string y)
: x(x)
, y(y)
{}
void incrementX() {
++x;
}
int getX() const { return x; }
void setX(int x_) { x = x_; }
static std::string getStringFromInstance(const MyClass& instance) {
return instance.y;
}
private:
int x;
std::string y;
};
// Binding code
EMSCRIPTEN_BINDINGS(my_class_example) {
class_<MyClass>("MyClass")
.constructor<int, std::string>()
.function("incrementX", &MyClass::incrementX)
.property("x", &MyClass::getX, &MyClass::setX)
.class_function("getStringFromInstance", &MyClass::getStringFromInstance)
;
}
```
绑定块定义了临时 class\_ 对象上的成员函数调用链(在 Boost.Python 中使用了相同的样式)。这些函数注册类、其 constructor() 、成员 function() 、class_function() (静态)和 property() .
然后可以在 JavaScript 中创建和使用 的 MyClass 实例,如下所示:
```js
var instance = new Module.MyClass(10, 'hello');
instance.incrementX();
instance.x; // 11
instance.x = 20; // 20
Module.MyClass.getStringFromInstance(instance); // "hello"
instance.delete();
```
为了防止闭包编译器重命名上述示例代码中的符号,需要按如下方式重写:
```js
var instance = new Module['MyClass'](10, 'hello');
instance['incrementX']();
instance['x']; // 11
instance['x'] = 20; // 20
Module['MyClass']['getStringFromInstance'](instance); // "hello"
instance.delete();
```
请注意,只有优化程序看到的代码才需要这样做,例如,如 in --pre-js 或 上所述,或在 EM_ASM 或 EM_JS --post-js .对于未通过闭包编译器优化的其他代码,您无需进行此类更改。如果您在构建时没有 --closure 1 启用闭包编译器,则也不需要它。
### clone
在某些情况下,JavaScript 代码库的多个长期部分需要将同一 C++ 对象保留不同的时间。
为了适应该用例,Emscripten 提供了一种引用计数机制,在该机制中,可以为同一底层 C++ 对象生成多个句柄。仅当删除所有句柄时,才会销毁对象。
clone() JavaScript 方法返回一个新的句柄。它最终还必须与 delete() :
```js
async function myLongRunningProcess(x, milliseconds) {
// sleep for the specified number of milliseconds
await new Promise((resolve) => setTimeout(resolve, milliseconds));
x.method();
x.delete();
}
const y = new Module.MyClass(); // refCount = 1
myLongRunningProcess(y.clone(), 5000); // refCount = 2
myLongRunningProcess(y.clone(), 3000); // refCount = 3
y.delete(); // refCount = 2
// (after 3000ms) refCount = 1
// (after 5000ms) refCount = 0 -> object is deleted
```
基本类型的手动内存管理很繁重,因此 embind 提供了对值类型的支持。Value arrays 与 JavaScript 数组相互转换,并 value objects 相互转换和从 JavaScript 对象转换。
### 总结
```sh
emcc -lembind -o main.js main.cpp -sEXPORTED_FUNCTIONS=_quick_sort,_main -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
```
### 基于内存的方式
1. 声明和分配内存
在 WebAssembly 中,内存是通过 WebAssembly.Memory 对象管理的。Emscripten 通常会自动处理内存分配,但你也可以手动管理。
2. 在 C/C++ 中访问内存
在 C/C++ 代码中,你可以通过指针直接访问和操作内存。
```c++
#include <emscripten.h>
#include <cstring>
// 简单的函数来设置内存中的数据
extern "C" {
EMSCRIPTEN_KEEPALIVE
void set_memory(int offset, int value) {
int *ptr = reinterpret_cast<int*>(offset);
*ptr = value;
}
EMSCRIPTEN_KEEPALIVE
int get_memory(int offset) {
int *ptr = reinterpret_cast<int*>(offset);
return *ptr;
}
}
```
3. 编译 C++ 代码
使用 Emscripten 将上述代码编译为 WebAssembly 模块。
```sh
emcc memory_example.cpp -o memory_example.js -s EXPORTED_FUNCTIONS='["_set_memory", "_get_memory"]' -s ALLOW_MEMORY_GROWTH=1
```
4. 在 JavaScript 中访问和操作内存
Emscripten 会为你提供一个 HEAP 对象,可以用来直接访问 WebAssembly 模块的内存。常用的内存视图包括:
- HEAP8: 8-bit signed integer array
- HEAPU8: 8-bit unsigned integer array
- HEAP16: 16-bit signed integer array
- HEAPU16: 16-bit unsigned integer array
- HEAP32: 32-bit signed integer array
- HEAPU32: 32-bit unsigned integer array
- HEAPF32: 32-bit floating-point array
- HEAPF64: 64-bit floating-point array
```html
<!doctype html>
<html>
<head>
<title>Memory Access Example</title>
<script src="memory_example.js"></script>
</head>
<body>
<script>
// 等待 WebAssembly 模块加载
Module.onRuntimeInitialized = function () {
// 在内存中分配一个整数位置
const offset = Module._malloc(4); // 分配 4 字节 (32-bit 整数)
// 使用 C 函数设置内存中的值
Module._set_memory(offset, 12345);
console.log('Value set in memory:', Module._get_memory(offset)); // 输出:12345
// 直接使用 HEAP 视图访问内存
Module.HEAP32[offset / 4] = 67890; // 4 字节对齐
console.log('Value directly in memory:', Module.HEAP32[offset / 4]); // 输出:67890
// 释放内存
Module._free(offset);
};
</script>
</body>
</html>
```
5. 更复杂的数据类型
你可以使用 HEAP 对象来访问和操作更复杂的数据类型,例如结构体或数组。
```c++
#include <emscripten.h>
#include <cstring>
struct MyStruct {
int a;
float b;
};
extern "C" {
EMSCRIPTEN_KEEPALIVE
void set_struct(int offset, int a, float b) {
MyStruct *ptr = reinterpret_cast<MyStruct*>(offset);
ptr->a = a;
ptr->b = b;
}
EMSCRIPTEN_KEEPALIVE
void get_struct(int offset, int *a, float *b) {
MyStruct *ptr = reinterpret_cast<MyStruct*>(offset);
*a = ptr->a;
*b = ptr->b;
}
}
```
编译命令
```sh
emcc struct_example.cpp -o struct_example.js -s EXPORTED_FUNCTIONS='["_set_struct", "_get_struct"]' -s ALLOW_MEMORY_GROWTH=1
```
JS 代码:
```html
<!doctype html>
<html>
<head>
<title>Struct Memory Access Example</title>
<script src="struct_example.js"></script>
</head>
<body>
<script>
// 等待 WebAssembly 模块加载
Module.onRuntimeInitialized = function () {
// 在内存中分配一个结构体位置
const structSize = 8; // sizeof(MyStruct)
const offset = Module._malloc(structSize);
// 设置结构体的值
Module._set_struct(offset, 42, 3.14);
// 获取结构体的值
const aPtr = Module._malloc(4); // int
const bPtr = Module._malloc(4); // float
Module._get_struct(offset, aPtr, bPtr);
// 打印结果
console.log('Struct values:', Module.HEAP32[aPtr >> 2], Module.HEAPF32[bPtr >> 2]);
// 释放内存
Module._free(offset);
Module._free(aPtr);
Module._free(bPtr);
};
</script>
</body>
</html>
```
通过这些步骤,你可以在 JavaScript 和 C/C++ 之间通过共享内存进行高效的通信。这种方法特别适合需要频繁交互或传递大量数据的场景。
但也有一些限制和注意事项:
1. 内存安全
- 缓冲区溢出:在直接操作内存时,需要小心避免缓冲区溢出。错误的内存访问可能导致崩溃或不可预测的行为。
- 类型安全:JavaScript 和 C/C++ 之间的数据类型可能不匹配。确保正确地处理和转换数据类型以避免错误。
2. 内存对齐
- 对齐要求:在操作内存时,确保数据对齐。例如,32 位整数需要 4 字节对齐,64 位浮点数需要 8 字节对齐。未对齐的内存访问可能导致性能下降或错误。
3. 性能问题
- 频繁的内存访问:尽管共享内存访问比函数调用更快,但频繁的内存读写仍可能带来性能开销。应尽量减少不必要的内存操作。
- 内存分配和释放:频繁的内存分配和释放可能导致内存碎片,从而影响性能。
4. 内存管理
- 手动内存管理:需要手动管理内存的分配和释放。忘记释放分配的内存可能导致内存泄漏。
- 固定内存大小:默认情况下,WebAssembly 内存大小是固定的,尽管可以配置增长,但需要额外的设置。
5. 内存视图限制
- 视图限制:WebAssembly 内存视图 (HEAP8, HEAP16, HEAP32, 等) 是基于 ArrayBuffer 的,需要注意视图的边界和大小。
6. 数据转换
- 字符串处理:C/C++ 中的字符串和 JavaScript 中的字符串处理方式不同。需要进行适当的转换。
从 C/C++ 到 JavaScript:使用 UTF8ToString。
从 JavaScript 到 C/C++:使用 stringToUTF8。
7. 并发和线程
- 线程安全:WebAssembly 目前支持共享内存和线程(使用 WebAssembly Threads),但需要小心处理并发和同步问题,以避免竞争条件和死锁。
8. 调试和开发
- 调试困难:直接操作内存可能使调试变得更加困难。需要仔细检查内存地址和数据,以确保正确性。
- 可维护性:直接内存访问的代码可能比使用更高级别接口的代码更难维护和理解。
示例代码中的改进建议
- 内存对齐:确保在使用 malloc 分配内存时,对齐地址。例如,对于 32 位整数使用 HEAP32 视图时,确保地址是 4 的倍数。
- 字符串转换:如果需要传递字符串,请使用 Emscripten 提供的工具函数。
改进后的示例
以下是一些改进建议:
C++ 代码(改进内存对齐)
```c++
#include <emscripten.h>
#include <cstring>
// 简单的函数来设置内存中的数据
extern "C" {
EMSCRIPTEN_KEEPALIVE
void set_memory(int offset, int value) {
if (offset % 4 != 0) return; // 检查对齐
int *ptr = reinterpret_cast<int*>(offset);
*ptr = value;
}
EMSCRIPTEN_KEEPALIVE
int get_memory(int offset) {
if (offset % 4 != 0) return 0; // 检查对齐
int *ptr = reinterpret_cast<int*>(offset);
return *ptr;
}
}
```
JavaScript 代码(改进内存对齐和字符串处理)
```html
<!doctype html>
<html>
<head>
<title>Memory Access Example</title>
<script src="memory_example.js"></script>
</head>
<body>
<script>
// 等待 WebAssembly 模块加载
Module.onRuntimeInitialized = function () {
// 在内存中分配一个整数位置
const offset = Module._malloc(4); // 分配 4 字节 (32-bit 整数)
// 确保内存对齐
if (offset % 4 === 0) {
// 使用 C 函数设置内存中的值
Module._set_memory(offset, 12345);
console.log('Value set in memory:', Module._get_memory(offset)); // 输出:12345
// 直接使用 HEAP 视图访问内存
Module.HEAP32[offset / 4] = 67890; // 4 字节对齐
console.log('Value directly in memory:', Module.HEAP32[offset / 4]); // 输出: 67890
} else {
console.error('Memory not aligned correctly.');
}
// 释放内存
Module._free(offset);
};
</script>
</body>
</html>
```
通过注意上述限制和改进建议,你可以更高效和安全地在 JavaScript 和 WebAssembly(C/C++)之间通过共享内存进行通信。
## 多线程
WebAssembly 目前支持多线程,通过 SharedArrayBuffer 和 Web Workers 实现。Emscripten 提供了一些工具和支持来使多线程编程更加容易。以下是使用 Emscripten 和 WebAssembly 实现多线程的方法。
前提条件
确保在你的浏览器环境中启用了 SharedArrayBuffer,因为它是实现多线程的关键。
设置 Emscripten 项目以支持多线程:
- 编译时启用线程支持
- 使用 Web Workers
- 使用 pthread 库
示例项目
1. 创建一个 C++ 文件
假设你的 C++ 文件名为 threads_example.cpp。
```c++
#include <iostream>
#include <pthread.h>
#include <emscripten.h>
void* thread_main(void* arg) {
int* num = static_cast<int*>(arg);
std::cout << "Hello from thread! Argument: " << *num << std::endl;
return 0;
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
void create_thread(int num) {
pthread_t thread;
int* arg = new int(num);
pthread_create(&thread, nullptr, thread_main, arg);
pthread_detach(thread);
}
}
```
2. 编译 C++ 文件
使用 Emscripten 编译文件,并启用线程支持。
```sh
emcc threads_example.cpp -o threads_example.js -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4 -s EXPORTED_FUNCTIONS='["_create_thread"]' -s ALLOW_MEMORY_GROWTH=1
```
3. 创建 HTML 文件
创建一个 HTML 文件以加载和运行编译后的 WebAssembly 模块。
```html
<!doctype html>
<html>
<head>
<title>WebAssembly Multithreading Example</title>
<script src="threads_example.js"></script>
</head>
<body>
<script>
Module.onRuntimeInitialized = function () {
console.log('WebAssembly module initialized');
Module._create_thread(42);
};
</script>
</body>
</html>
```
说明:
C++ 代码
- pthread_create:用于创建新线程。
- pthread_detach:分离线程,使其在完成后自动释放资源。
- EMSCRIPTEN_KEEPALIVE:确保函数不会被编译器优化掉,使其在 JavaScript 中可用。
JavaScript 代码
- Module.onRuntimeInitialized:等待 WebAssembly 模块初始化完成。
- Module.\_create_thread:调用导出的 create_thread 函数创建新线程。
多线程注意事项
1. 线程安全:确保在多线程环境中正确处理数据竞争和同步问题。
2. 共享内存:使用 SharedArrayBuffer 在线程之间共享内存。
3. 性能开销:线程的创建和管理会带来一些性能开销,尽量避免频繁创建和销毁线程。
4. 浏览器兼容性:确保你的浏览器支持 SharedArrayBuffer 和多线程 WebAssembly。
示例代码扩展
你可以扩展上述示例,使多个线程协作完成更复杂的任务。例如,实现一个简单的并行计算。
扩展 C++ 代码
```c++
#include <iostream>
#include <pthread.h>
#include <emscripten.h>
#include <vector>
const int num_threads = 4;
int results[num_threads];
void* thread_compute(void* arg) {
int index = *static_cast<int*>(arg);
results[index] = index * index; // 简单的计算任务
return 0;
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
void parallel_compute() {
pthread_t threads[num_threads];
std::vector<int> args(num_threads);
for (int i = 0; i < num_threads; ++i) {
args[i] = i;
pthread_create(&threads[i], nullptr, thread_compute, &args[i]);
}
for (int i = 0; i < num_threads; ++i) {
pthread_join(threads[i], nullptr);
}
for (int i = 0; i < num_threads; ++i) {
std::cout << "Result from thread " << i << ": " << results[i] << std::endl;
}
}
}
```
扩展 JavaScript 代码
```js
<!DOCTYPE html>
<html>
<head>
<title>WebAssembly Multithreading Example</title>
<script src="threads_example.js"></script>
</head>
<body>
<script>
Module.onRuntimeInitialized = function() {
console.log('WebAssembly module initialized');
Module._parallel_compute();
};
</script>
</body>
</html>
```
通过 Emscripten 和 WebAssembly,你可以利用多线程来提高性能和响应能力。确保处理好线程安全和同步问题,以避免数据竞争和其他多线程相关的问题。
以下是一些关键点:
1. 数据竞争和同步
- 数据竞争:当多个线程同时访问和修改共享数据时,可能会出现数据竞争问题。这会导致不可预测的行为和错误。
- 避免数据竞争:使用线程同步机制,例如互斥锁(mutex)、信号量(semaphore)和条件变量(condition variable)来保护共享数据。
示例:使用互斥锁
```c++
#include <iostream>
#include <pthread.h>
#include <emscripten.h>
pthread_mutex_t mutex;
void* thread_safe_increment(void* arg) {
pthread_mutex_lock(&mutex);
int* counter = static_cast<int*>(arg);
(*counter)++;
pthread_mutex_unlock(&mutex);
return 0;
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
void create_threads(int num_threads, int* counter) {
pthread_t threads[num_threads];
pthread_mutex_init(&mutex, nullptr);
for (int i = 0; i < num_threads; ++i) {
pthread_create(&threads[i], nullptr, thread_safe_increment, counter);
}
for (int i = 0; i < num_threads; ++i) {
pthread_join(threads[i], nullptr);
}
pthread_mutex_destroy(&mutex);
}
}
```
2. 死锁
- 死锁:当两个或多个线程相互等待对方释放资源时,会发生死锁,导致所有相关线程都被无限期阻塞。
- 避免死锁:小心设计锁的获取顺序,避免嵌套锁定。尽量使用尝试锁(try-lock)而不是阻塞锁。
3. 线程池
- 线程池:创建和销毁线程开销较大,使用线程池可以重复利用线程,减少开销。
- 实现线程池:通过预先创建一组线程,并将任务分配给这些线程执行。
示例:简单线程池
```c++
#include <iostream>
#include <queue>
#include <pthread.h>
#include <emscripten.h>
const int num_threads = 4;
pthread_t threads[num_threads];
std::queue<void (*)()> task_queue;
pthread_mutex_t queue_mutex;
pthread_cond_t queue_cond;
void* thread_main(void* arg) {
while (true) {
pthread_mutex_lock(&queue_mutex);
while (task_queue.empty()) {
pthread_cond_wait(&queue_cond, &queue_mutex);
}
auto task = task_queue.front();
task_queue.pop();
pthread_mutex_unlock(&queue_mutex);
task();
}
return 0;
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
void initialize_thread_pool() {
pthread_mutex_init(&queue_mutex, nullptr);
pthread_cond_init(&queue_cond, nullptr);
for (int i = 0; i < num_threads; ++i) {
pthread_create(&threads[i], nullptr, thread_main, nullptr);
}
}
EMSCRIPTEN_KEEPALIVE
void add_task(void (*task)()) {
pthread_mutex_lock(&queue_mutex);
task_queue.push(task);
pthread_cond_signal(&queue_cond);
pthread_mutex_unlock(&queue_mutex);
}
}
```
4. 资源管理
- 资源泄漏:确保所有动态分配的资源在使用完毕后正确释放,包括内存、文件描述符和锁等。
- 自动管理资源:使用智能指针(如 C++ 的 std::unique_ptr 和 std::shared_ptr)或 RAII(资源获取即初始化)模式。
5. 性能开销
- 线程切换:频繁的线程切换会导致性能下降。尽量减少不必要的线程创建和销毁。
- 批量处理:将多个任务批量处理,以减少线程切换开销。
6. 浏览器兼容性
- 浏览器支持:确保目标浏览器支持 WebAssembly 多线程和 SharedArrayBuffer。一些旧版浏览器可能不支持这些特性。
- 特性检测:在代码中检测浏览器是否支持 SharedArrayBuffer,并在不支持的情况下提供替代方案。
7. 调试和测试
- 调试工具:使用调试工具和日志记录来跟踪线程行为和问题。
- 并发测试:进行并发测试以确保代码在多线程环境下的正确性和稳定性。
8. 内存对齐
- 内存对齐:确保内存对齐以提高性能和避免潜在的错误,特别是在访问共享内存时。
示例总结
通过以下 JavaScript 代码来初始化线程池并添加任务:
```html
<!doctype html>
<html>
<head>
<title>WebAssembly Multithreading Example</title>
<script src="threads_example.js"></script>
</head>
<body>
<script>
Module.onRuntimeInitialized = function () {
console.log('WebAssembly module initialized');
Module._initialize_thread_pool();
const task = Module.addFunction(() => {
console.log('Task executed');
}, 'v');
Module._add_task(task);
};
</script>
</body>
</html>
```
通过注意上述多线程编程中的注意事项,可以有效地利用 WebAssembly 和 Emscripten 提供的多线程功能,实现高性能和高效的并发处理。确保正确处理数据竞争、同步和资源管理,以避免常见的多线程问题。
[emcc 指令参考](https://emscripten.org/docs/tools_reference/settings_reference.html)
================================================
FILE: packages/cpro/sum.cpp
================================================
#include <emscripten/bind.h>
using namespace emscripten;
//接收两个浮点型参数,返回一个字符串
std::string sum(double a,double b) {
return std::to_string(a*b);
}
//公开一个方法给 JavaScript 访问
EMSCRIPTEN_BINDINGS(myModule) {
function("sum", &sum);
}
================================================
FILE: packages/debug/koaStatic/index.ts
================================================
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import Koa from 'koa';
import serve from 'koa-static';
import mount from 'koa-mount';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = new Koa();
const PORT = 5555;
const STATIC_DIR = 'dist';
// 设置正确的 MIME 类型
app.use(async (ctx, next) => {
if (ctx.path.endsWith('.js')) {
ctx.type = 'application/javascript';
} else if (ctx.path.endsWith('.mjs')) {
ctx.type = 'application/javascript';
} else if (ctx.path.endsWith('.json')) {
ctx.type = 'application/json';
} else if (ctx.path.endsWith('.css')) {
ctx.type = 'text/css';
}
await next();
});
app.use(async (ctx, next) => {
ctx.set('Cross-Origin-Opener-Policy', 'same-origin');
ctx.set('Cross-Origin-Embedder-Policy', 'require-corp');
await next();
});
// Serve static files from the 'dist' directory with /weread prefix
app.use(mount('/weread', serve(path.join(__dirname, STATIC_DIR))));
// 启动服务器
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
export default app;
================================================
FILE: packages/debug/koaStatic/readme.md
================================================
# 静态服务
用于排查一些本地启动没有问题,但是部署到线上环境就无法运行的问题
有时候需要搭配 nginx 做反向代理域名映射,用于完整并彻底的模拟线上环境
================================================
FILE: packages/debug/nginxconf/agency.conf
================================================
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name trade-app.longbridge.xyz;
location / {
proxy_pass http://localhost:5555;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
================================================
FILE: packages/debug/nginxconf/readme.md
================================================
1. 使用命令行参数指定配置文件路径
```sh
nginx -c /path/to/your/nginx.conf
```
请注意,当您使用 -c 参数时,Nginx 将仅加载您指定的配置文件,而不会加载任何其他通过 include 指令包含的文件(除非这些 include 指令位于您指定的配置文件中)。因此,请确保您的自定义配置文件中包含了所有必要的设置和 include 指令。
在启动之前,可以先通过`-t`测试一下:
```sh
nginx -t -c /path/to/your/nginx.conf
```
重启
```sh
nginx -s reload
```
另外,如果您已经运行了 Nginx 实例,并且想要更改其配置而无需完全停止并重新启动服务,您可以使用 nginx -s reload 命令,但前提是您的主配置文件(或您通过 -c 参数指定的配置文件)已经更改,并且 Nginx 能够重新加载这些更改。不过,请注意,nginx -s reload 命令不会直接接受 -c 参数来指定一个新的配置文件;它只会重新加载当前正在使用的配置文件(或您通过 Nginx 的启动脚本/服务管理器指定的配置文件)的更改。
2. 配置本地 DNS 解析
由于 nginx 配置的 server_name 往往是一个真实的域名,你的本地机器默认会尝试通过互联网解析它。为了让你在本地开发环境中测试反向代理,你需要确保当在本地机器上访问这个域名时,它会被解析到 127.0.0.1(即 localhost)。
有几种方法可以实现这一点,包括修改 /etc/hosts 文件或在你的 DNS 服务器中设置条目(如果你正在使用本地 DNS 服务器)。
```sh
cat /etc/hosts
```
在文件末尾添加一行,将域名映射到 localhost:
```sh
127.0.0.1 server_name
```
保存并关闭文件。现在,当你尝试在浏览器中访问 server_name 域名时,请求应该会被转发到你的本地 localhost:5555。
注意:确保 localhost:5555 上有一个正在运行的服务器,以便 Nginx 可以成功转发请求。
3. 启动
进入 Nginx 安装目录的 sbin 文件夹:通常 Nginx 的可执行文件位于/usr/local/nginx/sbin(具体路径可能因安装方式和操作系统而异)。
执行重启命令:在 sbin 目录下,执行./nginx -s reload 命令。这条命令会优雅地重启 Nginx 服务,即不会立即关闭已经建立的连接,而是等待现有请求处理完成后,重新加载配置文件并启动新的工作进程。
使用 brew 服务命令:
```sh
brew services restart nginx
```
直接使用 Nginx 命令:
你也可以直接使用 Nginx 的-s 参数来停止服务。有两种停止方式:
快速停止(不等待处理完当前请求):
```sh
sudo nginx -s stop
```
优雅停止(等待处理完当前请求后再停止):
```sh
sudo nginx -s quit
```
4. 关闭
进入 Nginx 安装目录的 sbin 文件夹(如果尚未进入)。
执行关闭命令:可以使用./nginx -s stop 命令来快速停止 Nginx 服务,这将立即关闭所有连接。另外,./nginx -s quit 命令会等待所有请求处理完成后才停止服务,这是一种更优雅的关闭方式。
在某些情况下,你可能需要手动停止 Nginx 服务。这通常涉及到找到 Nginx 的主进程号(PID),并使用 kill 命令发送相应的信号来停止进程。
查找 Nginx 主进程的 PID:可以使用 ps 命令结合 grep 来查找,如:
```sh
ps -ef | grep nginx
```
发送停止信号:根据找到的 PID,使用 kill 命令发送 TERM(快速停止)或 INT(优雅停止)信号。例如,kill -TERM <pid>或 kill -INT <pid>。此外,kill -HUP <pid>也可以用于平滑重启 Nginx,但这实际上是发送了一个挂起信号,而不是停止信号。
使用 brew 服务命令:
关闭 Nginx 服务的最简单方式同样是使用 brew 提供的服务管理命令。在终端中输入以下命令:
```sh
brew services stop nginx
```
Nginx 的配置文件通常遵循以下结构:
```sh
# 全局块
events {
# events 块
}
http {
# http 块
server {
# server 块
location / {
# location 块
}
# 更多的 location 块
}
# 更多的 server 块
}
# 注意:server 指令必须嵌套在 http 块中
```
查看状态:
```sh
ps aux | grep nginx
```
================================================
FILE: packages/debug/package.json
================================================
{
"name": "debug",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^3.0.3",
"koa-mount": "^4.2.0",
"koa-send": "^5.0.1",
"koa-static": "^5.0.0"
},
"devDependencies": {
"@types/koa": "^2.15.0",
"@types/koa-mount": "^4.0.5",
"@types/koa-send": "^4.1.6",
"@types/koa-static": "^4.0.4"
}
}
================================================
FILE: packages/debug/tsconfig.json
================================================
{
"exclude": ["node_modules/**", "dist/**", "public"],
"include": ["**/*.ts", "**/*.d.ts", "**/*.tsx", "tailwind.config.ts"],
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"target": "ESNext",
"declaration": true,
"outDir": "dist",
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"isolatedModules": false,
"strict": true,
"skipLibCheck": true,
"noImplicitAny": true,
"useUnknownInCatchVariables": false,
"inlineSourceMap": true,
"baseUrl": ".",
"experimentalDecorators": true
}
}
================================================
FILE: packages/docs/.vitepress/common/index.ts
================================================
import { SERVICE_WORK_VERSION } from '../../variable/SERVICE_WORK_VERSION';
export const GTAG = 'https://www.googletagmanager.com/gtag/js?id=G-0MPS5WH1C0';
export const GOOGLE_ANALYSE = `;window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);};gtag('js', new Date());gtag('config', 'G-0MPS5WH1C0');`;
export const BD_ANALYSE = `
;var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?3bc20bd8070ce614078a36c686209456";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
`;
export const PREVIEW_CODE = `
window.uploadFile = (name) => {
const preview = document.getElementById(name)
const uploadFile = document.createElement('input')
uploadFile.setAttribute('type', 'file')
uploadFile.click()
uploadFile.onchange = (e) => {
const { files = [] } = uploadFile
if (preview) {
if (files && files.length > 0) {
preview.setAttribute('src', '')
const file = files[0]
const url = URL.createObjectURL(file)
preview.setAttribute('src', url)
}
}
}
}
`;
export const DESCRIPTION =
'Based on web component library, common function library utils, personal article record and so on';
export const HOME = 'https://chaxus.github.io/ran/';
export const BASE_PATH = '/ran/';
export const HOME_ICON = `${HOME}home.svg`;
export const UTILS_PATH = `${HOME}src/ranuts/utils/`;
export const RANUI_PATH = `${HOME}src/ranui/`;
export const ARTICLE_PATH = `${HOME}src/article/designMode.html`;
export const KEY_WORDS = 'ran,component,components,ui,design,ranui,web-components,javascript,typescript,js';
export const GITHUB = 'https://github.com/chaxus/ran';
export const SERVICE_WORK = `
// 注册 Service worker
const registerServiceWorker = async () => {
if ('serviceWorker' in window.navigator) {
try {
const registration = await navigator.serviceWorker.register('/ran/sw${SERVICE_WORK_VERSION}.js', {
scope: '/ran/',
});
if (registration.installing) {
console.log('installing Service worker');
} else if (registration.waiting) {
console.log('Service worker installed');
} else if (registration.active) {
console.log('Service worker active');
}
} catch (error) {
console.error('service worker register error:', error);
}
}
};
registerServiceWorker();
`;
export const SET_FONT_SIZE = `
function initFontSize() {
let base = 375;
const { documentElement } = document;
const mediaQuery = window.matchMedia('(orientation: portrait)');
let timer;
let standardRatio = 667 / 375;
const ua = navigator.userAgent.toLowerCase();
const ipad = /ipad|ipod/.test(ua)
if (ipad) {
standardRatio = 1024 / 768;
base = 768;
}
function setFontSize() {
const ua = navigator.userAgent.toLowerCase();
const ipad = /ipad|ipod/.test(ua)
const android = /android/.test(ua)
const iphone = /iphone/.test(ua)
if(!ipad && !android && !iphone) {
documentElement.style.fontSize = '';
return
}
const isLandscape = !mediaQuery.matches;
let screenWidth = window.screen.width;
let screenHeight = window.screen.height;
if (screenWidth < screenHeight) {
[ screenWidth, screenHeight ] = [ screenHeight, screenWidth ];
}
let width = documentElement.clientWidth;
let height = screenHeight;
const realRatio = width / height;
if (realRatio >= standardRatio) {
width = height * standardRatio;
documentElement.classList.remove('adjustHeight');
documentElement.classList.add('adjustWidth');
} else {
height = width / standardRatio;
documentElement.classList.remove('adjustWidth');
documentElement.classList.add('adjustHeight');
}
window.adjustWidth = width;
window.adjustHeight = height;
let target = width / base * 16;
if (isLandscape) {
target /= standardRatio;
}
documentElement.style.fontSize = target + 'px';
const currentSize = window.getComputedStyle(documentElement).fontSize.replace('px', '');
if (target !== currentSize) {
documentElement.style.fontSize = target / currentSize * target + 'px';
}
}
window.addEventListener('resize', function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, !1);
window.addEventListener('pageshow', function(e) {
e.persisted && (clearTimeout(timer), timer = setTimeout(setFontSize, 300));
}, !1);
window.addEventListener('orientationchange', function() {
console.log('改变了手机方向');
setFontSize();
}, false);
setFontSize();
};
initFontSize();
`;
================================================
FILE: packages/docs/.vitepress/common/sw.ts
================================================
// 注册 Service worker
const registerServiceWorker = async () => {
if ('serviceWorker' in window.navigator) {
try {
// eslint-disable-next-line n/no-unsupported-features/node-builtins
const registration = await navigator.serviceWorker.register('/ran/sw.js', {
scope: '/ran/',
});
if (registration.installing) {
console.log('installing Service worker');
} else if (registration.waiting) {
console.log('Service worker installed');
} else if (registration.active) {
console.log('Service worker active');
}
} catch (error) {
console.error('service worker register error:', error);
}
}
};
registerServiceWorker();
================================================
FILE: packages/docs/.vitepress/components/Layout.vue
================================================
<template>
<DefaultTheme.Layout />
</template>
<script setup lang="ts">
import DefaultTheme from 'vitepress/theme';
import { useData } from 'vitepress';
import useBasic from '../composition/useBasic';
import { watchEffect, onMounted } from 'vue';
import { localStorageSetItem, setFontSize2html } from 'ranuts/utils';
import { RAN_CHAXUS_LANG, LANGS_DICT } from '../lib/constant';
import { loadLanguageAsync } from '../lang';
const { $env, locale } = useBasic();
const { lang } = useData();
const setLang = () => {
const language = lang.value || LANGS_DICT.EN;
locale.value = language;
$env.locale = language;
loadLanguageAsync(language).catch((error) => {
console.log('error', error);
});
localStorageSetItem(RAN_CHAXUS_LANG, language);
};
watchEffect(() => {
setLang();
});
onMounted(() => {
setFontSize2html();
});
</script>
================================================
FILE: packages/docs/.vitepress/components/TOTP.vue
================================================
<template>
<div>
<div class="text-slate-600 text-base mt-2">{{ t('components_totp_6') }}</div>
<div class="flex flex-row justify-start items-start mt-4">
<div class="relative h-14">
<r-input
:label="t('components_totp_2')"
class="w-64 h-8 rounded-lg block text-lg"
:status="inputStatus"
@input="onChange"
></r-input>
<div class="absolute bottom-0 left-0 text-sm text-[#ff4d4f]" v-if="inputStatus === INPUT_STATUS.ERROR">
{{ errorMessage }}
</div>
</div>
<r-button class="ml-1 h-8" @click="clickButton">{{ t('components_totp_1') }}</r-button>
</div>
<div class="text-[#3451b2] text-base mt-6">
<div>code: {{ outputValue.code }}</div>
<div>{{ t('components_totp_4') }}: {{ outputValue.expires }}</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { INPUT_STATUS } from '../lib/constant';
import { ref } from 'vue';
import useBasic from '../composition/useBasic';
import { TOTP, timestampToTime } from 'ranuts/utils';
const { t, $env, locale } = useBasic();
// 输入框的值
const inputValue = ref('');
// 输入框的状态
const inputStatus = ref(INPUT_STATUS.NORMAL);
// 错误的文本提示
const errorMessage = ref('');
// 点击按钮输出的结果
const outputValue = ref({
code: '',
expires: '',
});
/**
* @description: 监听输入框的变化
* @param {*} e
*/
const onChange = (e: { detail: { value: string } }) => {
inputValue.value = e.detail.value;
inputStatus.value = INPUT_STATUS.NORMAL;
};
/**
* @description: 点击生成结果
* @return {*}
*/
const clickButton = () => {
// 没有输入的情况
if (inputValue.value.length <= 0) {
errorMessage.value = t('components_totp_3');
inputStatus.value = INPUT_STATUS.ERROR;
} else {
try {
const { otp, expires } = TOTP.generate(inputValue.value);
outputValue.value.code = otp;
outputValue.value.expires = timestampToTime(expires).format();
} catch (error) {
errorMessage.value = t('components_totp_5');
inputStatus.value = INPUT_STATUS.ERROR;
}
}
};
</script>
================================================
FILE: packages/docs/.vitepress/composition/useBasic.ts
================================================
import { inject } from 'vue';
import { useI18n } from 'vue-i18n';
import type { Env } from '../plugins/env';
export default (): any => {
const $env: Env = inject('$env')!;
const { t, locale } = useI18n();
return { locale, $env, t };
};
================================================
FILE: packages/docs/.vitepress/config.ts
================================================
import { defineConfig } from 'vitepress';
import { themeEnConfig } from './langs/en';
import { themeCnConfig } from './langs/cn';
import {
ARTICLE_PATH,
BASE_PATH,
BD_ANALYSE,
DESCRIPTION,
GOOGLE_ANALYSE,
GTAG,
HOME,
HOME_ICON,
// KEY_WORDS,
PREVIEW_CODE,
RANUI_PATH,
SERVICE_WORK,
SET_FONT_SIZE,
UTILS_PATH,
} from './common/index';
import { LANGS_DICT } from './lib/constant';
export default defineConfig({
title: 'ran',
description: DESCRIPTION,
base: BASE_PATH,
lastUpdated: true,
locales: {
// root: { label: '简体中文', lang: 'zh-CN' },
// en: {
// label: 'English',
// lang: 'en',
// themeConfig: themeEnConfig,
// },
root: { label: 'English', lang: LANGS_DICT.EN },
cn: {
label: '简体中文',
lang: LANGS_DICT.ZH_CN,
themeConfig: themeCnConfig,
},
},
vue: {
template: {
compilerOptions: {
isCustomElement: (tag: string) => {
return tag.startsWith('r-');
},
},
},
},
head: [
// base
['link', { rel: 'icon', href: `${BASE_PATH}favicon.ico` }],
['link', { rel: 'manifest', href: `${BASE_PATH}manifest.json` }],
['meta', { name: 'theme-color', content: '#646cff' }],
// author
['meta', { name: 'author', content: '81380@163.com' }],
// 表示爬虫对此页面的处理行为 或 应当遵守的规则,是用来做搜索引擎抓取的
// all:搜索引擎将索引此网页,并继续通过此 网页的链接索引文件 将被检索
// none:搜索引擎将 忽略 此网页
// index:搜索引擎 索引 此网页
// follow:搜索引擎继续通过此网页的链接索引搜索 其它的网页
['meta', { name: 'robots', content: 'all' }],
// 用来指定支持双核浏览器要采用哪种的渲染方式
['meta', { name: 'renderer', content: 'webkit' }],
// 已经有国际化,禁止谷歌自动翻译
['meta', { name: 'google', content: 'notranslate' }],
// og
['meta', { property: 'og:title', content: 'ran' }],
[
'meta',
{
property: 'og:description',
content: DESCRIPTION,
},
],
['meta', { property: 'og:url', content: HOME }],
['meta', { property: 'og:image', content: HOME_ICON }],
['meta', { property: 'og:type', content: 'article' }],
[
'meta',
{
property: 'article:home',
content: HOME,
},
],
['meta', { property: 'article:ranui', content: RANUI_PATH }],
['meta', { property: 'article:ranuts', content: UTILS_PATH }],
['meta', { property: 'article:section', content: ARTICLE_PATH }],
// keywords
// ['meta', { name: 'keywords', content: KEY_WORDS }],
// chrome
['meta', { httpEquiv: 'Permissions-Policy', content: 'interest-cohort=()' }],
// set font size
['script', {}, SET_FONT_SIZE],
// report
['script', { defer: 'true', src: GTAG }],
['script', {}, GOOGLE_ANALYSE],
['script', {}, BD_ANALYSE],
// preview component script
['script', {}, PREVIEW_CODE],
// service worker and pwa
['script', {}, SERVICE_WORK],
],
themeConfig: themeEnConfig,
});
================================================
FILE: packages/docs/.vitepress/lang/en.json
================================================
{
"lang": "English",
"components_totp_1": "Generate",
"components_totp_2": "Please enter the key of 2FA",
"components_totp_3": "You haven't entered the key for 2FA",
"components_totp_4": "expires",
"components_totp_5": "The entered key value is invalid",
"components_totp_6": "2FA Verification"
}
================================================
FILE: packages/docs/.vitepress/lang/index.ts
================================================
import { createI18n } from 'vue-i18n';
import { $env } from '../plugins/env';
import { I18N_MODE, LANGS_DICT, LANG_MESSAGES, LOADED_LOCALES } from '../lib/constant';
const locale = $env.locale;
const i18n = createI18n({
legacy: false,
locale,
fallbackLocale: LANGS_DICT.EN,
messages: LANG_MESSAGES,
devtools: false,
});
export const setI18nLanguage = (lang: string): string => {
if (i18n.mode === I18N_MODE.LEGACY) {
i18n.global.locale.value = lang as 'zh-CN' | 'en';
} else {
i18n.global.locale.value = lang as 'zh-CN' | 'en';
}
return lang;
};
// 合并公共语言词条
export const mergeCommonMessage = (message: string, lang = locale): void => {
i18n.global.mergeLocaleMessage(lang, message);
};
// 异步加载语言词条
export const loadLanguageAsync = (lang: string): Promise<string> => {
if (!lang) return Promise.reject('lang is undefined');
// 如果语言相同
if (i18n.global.locale.value === lang) {
return Promise.resolve(setI18nLanguage(lang));
}
// 如果语言已经加载
if (LOADED_LOCALES.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang));
}
return import(`../lang/${lang}.json`).then((messages) => {
mergeCommonMessage(messages.default, lang);
LOADED_LOCALES.push(lang);
return setI18nLanguage(lang);
});
};
export default i18n;
================================================
FILE: packages/docs/.vitepress/lang/zh-CN.json
================================================
{
"lang": "简体中文",
"components_totp_1": "生成结果",
"components_totp_2": "请输入 2FA 的 key",
"components_totp_3": "你还没有输入 2FA 的 key",
"components_totp_4": "有效期",
"components_totp_5": "输入的 key 值无效",
"components_totp_6": "2FA 验证"
}
================================================
FILE: packages/docs/.vitepress/langs/cn/index.ts
================================================
import type { DefaultTheme } from 'vitepress';
import { GITHUB } from '../../common/index';
const themeCnConfig: DefaultTheme.Config = {
logo: '/home.svg',
search: {
provider: 'local',
},
nav: [
{ text: '首页', link: '/cn/' },
{ text: '函数', link: '/cn/src/ranuts/' },
{ text: '组件', link: '/cn/src/ranui/' },
{ text: '璀璨', link: '/cn/src/article/design_mode.md' },
],
socialLinks: [{ icon: 'github', link: GITHUB }],
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2022-11-11',
},
// algolia: {
// appId: 'RDX0Y4AQW1',
// apiKey: 'c7b6e28f95335eddc66c5a1b54ad9834',
// indexName: 'chaxus_ran',
// placeholder: 'search',
// },
sidebar: {
'/cn/src/ranuts/': [
{
text: '总览',
link: '/cn/src/ranuts/',
},
{
text: '工具函数',
link: '/cn/src/ranuts/utils/',
collapsed: false,
items: [
{
text: '函数式编程',
collapsed: true,
items: [
{ text: 'debounce - 防抖函数', link: '/cn/src/ranuts/utils/debounce.md' },
{ text: 'throttle - 节流函数', link: '/cn/src/ranuts/utils/throttle.md' },
{ text: 'memoize - 记忆化函数', link: '/cn/src/ranuts/utils/memoize.md' },
{ text: 'noop - 空函数', link: '/cn/src/ranuts/utils/noop.md' },
{ text: 'compose - 组合中间件函数', link: '/cn/src/ranuts/utils/compose.md' },
],
},
{
text: '字符串处理',
collapsed: true,
items: [
{ text: 'md5 - MD5 哈希函数', link: '/cn/src/ranuts/utils/md5.md' },
{ text: 'randomString - 生成随机字符串', link: '/cn/src/ranuts/utils/random_string.md' },
{ text: 'clearBr - 清除空格和换行', link: '/cn/src/ranuts/utils/clear_br.md' },
{ text: 'clearStr - 去除首尾空格和引号', link: '/cn/src/ranuts/utils/clear_str.md' },
{ text: 'strParse - 字符串解析为对象', link: '/cn/src/ranuts/utils/str_parse.md' },
{ text: 'toString - 转换为字符串', link: '/cn/src/ranuts/utils/to_string.md' },
{ text: 'transformText - ArrayBuffer 转文本', link: '/cn/src/ranuts/utils/transform_text.md' },
{ text: 'checkEncoding - 检测字符编码', link: '/cn/src/ranuts/utils/check_encoding.md' },
{
text: 'changeHumpToLowerCase - 驼峰转下划线',
link: '/cn/src/ranuts/utils/change_hump_to_lower_case.md',
},
{ text: 'getMatchingSentences - 提取匹配句子', link: '/cn/src/ranuts/utils/get_matching_sentences.md' },
{ text: 'isString - 判断是否为字符串', link: '/cn/src/ranuts/utils/is_string.md' },
{ text: 'str2Xml - 字符串转 XML', link: '/cn/src/ranuts/utils/str2xml.md' },
],
},
{
text: '对象处理',
collapsed: true,
items: [
{ text: 'merge - 合并对象', link: '/cn/src/ranuts/utils/merge.md' },
{ text: 'isEqual - 深度比较', link: '/cn/src/ranuts/utils/is_equal.md' },
{ text: 'cloneDeep - 深度克隆', link: '/cn/src/ranuts/utils/clone_deep.md' },
{ text: 'querystring - 对象转查询字符串', link: '/cn/src/ranuts/utils/querystring.md' },
{ text: 'filterObj - 过滤对象', link: '/cn/src/ranuts/utils/filter_obj.md' },
{ text: 'formatJson - 格式化 JSON', link: '/cn/src/ranuts/utils/format_json.md' },
],
},
{
text: '数字处理',
collapsed: true,
items: [
{ text: 'range - 限制数字范围', link: '/cn/src/ranuts/utils/range.md' },
{ text: 'mathjs - 精确数字运算', link: '/cn/src/ranuts/utils/mathjs.md' },
{ text: 'perToNum - 百分比转数字', link: '/cn/src/ranuts/utils/per_to_num.md' },
{ text: 'transformNumber - 数字格式化', link: '/cn/src/ranuts/utils/transform_number.md' },
{ text: 'addNumSym - 添加正负号', link: '/cn/src/ranuts/utils/add_num_sym.md' },
],
},
{
text: '颜色处理',
collapsed: true,
items: [
{ text: 'hexToRgb - 十六进制转 RGB', link: '/cn/src/ranuts/utils/hex_to_rgb.md' },
{ text: 'rgbToHex - RGB 转十六进制', link: '/cn/src/ranuts/utils/rgb_to_hex.md' },
{ text: 'randomColor - 生成随机颜色', link: '/cn/src/ranuts/utils/random_color.md' },
],
},
{
text: '时间处理',
collapsed: true,
items: [
{ text: 'timeFormat - 时间格式化', link: '/cn/src/ranuts/utils/time_format.md' },
{ text: 'timestampToTime - 时间戳转 Date', link: '/cn/src/ranuts/utils/timestamp_to_time.md' },
{ text: 'performanceTime - 高精度时间戳', link: '/cn/src/ranuts/utils/performance_time.md' },
],
},
{
text: '设备检测',
collapsed: true,
items: [
{ text: 'isMobile - 判断移动端', link: '/cn/src/ranuts/utils/is_mobile.md' },
{ text: 'isWeiXin - 判断微信浏览器', link: '/cn/src/ranuts/utils/is_weixin.md' },
{ text: 'isClient - 判断客户端环境', link: '/cn/src/ranuts/utils/is_client.md' },
{ text: 'isSafari - 判断 Safari', link: '/cn/src/ranuts/utils/is_safari.md' },
{ text: 'isBangDevice - 判断刘海屏', link: '/cn/src/ranuts/utils/is_bang_device.md' },
{ text: 'currentDevice - 获取设备类型', link: '/cn/src/ranuts/utils/current_device.md' },
],
},
{
text: 'DOM 操作',
collapsed: true,
items: [
{ text: 'addClassToElement - 添加类名', link: '/cn/src/ranuts/utils/add_class_to_element.md' },
{ text: 'removeClassToElement - 移除类名', link: '/cn/src/ranuts/utils/remove_class_to_element.md' },
{
text: 'createDocumentFragment - 创建文档片段',
link: '/cn/src/ranuts/utils/create_document_fragment.md',
},
{ text: 'escapeHtml - 转义 HTML', link: '/cn/src/ranuts/utils/escape_html.md' },
{ text: 'Chain - 链式 DOM 操作', link: '/cn/src/ranuts/utils/chain.md' },
{ text: 'create - 创建 DOM 元素', link: '/cn/src/ranuts/utils/create.md' },
],
},
{
text: '存储',
collapsed: true,
items: [
{ text: 'localStorageGetItem - 获取存储值', link: '/cn/src/ranuts/utils/local_storage.md' },
{ text: 'localStorageSetItem - 设置存储值', link: '/cn/src/ranuts/utils/local_storage.md' },
],
},
{
text: 'URL/Query',
collapsed: true,
items: [
{ text: 'getAllQueryString - 提取查询参数', link: '/cn/src/ranuts/utils/get_all_query_string.md' },
{ text: 'getQuery - 提取查询参数', link: '/cn/src/ranuts/utils/get_query.md' },
{ text: 'encodeUrl - 安全编码 URL', link: '/cn/src/ranuts/utils/encode_url.md' },
{ text: 'appendUrl - 拼接查询参数', link: '/cn/src/ranuts/utils/append_url.md' },
],
},
{
text: 'Cookie',
collapsed: true,
items: [
{ text: 'getCookie - 获取 Cookie', link: '/cn/src/ranuts/utils/get_cookie.md' },
{ text: 'getCookieByName - 正则获取 Cookie', link: '/cn/src/ranuts/utils/get_cookie_by_name.md' },
],
},
{
text: '图片处理',
collapsed: true,
items: [
{ text: 'convertImageToBase64 - 图片转 Base64', link: '/cn/src/ranuts/utils/convert_image_to_base64.md' },
{ text: 'isImageSize - 校验图片尺寸', link: '/cn/src/ranuts/utils/is_image_size.md' },
],
},
{
text: '性能',
collapsed: true,
items: [
{ text: 'getPerformance - 获取性能指标', link: '/cn/src/ranuts/utils/get_performance.md' },
{ text: 'getFrame - 计算帧率', link: '/cn/src/ranuts/utils/get_frame.md' },
{ text: 'getPixelRatio - 获取分辨率比例', link: '/cn/src/ranuts/utils/get_pixel_ratio.md' },
],
},
{
text: '网络',
collapsed: true,
items: [
{ text: 'imageRequest - 测试网络延迟', link: '/cn/src/ranuts/utils/image_request.md' },
{ text: 'networkSpeed - 测试网络速度', link: '/cn/src/ranuts/utils/network_speed.md' },
{ text: 'connection - 获取网络连接信息', link: '/cn/src/ranuts/utils/connection.md' },
],
},
{
text: '浏览器',
collapsed: true,
items: [
{ text: 'getWindow - 获取窗口大小', link: '/cn/src/ranuts/utils/get_window.md' },
{ text: 'getHost - 获取主机地址', link: '/cn/src/ranuts/utils/get_host.md' },
{ text: 'createObjectURL - 创建对象 URL', link: '/cn/src/ranuts/utils/create_object_url.md' },
{ text: 'removeGhosting - 移除拖拽阴影', link: '/cn/src/ranuts/utils/remove_ghosting.md' },
{ text: 'retain - 覆盖后退事件', link: '/cn/src/ranuts/utils/retain.md' },
],
},
{
text: '脚本加载',
collapsed: true,
items: [{ text: 'scriptOnLoad - 动态加载脚本', link: '/cn/src/ranuts/utils/script_on_load.md' }],
},
{
text: '错误处理',
collapsed: true,
items: [
{ text: 'handleConsole - 拦截 console', link: '/cn/src/ranuts/utils/handle_console.md' },
{ text: 'handleError - 全局错误处理', link: '/cn/src/ranuts/utils/handle_error.md' },
{ text: 'handleFetchHook - 拦截 fetch', link: '/cn/src/ranuts/utils/handle_fetch_hook.md' },
],
},
{
text: '其他',
collapsed: true,
items: [
{ text: 'TOTP - 一次性密码生成器', link: '/cn/src/ranuts/utils/totp.md' },
{ text: 'OCR - 文字识别', link: '/cn/src/ranuts/utils/ocr.md' },
{ text: 'createSignal - 创建响应式信号', link: '/cn/src/ranuts/utils/create_signal.md' },
{ text: 'setMime - 设置 MIME 类型', link: '/cn/src/ranuts/utils/set_mime.md' },
{ text: 'getExtensions - 获取扩展名', link: '/cn/src/ranuts/utils/get_extensions.md' },
{ text: 'setAttributeByGlobal - 全局属性', link: '/cn/src/ranuts/utils/set_attribute_by_global.md' },
{ text: 'SyncHook - 同步事件钩子', link: '/cn/src/ranuts/utils/sync_hook.md' },
{ text: 'durationHandler - 延迟执行', link: '/cn/src/ranuts/utils/duration_handler.md' },
{ text: 'task - 统计执行时间', link: '/cn/src/ranuts/utils/task.md' },
],
},
],
},
{
text: '文件操作',
collapsed: true,
items: [
{ text: 'writeFile - 写入文件', link: '/cn/src/ranuts/file/write_file.md' },
{ text: 'readFile - 读取文件', link: '/cn/src/ranuts/file/read_file.md' },
{ text: 'readDir - 读取目录', link: '/cn/src/ranuts/file/read_dir.md' },
{ text: 'watchFile - 监听文件变化', link: '/cn/src/ranuts/file/watch_file.md' },
{ text: 'queryFileInfo - 查询文件信息', link: '/cn/src/ranuts/file/file_info.md' },
{ text: 'appendFile - 追加文件内容', link: '/cn/src/ranuts/file/append_file.md' },
],
},
{
text: '事件系统',
collapsed: true,
items: [{ text: 'EventEmitter - 发布订阅模式', link: '/cn/src/ranuts/mode/subscribe.md' }],
},
{
text: 'MIME 类型',
collapsed: true,
items: [{ text: 'getMime - 获取 MIME 类型', link: '/cn/src/ranuts/mime_type/mime_type.md' }],
},
{
text: '其他',
collapsed: true,
items: [
{ text: '二叉树', link: '/cn/src/ranuts/binary_tree/index.md' },
{ text: '打包器', link: '/cn/src/ranuts/bundler/index.md' },
],
},
],
'/cn/src/ranui/': [
{
text: 'Overview 总览',
link: '/cn/src/ranui/',
},
{
text: '通用',
items: [
{ text: 'Button 按钮', link: '/cn/src/ranui/button/' },
{ text: 'Icon 图标', link: '/cn/src/ranui/icon/' },
{ text: 'Loading 加载中', link: '/cn/src/ranui/loading/' },
],
},
{
text: '数据展示',
items: [
{ text: 'Image 图片', link: '/cn/src/ranui/image/' },
{ text: 'Math 数学公式', link: '/cn/src/ranui/math/' },
{ text: 'CheckBox 多选框', link: '/cn/src/ranui/checkbox/' },
{ text: 'Tabs 标签页', link: '/cn/src/ranui/tabs/' },
{ text: 'Preview 预览', link: '/cn/src/ranui/preview/' },
{ text: 'Radar 雷达图', link: '/cn/src/ranui/radar/' },
{ text: 'Select 选择框', link: '/cn/src/ranui/select/' },
{ text: 'Player 视频播放器', link: '/cn/src/ranui/player/' },
{ text: 'Progress 进度条', link: '/cn/src/ranui/progress/' },
{ text: 'Popover 气泡卡片', link: '/cn/src/ranui/popover/' },
],
},
{
text: '数据录入',
items: [{ text: 'Input 输入框', link: '/cn/src/ranui/input/' }],
},
{
text: '反馈',
items: [
{ text: 'Message 全局提示', link: '/cn/src/ranui/message/' },
{ text: 'Skeleton 骨架屏', link: '/cn/src/ranui/skeleton/' },
// { text: 'Modal 对话框', link: '/src/ranui/modal/' },
],
},
],
'/cn/src/article/': [
{
items: [
{ text: '23 种经典设计模式', link: '/cn/src/article/design_mode.md' },
{
text: '函数式编程',
link: '/cn/src/article/functional_programming.md',
},
{
text: 'web 文档预览方案',
link: '/cn/src/article/doc_preview.md',
},
{
text: 'Web 视频加密动态方案',
link: '/cn/src/article/video.md',
},
{
text: '可视化渲染引擎',
link: '/cn/src/article/visual.md',
},
{
text: '排序算法',
link: '/cn/src/article/sort/index.md',
collapsed: true,
items: [
{ text: '冒泡排序', link: '/cn/src/article/sort/bubble/' },
{ text: '选择排序', link: '/cn/src/article/sort/select/' },
{ text: '插入排序', link: '/cn/src/article/sort/insert/' },
{ text: '希尔排序', link: '/cn/src/article/sort/shell/' },
{ text: '归并排序', link: '/cn/src/article/sort/merge/' },
{ text: '快速排序', link: '/cn/src/article/sort/quick/' },
{ text: '堆排序', link: '/cn/src/article/sort/heap/' },
{ text: '计数排序', link: '/cn/src/article/sort/count/' },
{ text: '桶排序', link: '/cn/src/article/sort/bucket/' },
{ text: '基数排序', link: '/cn/src/article/sort/radix/' },
],
},
{
text: '数学',
collapsed: true,
items: [{ text: '线性代数', link: '/cn/src/article/math/linear_algebra.md' }],
},
],
},
],
},
};
export { themeCnConfig };
================================================
FILE: packages/docs/.vitepress/langs/en/index.ts
================================================
import type { DefaultTheme } from 'vitepress';
import { GITHUB } from '../../common/index';
const themeEnConfig: DefaultTheme.Config = {
logo: '/home.svg',
search: {
provider: 'local',
},
nav: [
{ text: 'Home', link: '/' },
{ text: 'Function', link: '/src/ranuts/' },
{ text: 'Component', link: '/src/ranui/' },
{ text: 'Article', link: '/src/article/design_mode.md' },
],
socialLinks: [{ icon: 'github', link: GITHUB }],
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2022-11-11',
},
// algolia: {
// appId: 'RDX0Y4AQW1',
// apiKey: 'c7b6e28f95335eddc66c5a1b54ad9834',
// indexName: 'chaxus_ran',
// placeholder: 'search',
// },
sidebar: {
'/src/ranuts/': [
{
text: 'Overview',
link: '/src/ranuts/',
},
{
text: 'Utility Functions',
link: '/src/ranuts/utils/',
collapsed: false,
items: [
{
text: 'Functional Programming',
collapsed: true,
items: [
{ text: 'debounce - Debounce function', link: '/src/ranuts/utils/debounce.md' },
{ text: 'throttle - Throttle function', link: '/src/ranuts/utils/throttle.md' },
{ text: 'memoize - Memoization function', link: '/src/ranuts/utils/memoize.md' },
{ text: 'noop - No-op function', link: '/src/ranuts/utils/noop.md' },
{ text: 'compose - Compose middleware', link: '/src/ranuts/utils/compose.md' },
],
},
{
text: 'String Processing',
collapsed: true,
items: [
{ text: 'md5 - MD5 hash function', link: '/src/ranuts/utils/md5.md' },
{ text: 'randomString - Generate random string', link: '/src/ranuts/utils/random_string.md' },
{ text: 'clearBr - Remove spaces and line breaks', link: '/src/ranuts/utils/clear_br.md' },
{ text: 'clearStr - Remove leading/trailing spaces', link: '/src/ranuts/utils/clear_str.md' },
{ text: 'strParse - Parse string to object', link: '/src/ranuts/utils/str_parse.md' },
{ text: 'toString - Convert to string', link: '/src/ranuts/utils/to_string.md' },
{ text: 'transformText - ArrayBuffer to text', link: '/src/ranuts/utils/transform_text.md' },
{ text: 'checkEncoding - Detect encoding', link: '/src/ranuts/utils/check_encoding.md' },
{
text: 'changeHumpToLowerCase - Camel to snake',
link: '/src/ranuts/utils/change_hump_to_lower_case.md',
},
{ text: 'getMatchingSentences - Extract sentences', link: '/src/ranuts/utils/get_matching_sentences.md' },
{ text: 'isString - Check if string', link: '/src/ranuts/utils/is_string.md' },
{ text: 'str2Xml - String to XML', link: '/src/ranuts/utils/str2xml.md' },
],
},
{
text: 'Object Processing',
collapsed: true,
items: [
{ text: 'merge - Merge objects', link: '/src/ranuts/utils/merge.md' },
{ text: 'isEqual - Deep comparison', link: '/src/ranuts/utils/is_equal.md' },
{ text: 'cloneDeep - Deep clone', link: '/src/ranuts/utils/clone_deep.md' },
{ text: 'querystring - Object to query string', link: '/src/ranuts/utils/querystring.md' },
{ text: 'filterObj - Filter object', link: '/src/ranuts/utils/filter_obj.md' },
{ text: 'formatJson - Format JSON', link: '/src/ranuts/utils/format_json.md' },
],
},
{
text: 'Number Processing',
collapsed: true,
items: [
{ text: 'range - Clamp number range', link: '/src/ranuts/utils/range.md' },
{ text: 'mathjs - Precise calculation', link: '/src/ranuts/utils/mathjs.md' },
{ text: 'perToNum - Percentage to number', link: '/src/ranuts/utils/per_to_num.md' },
{ text: 'transformNumber - Format number', link: '/src/ranuts/utils/transform_number.md' },
{ text: 'addNumSym - Add sign to number', link: '/src/ranuts/utils/add_num_sym.md' },
],
},
{
text: 'Color Processing',
collapsed: true,
items: [
{ text: 'hexToRgb - Hex to RGB', link: '/src/ranuts/utils/hex_to_rgb.md' },
{ text: 'rgbToHex - RGB to hex', link: '/src/ranuts/utils/rgb_to_hex.md' },
{ text: 'randomColor - Generate random color', link: '/src/ranuts/utils/random_color.md' },
],
},
{
text: 'Time Processing',
collapsed: true,
items: [
{ text: 'timeFormat - Format time', link: '/src/ranuts/utils/time_format.md' },
{ text: 'timestampToTime - Timestamp to Date', link: '/src/ranuts/utils/timestamp_to_time.md' },
{ text: 'performanceTime - High precision timestamp', link: '/src/ranuts/utils/performance_time.md' },
],
},
{
text: 'Device Detection',
collapsed: true,
items: [
{ text: 'isMobile - Check mobile device', link: '/src/ranuts/utils/is_mobile.md' },
{ text: 'isWeiXin - Check WeChat browser', link: '/src/ranuts/utils/is_weixin.md' },
{ text: 'isClient - Check client environment', link: '/src/ranuts/utils/is_client.md' },
{ text: 'isSafari - Check Safari browser', link: '/src/ranuts/utils/is_safari.md' },
{ text: 'isBangDevice - Check notch device', link: '/src/ranuts/utils/is_bang_device.md' },
{ text: 'currentDevice - Get device type', link: '/src/ranuts/utils/current_device.md' },
],
},
{
text: 'DOM Manipulation',
collapsed: true,
items: [
{ text: 'addClassToElement - Add class', link: '/src/ranuts/utils/add_class_to_element.md' },
{ text: 'removeClassToElement - Remove class', link: '/src/ranuts/utils/remove_class_to_element.md' },
{
text: 'createDocumentFragment - Create fragment',
link: '/src/ranuts/utils/create_document_fragment.md',
},
{ text: 'escapeHtml - Escape HTML', link: '/src/ranuts/utils/escape_html.md' },
{ text: 'Chain - Chainable DOM', link: '/src/ranuts/utils/chain.md' },
{ text: 'create - Create DOM element', link: '/src/ranuts/utils/create.md' },
],
},
{
text: 'Storage',
collapsed: true,
items: [
{ text: 'localStorageGetItem - Get storage', link: '/src/ranuts/utils/local_storage.md' },
{ text: 'localStorageSetItem - Set storage', link: '/src/ranuts/utils/local_storage.md' },
],
},
{
text: 'URL/Query',
collapsed: true,
items: [
{ text: 'getAllQueryString - Extract query', link: '/src/ranuts/utils/get_all_query_string.md' },
{ text: 'getQuery - Extract query', link: '/src/ranuts/utils/get_query.md' },
{ text: 'encodeUrl - Encode URL safely', link: '/src/ranuts/utils/encode_url.md' },
{ text: 'appendUrl - Append query params', link: '/src/ranuts/utils/append_url.md' },
],
},
{
text: 'Cookie',
collapsed: true,
items: [
{ text: 'getCookie - Get cookie', link: '/src/ranuts/utils/get_cookie.md' },
{ text: 'getCookieByName - Get cookie by regex', link: '/src/ranuts/utils/get_cookie_by_name.md' },
],
},
{
text: 'Image Processing',
collapsed: true,
items: [
{ text: 'convertImageToBase64 - Image to Base64', link: '/src/ranuts/utils/convert_image_to_base64.md' },
{ text: 'isImageSize - Validate image size', link: '/src/ranuts/utils/is_image_size.md' },
],
},
{
text: 'Performance',
collapsed: true,
items: [
{ text: 'getPerformance - Get performance metrics', link: '/src/ranuts/utils/get_performance.md' },
{ text: 'getFrame - Calculate frame rate', link: '/src/ranuts/utils/get_frame.md' },
{ text: 'getPixelRatio - Get resolution ratio', link: '/src/ranuts/utils/get_pixel_ratio.md' },
],
},
{
text: 'Network',
collapsed: true,
items: [
{ text: 'imageRequest - Test network latency', link: '/src/ranuts/utils/image_request.md' },
{ text: 'networkSpeed - Test network speed', link: '/src/ranuts/utils/network_speed.md' },
{ text: 'connection - Get network info', link: '/src/ranuts/utils/connection.md' },
],
},
{
text: 'Browser',
collapsed: true,
items: [
{ text: 'getWindow - Get window size', link: '/src/ranuts/utils/get_window.md' },
{ text: 'getHost - Get host address', link: '/src/ranuts/utils/get_host.md' },
{ text: 'createObjectURL - Create object URL', link: '/src/ranuts/utils/create_object_url.md' },
{ text: 'removeGhosting - Remove drag shadow', link: '/src/ranuts/utils/remove_ghosting.md' },
{ text: 'retain - Override back event', link: '/src/ranuts/utils/retain.md' },
],
},
{
text: 'Script Loading',
collapsed: true,
items: [{ text: 'scriptOnLoad - Dynamic script loading', link: '/src/ranuts/utils/script_on_load.md' }],
},
{
text: 'Error Handling',
collapsed: true,
items: [
{ text: 'handleConsole - Intercept console', link: '/src/ranuts/utils/handle_console.md' },
{ text: 'handleError - Global error handling', link: '/src/ranuts/utils/handle_error.md' },
{ text: 'handleFetchHook - Intercept fetch', link: '/src/ranuts/utils/handle_fetch_hook.md' },
],
},
{
text: 'Others',
collapsed: true,
items: [
{ text: 'TOTP - One-time password generator', link: '/src/ranuts/utils/totp.md' },
{ text: 'OCR - Text recognition', link: '/src/ranuts/utils/ocr.md' },
{ text: 'createSignal - Create reactive signal', link: '/src/ranuts/utils/create_signal.md' },
{ text: 'setMime - Set MIME type', link: '/src/ranuts/utils/set_mime.md' },
{ text: 'getExtensions - Get extensions', link: '/src/ranuts/utils/get_extensions.md' },
{ text: 'setAttributeByGlobal - Global attribute', link: '/src/ranuts/utils/set_attribute_by_global.md' },
{ text: 'SyncHook - Sync event hook', link: '/src/ranuts/utils/sync_hook.md' },
{ text: 'durationHandler - Delayed execution', link: '/src/ranuts/utils/duration_handler.md' },
{ text: 'task - Statistical execution time', link: '/src/ranuts/utils/task.md' },
],
},
],
},
{
text: 'File Operations',
collapsed: true,
items: [
{ text: 'writeFile - Write to file', link: '/src/ranuts/file/write_file.md' },
{ text: 'readFile - Read file', link: '/src/ranuts/file/read_file.md' },
{ text: 'readDir - Read directory', link: '/src/ranuts/file/read_dir.md' },
{ text: 'watchFile - Watch file changes', link: '/src/ranuts/file/watch_file.md' },
{ text: 'queryFileInfo - Query file info', link: '/src/ranuts/file/file_info.md' },
{ text: 'appendFile - Append to file', link: '/src/ranuts/file/append_file.md' },
],
},
{
text: 'Event System',
collapsed: true,
items: [{ text: 'EventEmitter - Publish-subscribe', link: '/src/ranuts/mode/subscribe.md' }],
},
{
text: 'MIME Type',
collapsed: true,
items: [{ text: 'getMime - Get MIME type', link: '/src/ranuts/mime_type/mime_type.md' }],
},
{
text: 'Others',
collapsed: true,
items: [
{ text: 'Binary Tree', link: '/src/ranuts/binary_tree/index.md' },
{ text: 'Bundler', link: '/src/ranuts/bundler/index.md' },
],
},
],
'/src/ranui/': [
{
text: 'Overview ',
link: '/src/ranui/',
},
{
text: 'Common',
items: [
{ text: 'Button', link: '/src/ranui/button/' },
{ text: 'Icon', link: '/src/ranui/icon/' },
{ text: 'Loading', link: '/src/ranui/loading/' },
],
},
{
text: 'Data Presentation',
items: [
{ text: 'Image', link: '/src/ranui/image/' },
{ text: 'Math', link: '/src/ranui/math' },
{ text: 'CheckBox', link: '/src/ranui/checkbox/' },
{ text: 'Tabs', link: '/src/ranui/tabs/' },
{ text: 'Preview', link: '/src/ranui/preview/' },
{ text: 'Radar', link: '/src/ranui/radar/' },
{ text: 'Select', link: '/src/ranui/select/' },
{ text: 'Player', link: '/src/ranui/player/' },
{ text: 'Progress', link: '/src/ranui/progress/' },
{ text: 'Popover', link: '/src/ranui/popover/' },
],
},
{
text: 'Data Entry',
items: [{ text: 'Input', link: '/src/ranui/input/' }],
},
{
text: 'Feedback',
items: [
{ text: 'Message', link: '/src/ranui/message/' },
{ text: 'Skeleton', link: '/src/ranui/skeleton/' },
// { text: 'Modal 对话框', link: '/src/ranui/modal/' },
],
},
],
'/src/article/': [
{
items: [
{
text: '23 classic design patterns',
link: '/src/article/design_mode.md',
},
{
text: 'Functional programming',
link: '/src/article/functional_programming.md',
},
{
text: 'Sorting algorithm',
link: '/src/article/sort/index.md',
collapsed: true,
items: [
{ text: 'bubble sort', link: '/src/article/sort/bubble/' },
{ text: 'selection sort', link: '/src/article/sort/select/' },
{ text: 'insertion sort', link: '/src/article/sort/insert/' },
{ text: 'shell sort', link: '/src/article/sort/shell/' },
{ text: 'Merge sort', link: '/src/article/sort/merge/' },
{ text: 'Quick sort', link: '/src/article/sort/quick/' },
{ text: 'Heap Sort', link: '/src/article/sort/heap/' },
{ text: 'Counting sort', link: '/src/article/sort/count/' },
{ text: 'Bucket sort', link: '/src/article/sort/bucket/' },
{ text: 'Radix sort', link: '/src/article/sort/radix/' },
],
},
],
},
],
},
};
export { themeEnConfig };
================================================
FILE: packages/docs/.vitepress/lib/constant.ts
================================================
export enum INPUT_STATUS {
NORMAL = 'normal',
ERROR = 'error',
WARNING = 'warning',
}
// 支持语言包字典
export enum LANGS_DICT {
EN = 'en', // 英文
ZH_CN = 'zh-CN', // 简体中文
}
// localStorage 中的多语言标识
export const RAN_CHAXUS_LANG = 'ran_chaxus_lang';
export const LOADED_LOCALES: string[] = [];
export const LANG_MESSAGES = {
'zh-CN': {
lang: '简体中文',
},
en: {
lang: 'English',
},
};
export enum I18N_MODE {
LEGACY = 'legacy',
}
export const PWA_INSTALL_ID = 'PWA_INSTALL_ID';
export const PWA_ELEMENT_NAME = 'pwa-install';
export const MANIFEST_PATH_ROOT = '/ran/manifest.json';
================================================
FILE: packages/docs/.vitepress/plugins/env.ts
================================================
import { currentDevice, isBangDevice, isMobile, isWeiXin } from 'ranuts/utils';
import type { App } from 'vue';
import type { CurrentDevice } from 'ranuts/utils';
import { LANGS_DICT } from '../lib/constant';
// env 信息
const isDev = process.env.NODE_ENV !== 'production';
// debug 开关信息
// const { debug = '' } = getAllQueryString() || {};
export interface Env {
isDev: boolean;
locale: LANGS_DICT | string;
currentDevice: CurrentDevice;
isWeiXin: boolean;
isMobile: boolean;
isBang: boolean;
}
export const $env: Env = {
isDev,
locale: LANGS_DICT.EN,
currentDevice: currentDevice(),
isWeiXin: isWeiXin(),
isMobile: isMobile(),
isBang: isBangDevice(), // 是否是刘海机型
// theme: localStorage.getItem("ran-chaxus-theme")
};
export default {
install: (app: App): void => {
app.config.globalProperties.$env = $env;
app.provide('$env', $env);
},
};
================================================
FILE: packages/docs/.vitepress/theme/index.ts
================================================
import DefaultTheme from 'vitepress/theme';
import type { EnhanceAppContext } from 'vitepress';
import { localStorageGetItem, setAttributeByGlobal } from 'ranuts/utils';
import env from '../plugins/env';
import TOTP from '../components/TOTP.vue';
import Layout from '../components/Layout.vue';
import i18n, { loadLanguageAsync } from '../lang';
import { LANGS_DICT, MANIFEST_PATH_ROOT, PWA_ELEMENT_NAME, PWA_INSTALL_ID, RAN_CHAXUS_LANG } from '../lib/constant';
import './styles/index.less';
import './styles/vars.less';
import './tailwind.min.css';
import 'ranui/style';
declare global {
interface ImportMeta {
env: {
SSR: boolean;
};
}
}
/**
* @description: pwa 引导安装
*/
const pwaInstall = () => {
import('@khmyznikov/pwa-install').then(() => {
let pwaInstall = document.getElementById(PWA_INSTALL_ID);
if (!pwaInstall) {
pwaInstall = document.createElement(PWA_ELEMENT_NAME);
pwaInstall.setAttribute('manifest-url', MANIFEST_PATH_ROOT);
pwaInstall.setAttribute('id', PWA_INSTALL_ID);
document.body.appendChild(pwaInstall);
}
});
};
export default {
extends: DefaultTheme,
// Layout,
enhanceApp({ app }: EnhanceAppContext): void {
if (!import.meta.env.SSR) {
import('ranui');
import('@ranui/preview');
pwaInstall();
}
app.use(env);
const locale = localStorageGetItem(RAN_CHAXUS_LANG) || LANGS_DICT.EN;
loadLanguageAsync(locale)
.then(() => {
setAttributeByGlobal('__VUE_PROD_DEVTOOLS__', false);
app.use(i18n);
app.component('Layout', Layout);
app.component('TOTP', TOTP);
})
.catch((error) => {
console.log('error', error);
});
},
};
================================================
FILE: packages/docs/.vitepress/theme/styles/index.less
================================================
#app .VPNavBar {
border-bottom: 1px solid var(--vp-c-divider-light);
}
#app .VPHomeHero {
margin-top: 20px;
margin-bottom: 35px;
.main {
margin-top: -40px;
}
}
#app .VPNavBarTitle {
.title {
color: transparent;
background: var(--vp-home-hero-name-background);
-webkit-background-clip: text;
}
}
.font-icon {
padding: 2px 8px;
border-radius: 4px;
display: inline-block;
background-color: var(--vp-c-gray-light-4);
}
.dark .font-icon {
background-color: var(--vp-c-bg);
}
p img {
margin-top: 2px;
}
@media (max-width: 960px) {
#app .image {
margin-top: -75px;
}
#app .VPHomeHero {
margin-bottom: 5px;
.main {
margin-top: 50px;
}
}
}
@media (min-width: 960px) {
}
================================================
FILE: packages/docs/.vitepress/theme/styles/vars.less
================================================
/**
* Colors
* -------------------------------------------------------------------------- */
:root {
--vp-c-brand: #646cff;
--vp-c-brand-light: #747bff;
--vp-c-brand-lighter: #9499ff;
--vp-c-brand-lightest: #bcc0ff;
--vp-c-brand-dark: #535bf2;
--vp-c-brand-darker: #454ce1;
--vp-c-brand-dimm: rgba(100, 108, 255, 0.08);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-text: #fff;
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-alt-hover-text: var(--vp-c-brand);
--vp-button-brand-hover-bg: var(--vp-c-brand-lighter);
--vp-button-brand-hover-border: var(--vp-c-brand-lighter);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-active-text: var(--vp-c-text-dark-1);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);
--vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%);
--vp-home-hero-image-filter: blur(40px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(72px);
}
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-darker);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
.dark {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-lightest);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand) !important;
}
/**
* VitePress: Custom fix
* -------------------------------------------------------------------------- */
/*
Use lighter colors for links in dark mode for a11y.
Also specify some classes twice to have higher specificity
over scoped class data attribute.
*/
.dark .vp-doc a,
.dark .vp-doc a > code,
.dark .VPNavBarMenuLink.VPNavBarMenuLink:hover,
.dark .VPNavBarMenuLink.VPNavBarMenuLink.active,
.dark .link.link:hover,
.dark .link.link.active,
.dark .edit-link-button.edit-link-button,
.dark .pager-link .title {
color: var(--vp-c-brand-lighter);
}
.dark .vp-doc a:hover,
.dark .vp-doc a > code:hover {
color: var(--vp-c-brand-lightest);
opacity: 1;
}
/* Transition by color instead of opacity */
.dark .vp-doc .custom-block a {
transition: color 0.25s;
}
================================================
FILE: packages/docs/.vitepress/theme/theme.less
================================================
:root {
--bg-color: #f5f6f6;
--front-bg-color-2: #fafafa;
--front-bg-color-1: #ffffff;
--front-bg-color1: #ffffff;
--front-bg-color: #f5f6f6;
--tag-bg-color: #f5f6f6;
--line-color: #eaebec;
--tag-border-color: #c7cacc;
--text-color-3: #afb3b6;
--text-color-2: #82888d;
--text-color-2-raw: 130, 136, 141;
--text-color-1-supplement: #464f56;
--text-color-1: #000000;
--link-text-color: #37a0ff;
--environment-text-color-3: #ffffff;
--environment-text-color-2: #f5f6f6;
--environment-text-color-1: #1f2a32;
--wtt-brand-color: #5622cf;
--brand-color: #37a0ff;
--brand-color-raw: 55, 160, 255;
--brand-color-2: #ff4040;
--brand-color-3: #ffc700;
--up-color: #ff5000;
--down-color: #00b99a;
--list-bg-color: #ffffff;
--green-color: #00b99a;
--red-color: #ff5000;
}
:root[theme='dark'] {
--bg-color: #07121c;
--front-bg-color-2: #141f28;
--front-bg-color-1: #1a252e;
--front-bg-color1: #1a252e;
--front-bg-color: #2a343c;
--tag-bg-color: #2a343c;
--line-color: #384149;
--tag-border-color: #424b53;
--text-color-3: #61686e;
--text-color-2: #82888d;
--text-color-2-raw: 130, 136, 141;
--text-color-1-supplement: #cfd1d3;
--text-color-1: #ffffff;
--link-text-color: #37a0ff;
--environment-text-color-3: #ffffff;
--environment-text-color-2: #f5f6f6;
--environment-text-color-1: #1f2a32;
--wtt-brand-color: #5622cf;
--brand-color: #37a0ff;
--brand-color-2: #ff4040;
--brand-color-3: #ffc700;
--up-color: #ff5000;
--down-color: #00b99a;
--list-bg-color: #2a343c;
--green-color: #00b99a;
--red-color: #ff5000;
}
================================================
FILE: packages/docs/bin/build.sh
================================================
#!/bin/bash
# 更新 service work的版本号
version=$(date +%s)
# 将版本号写入 variable 目录下 SERVICE_WORK_VERSION.ts
SERVICE_WORK_VERSION="./variable/SERVICE_WORK_VERSION.ts"
echo "export const SERVICE_WORK_VERSION = \"$version\"" > $SERVICE_WORK_VERSION
# 执行 ssg 构建命令
bin=./node_modules/.bin
$bin/vitepress build
# 开启调试模式
# set -x
# 指定输出的目录
dir="./.vitepress/dist"
# 生成的目标文件
target="./.vitepress/dist/sw.js"
# 改名
mv "$target" "./.vitepress/dist/sw$version.js"
target="./.vitepress/dist/sw$version.js"
# 创建一个临时文件
tmpfile=$(mktemp)
# 将目录 dir 下的文件名追加到临时文件中
find "$dir" -type f > "$tmpfile"
# service worker中生成
# SERVICE_WORK_CACHE_FILE_PATHS(根据打包后生成的文件来生成)
# VERSION (时间戳)
# 的临时文件
SERVICE_WORK_VARABLE="./.vitepress/dist/sw-file.js"
# 拼接字符串
echo "const SERVICE_WORK_CACHE_FILE_PATHS = [" > "$SERVICE_WORK_VARABLE"
# 根路径
ran="/ran"
while read -r file; do
# if [[ $file != *".DS_Store"* ]]; then
str="${file##./.vitepress/dist}"
echo "\"$ran$str\"," >> "$SERVICE_WORK_VARABLE"
# fi
done < "$tmpfile"
# 拼接字符串
echo "];" >> "$SERVICE_WORK_VARABLE"
# 更新 sw 的版本号
echo "const VERSION = \"$version\";" >> "$SERVICE_WORK_VARABLE"
# 删除临时文件
rm "$tmpfile"
tmpfile=$(mktemp)
cat "$SERVICE_WORK_VARABLE" >> "$tmpfile"
cat "$target" >> "$tmpfile"
mv "$tmpfile" "$target"
rm "$SERVICE_WORK_VARABLE"
# # 打印完成消息
echo "service work file paths have been generate for $target"
# 关闭调试模式
# set +x
================================================
FILE: packages/docs/cn/index.md
================================================
---
layout: home
title: Home
hero:
name: ran
text: 风起于青萍之末
tagline: A ship in harbor is safe, but that is not what ships are built for.
image:
src: /home.svg
alt: logo
actions:
- theme: alt
text: 更多详情
link: https://github.com/chaxus/ran
- theme: alt
text: 访问我的 GitHub
link: https://github.com/chaxus/ran
features:
- icon: ⚡️
title: 记录
details: 每段旅程都有终点
- icon: 🛠️
title: 解决
details: 无法衡量,无法改进
- icon: 🖖
title: 分享
details: 一个人可以走得很快,一群人可以走的很远
---
================================================
FILE: packages/docs/cn/src/article/ai/index.md
================================================
# Prompt
## System Prompt
用来描述 AI 的角色,性格,背景知识,语气等,总之只要不是用户直接说出来的内容,都可以放到 System Prompt 里面。
## User Prompt
用户直接发送给 AI 的内容。
每次用户发送 User Prompt 的时候,系统会自动把 System Prompt 也一起发起 AI 模型,这样就会显得非常自然。
但到了这个程度,AI 也只是一个聊天机器人,只能问问题,然后 AI 模型去回复问题。
那么如何让 AI 模型去自动的执行一些任务呢?这时候,Agent 就出现了。
# Agent
比如期望用 AI 来管理一些文件,那么得先写好一些文件管理函数:
- list_file 列出目录下的所有文件
- read_file 读取文件的内容
然后把这些函数及其他们的功能描述,使用方法,注册到 Agent 中。
Agent 会根据这些信息,生成一个 System Prompt,告诉 AI 模型,用户给了哪些工具,能够做什么。
以及 AI 使用他们应该返回什么样的格式。
当用户在发送 User Prompt 的时候,连同 System Prompt,一起发送给 AI 模型。
如果 AI 模型足够聪明,就会返回一个格式:需要调用某个函数,比如 list_file 给 Agent。
Agent 解析之后,就会调用对应的函数,然后把结果再给 AI,AI 再根据 Agent 返回的结果,再决定下一步去做什么操作。
这个过程就这样反复,直到任务完成为止。
最后,把这种在 AI 模型,提供的工具 (list_file,read_file),和最终用户之间传话的工具,就叫 AI Agent。
这些提供给 AI Agent 调用的函数,或者服务,就叫 Agent Tool。
但这样可能存在一个问题,虽然我们在 System Prompt 里面描述和规定了 AI 应该用什么格式进行返回,但 AI 模型说到底是一个概率模型。还是有可能返回的格式不对。
一般的 AI Agent 会判断,如果 AI 模型返回的格式不对,会自动进行重试。面对这种场景,FunctionCalling 就出现了。
# FunctionCalling
核心作用就是统一格式,规范描述,比如上面的 System Prompt,使用自然语言描述的,AI 看的懂就行。
FunctionCalling 则对这些描述进行了标准化,每一个 Tool 都用一个 json 来定义,比如:
```json
{
"name": "list_file",
"desc": "列出目录下的所有文件",
"params": {
"path": "str"
}
}
```
然后这些字段也从 System Prompt 中剥离了出来,这样,所有的工具定义,描述,和返回都放在了相同的地方。这样 AI 使用工具时,也会遵循相同 json 格式进行回复。于是人们就可以更加有针对性的训练 AI 模型。甚至在这种情况下,如果 AI 依然返回了错误的回复,因为这种返回的格式是固定的,AI 服务端自己就能检测到,然后进行重试。这样用户根本感觉不到,降低了用户端的开发难度,同时也节约了重试的 token 成本。
但 FunctionCalling 也有自己的问题,那就是没有统一的标准。目前每家大厂的 API 格式都不太一样。甚至还有一些模型,不支持 FunctionCalling,所以,要写一个通用的 AI Agent,还是挺麻烦的。
因此 FunctionCalling 和 System Prompt 这两种方式,在市面上都是并存的。
以上都是 AI Agent 如何和 AI 模型之间的通信,那么 Agent Tool 和 Agent 是怎么通信的呢。
# MCP
一般都是把 Agent 和 Agent Tool 写到一个程序里,这样就能直接调用,搞定。
但后来人们发现,有些 Agent Tool 还是挺通用的,比如浏览网页的功能,每个 Agent 都需要,那么总不能在每个 Agent 里面都拷贝一份吧。于是,就想到来一个办法:
把 Tool 做成一个服务,进行统一的托管。让所有的 Agent 都来调用,这个过程,就是 MCP。
MCP 是一个通信协议,专门用来规范 Agent 和 Tool 服务之间是怎么交互的。
运行 Tool 的服务叫 MCP Server,调用它的 Agent 叫 MCP Client。
MCP 规定了 MCP Server 如何和 MCP Client 进行通信,以及 MCP Server 要提供哪些接口,比如查询 MCP Server 有哪些接口,接口的功能,描述,如何使用。除了普通的 Tool 这种函数的调用形式。
MCP 也可以直接提供数据,提供文件读取的服务 Resources,或者为 Agent 提供提示词的模版叫 Prompt。
MCP Server 既可以和 Agent 跑在同一台机器上,通过标准输入输出进行通信,也可以部署在网络上,通过 http 进行通信。
虽然 MCP 是为了 AI 而定制出来的标准,但实际上,MCP 本身和 AI 模型没有关系,它并不关心 Agent 用的是哪个模型,MCP 只负责帮 Agent 管理工具,资源和提示词。
最后,总结一下全部的流程:
用户 --> 发送消息给 Agent,Agent(MCP Client)调用 MCP Server 的函数,并把结果一起给 AI 模型。
AI 模型通过 FunctionCalling 或者普通回复的方式,产生调用 Tool 的请求,Agent 收到这个请求后,通过 MCP 协议去调用 MCP Server 的工具。将结果返回给 Agent,Agent 再把结果给 AI 模型,AI 模型再把最终结果,返回个 Agent,Agent 再发送给用户。
# 写一个 Agent
Agent 是一个在用户,AI 模型,工具函数之间进行传话的程序。
```mermaid
sequenceDiagram
Tools->>Agent: 将 Tools 里的函数注册到 Agent,让 Agent 知道有哪些工具函数可以使用
User->>Agent: 将问题发送给 Agent
Agent->>AI: 用户的问题是 User Prompt,还有将工具函数信息通过 System Prompt 或者 FunctionCalling 的方式告诉 AI 模型
AI->>Agent: 思考用户的问题,并返回响应的指令,告诉 Agent 应该执行 Tools 中的哪些方法。
Agent->>Tools: 使用 Tools 中的方法,并获得结果
Agent->>AI: 将结果告诉给 AI 模型,AI 模型继续分析问题,看是否需要继续调用 Agent,直到结束。
AI->>Agent: 告诉 Agent 思考过程结束,并将结果发送给 Agent。
Agent->>User: 将最终结果给用户输出。
```
简单来说,就是下面这种方式
```mermaid
graph TD
customer[用户] --> Agent
Agent --> AI
Tools[工具函数] --> Agent
Agent --> customer[用户]
Agent --> Tools[工具函数]
Agent --> AI
```
================================================
FILE: packages/docs/cn/src/article/ast_parse/tokenizer.md
================================================
# Abstract Syntax Tree
## 一.(`abstract syntax tree`)抽象语法树的作用
源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(`abstract syntax tree`)。
之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 `; { }` 等。
有了 `AST`,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 `parse` 成 `AST`。
转成 `AST` 之后就可以通过修改 `AST` ,分析 `AST` 的方式来修改和分析代码,比如 `babel` 就通过这种方式进行代码的转换,比如 `rollup` 的 `Tree Shaking` ,就是通过分析 `AST`的 导入导出语法,从而分析出没有使用的代码,进行去除。
## 二。常见的 AST 节点
常见的 AST 节点
AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。
我们分别来了解一下:
### Literal
`Literal` 是字面量的意思,比如 `let name = 'value'`中,`'value'`就是一个字符串字面量 `StringLiteral`,相应的还有数字字面量 `NumericLiteral`,布尔字面量 `BooleanLiteral`,字符串字面量 `StringLiteral`,正则表达式字面量 `RegExpLiteral` 等。
下面这些字面量都有对应的 `Literal` 节点:

代码中的字面量很多,`babel` 就是通过 `xxLiteral` 来抽象这部分内容的。
### Identifier
`Identifer` 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是`Identifer`。
我们知道, `JS` 中的标识符只能包含字母或数字或下划线 `(“_”)` 或美元符号 `(“$”)` ,且不能以数字开头。这是 `Identifier` 的词法特点。
尝试分析一下,下面这一段代码里面有多少 `Identifier` 呢?
```js
const name = 'value';
function say(name) {
console.log(name);
}
const obj = {
name: 'guang',
};
```
答案是这些

### Statement
`statement` 是语句,它是可以独立执行的单位,比如 `break、continue、debugger、return` 或者 `if` 语句、`while` 语句、`for` 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。
语句末尾一般会加一个分号分隔,或者用换行分隔。
下面这些我们经常写的代码,每一行都是一个 `Statement`:
```js
break;
continue;
return;
debugger;
throw Error();
{}
try {} catch(e) {} finally{}
for (let key in obj) {}
for (let i = 0;i < 10;i ++) {}
while (true) {}
do {} while (true)
switch (v){case 1: break;default:;}
label: console.log();
with (a){}
```
它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 `(Statement)` 构成的。
### Declaration
声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 `class、import、export` 等。
比如下面这些语句都是声明语句:
```js
const a = 1;
function b() {}
class C {}
import d from 'e';
export default e = 1;
export { e };
export * from 'e';
```
它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。
### Expression
`expression` 是表达式,特点是执行完以后有返回值,这是和语句 (`statement`) 的区别。
下面是一些常见的表达式
```js
[1,2,3]
a = 1
1 + 2;
-1;
function(){};
() => {};
class{};
a;
this;
super;
a::b;
```
它们对应的 AST 如图:

细心的同学可能会问 `identifier` 和 `super` 怎么也是表达式呢?
因为 `identifier、super` 有返回值,符合表达式的特点,所以也是 `expression` 。
我们判断 `AST` 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。
有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。
```js
a = 1;
[1, 2, 3];
```
但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。
比如匿名函数表达式和匿名 `class` 表达式单独执行会报错:
```js
function(){};
class{}
```
需要和其他部分一起构成一条语句,比如组成赋值语句:
```js
a = function () {};
b = class {};
```
这条赋值语句对应的 `AST` 是这样的:

你会发现赋值语句的 AST 节点 `AssignmentExpression` 包裹了一层 `ExpressionStatement` 的节点,代表这个表达式是被当成语句执行的。
### Class
`class` 的语法也有专门的 AST 节点来表示。
整个 `class` 的内容是 `ClassBody` ,属性是 `ClassProperty` ,方法是 `ClassMethod` (通过 `kind` 属性来区分是 `constructor` 还是 `method` )。
比如下面的代码
```js
class Guang extends Person {
name = 'guang';
constructor() {}
eat() {}
}
```
对应的 AST 是这样的

`class` 是 `es next` 的语法, `babel` 中有专门的 `AST` 来表示它的内容。
### Modules
`es module` 是语法级别的模块规范,所以也有专门的 `AST` 节点。
**import**
`import` 有 3 种语法:
`named import`:
```js
import { c, d } from 'c';
```
`default import`:
```js
import a from 'a';
```
`namespaced import`:
```js
import * as b from 'b';
```
这 3 种语法都对应 `ImportDeclaration` 节点,但是 `specifiers` 属性不同,分别对应 `ImportSpicifier` `、ImportDefaultSpecifier` `、ImportNamespaceSpcifier` 。

图中黄框标出的就是 `specifier` 部分。可以直观的看出整体结构相同,只是 `specifier` 部分不同,所以 `import` 语法的 `AST` 的结构是 `ImportDeclaration` 包含着各种 `import specifier` 。
**export**
`export` 也有 3 种语法:
`named export`:
```js
export { b, d };
```
`default export`:
```js
export default a;
```
`all export`:
```js
export * from 'c';
```
分别对应 `ExportNamedDeclaration` `、ExportDefaultDeclaration` `、ExportAllDeclaration` 的 `AST` 。
比如这三种 `export`
```js
export { b, d };
export default a;
export * from 'c';
```
对应的 AST 节点为

### Program & Directive
`program` 是代表整个程序的节点,它有 `body` 属性代表程序体,存放 `statement` 数组,就是具体执行的语句的集合。还有 `directives` 属性,存放 `Directive` 节点,比如 `"use strict"` 这种指令会使用 `Directive` 节点表示。

`Program` 是包裹具体执行语句的节点,而 `Directive` 则是代码中的指令部分。
### File & Comment
`babel` 的 `AST` 最外层节点是 `File` ,它有 `program` 、 `comments` 、 `tokens` 等属性,分别存放 `Program` 程序体、注释、 `token` 等,是最外层节点。
注释分为块注释和行内注释,对应 `CommentBlock` 和 `CommentLine` 节点。

上面 6 种就是常见的一些 `AST` 节点类型, `babel` 就是通过这些节点来抽象源码中不同的部分。
### `AST` 可视化查看工具
这么多 `AST` 我们都要记住么?
不需要。可以通过 `axtexplorer.net` 这个网站来可视化的查看。

这个网站可以查看代码 `parse` 以后的 `AST` ,可以切换 `parse` 的语言和用的 `parser` ,也可以修改 `parse options` 。
点击这里的 `save` 就可以保存下来,然后把 `url` 分享出去:

比如这个链接:`https://astexplorer.net/`
如果想查看全部的 `AST` 可以在 `babel parser` 仓库里的 `AST` 文档里查,或者直接去看 `@babel/types` 的 `typescript` 类型定义。
### AST 的公共属性
每种 `AST` 都有自己的属性,但是它们也有一些公共的属性:
`type`: `AST` 节点的类型
`start` 、 `end` 、`loc:start` 和 `end` 代表该节点在源码中的开始和结束下标。而 `loc` 属性是一个对象,有 `line` 和 `column` 属性分别记录开始和结束的行列号。
`leadingComments` 、 `innerComments` 、 `trailingComments` :表示开始的注释、中间的注释、结尾的注释,每个 `AST` 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。
比如这段有注释的代码的 `AST` :

`extra:`记录一些额外的信息,用于处理一些特殊情况。比如 `StringLiteral` 的 `value` 只是值的修改,而修改 `extra.raw` 则可以连同单双引号一起修改。
比如这段代码的 `AST`:

修改 `value` 只能修改值,修改 `extra.raw` 可以连引号一起修改。
### 总结
了解了这些节点,就能知道平时写的代码是怎么用 `AST` 表示的。
当然也不需要记,可以用 `(astexpoler.net)` 可视化的查看。
`AST` 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 `Statement` 的特点是可以单独执行, `Expression` 的特点是有返回值,所以一些可以单独执行的 `Expression` 会包一层 `ExpressionStatement`。
不同 `AST` 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 `type` `、xxComments` 、 `loc` 等。
学会了 `AST` ,就可以把对代码的操作转为对 `AST` 的操作了,这是编译、静态分析的第一步。
## 三。编写词法分析器(Tokenizer)
词法分析器,也叫分词器 (`Tokenizer`),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:
```js
let foo = function () {};
```
在经过分词之后,代码会被切分为如下的 `token` 数组:
```js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];
```
从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 `token` 列表,不同的 `token` 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 `token` 之间的联系,整理出 `AST` 数据结构。
当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:
1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
2. 逐个代码字符扫描,根据语法规则进行 `token` 分组
### 1. 确定 Token 的类型和规则
增加 `Token` 的类型
```ts
export enum TokenType {
// let
Let = 'Let',
// =
Assign = 'Assign',
// function
Function = 'Function',
// 变量名
Identifier = 'Identifier',
// (
LeftParen = 'LeftParen',
// )
RightParen = 'RightParen',
// {
LeftCurly = 'LeftCurly',
// }
RightCurly = 'RightCurly',
}
export type Token = {
type: TokenType;
value?: string;
start: number;
end: number;
raw?: string;
};
```
定义 Token 类型到规则的映射
```ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
let(start: number) {
return { type: TokenType.Let, value: 'let', start, end: start + 3 };
},
assign(start: number) {
return { type: TokenType.Assign, value: '=', start, end: start + 1 };
},
function(start: number) {
return {
type: TokenType.Function,
value: 'function',
start,
end: start + 8,
};
},
leftParen(start: number) {
return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
},
rightParen(start: number) {
return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
},
leftCurly(start: number) {
return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
},
rightCurly(start: number) {
return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
},
identifier(start: number, value: string) {
return {
type: TokenType.Identifier,
value,
start,
end: start + value.length,
};
},
};
type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
// 单字符到 Token 生成器的映射
const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
['(', TOKENS_GENERATOR.leftParen],
[')', TOKENS_GENERATOR.rightParen],
['{', TOKENS_GENERATOR.leftCurly],
['}', TOKENS_GENERATOR.rightCurly],
['=', TOKENS_GENERATOR.assign],
]);
```
有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。
### 2.代码字符扫描
在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:
- 当前字符为分隔符,如空格,直接跳过,不处理;
- 当前字符为字母,需要继续扫描,获取完整的单词:
- 如果单词为语法关键字,则新建相应关键字的 `Token`
- 否则视为普通的变量名
- 当前字符为单字符,如`{、}、(、)`,则新建单字符对应的 `Token`
```ts
export class Tokenizer {
private _tokens: Token[] = [];
private _currentIndex: number = 0;
private _source: string;
constructor(input: string) {
this._source = input;
}
tokenize(): Token[] {
while (this._currentIndex < this._source.length) {
let currentChar = this._source[this._currentIndex];
const startIndex = this._currentIndex;
// 根据语法规则进行 token 分组
// while 循环内部
let currentChar = this._source[this._currentIndex];
const startIndex = this._currentIndex;
const isAlpha = (char: string): boolean => {
return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
};
// 1. 处理空格
if (currentChar === ' ') {
this._currentIndex++;
continue;
}
// 2. 处理字母
else if (isAlpha(currentChar)) {
let identifier = '';
while (isAlpha(currentChar)) {
identifier += currentChar;
this._currentIndex++;
currentChar = this._source[this._currentIndex];
}
let token: Token;
if (identifier in TOKENS_GENERATOR) {
// 如果是关键字
token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
} else {
// 如果是普通标识符
token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
}
this._tokens.push(token);
continue;
}
// 3. 处理单字符
else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
this._tokens.push(token);
this._currentIndex++;
continue;
}
}
return this._tokens;
}
}
```
使用方式
```ts
const tokenizer = new Tokenizer('let a = function() {}');
```
结果
```ts
const tokenizer = [
{ type: 'Let', value: 'let', start: 0, end: 3 },
{ type: 'Identifier', value: 'a', start: 4, end: 5 },
{ type: 'Assign', value: '=', start: 6, end: 7 },
{ type: 'Function', value: 'function', start: 8, end: 16 },
{ type: 'LeftParen', value: '(', start: 16, end: 17 },
{ type: 'RightParen', value: ')', start: 17, end: 18 },
{ type: 'LeftCurly', value: '{', start: 19, end: 20 },
{ type: 'RightCurly', value: '}', start: 20, end: 21 },
];
```
一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。
## 四。编写语法分析器(Parser)
在解析出词法 `token` 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 `token` ,对代码进行语法结构层面的分析,最后的目标是生成 `AST` 数据结构。至于代码的 `AST` 结构到底是什么样子,你可以去 `AST Explorer` 网站进行在线预览:

接下来,我们要做的就是将 `token` 数组转换为上图所示的 `AST` 数据。
开发步骤主要分为:
- 初始化类型声明
-
================================================
FILE: packages/docs/cn/src/article/babel.md
================================================
# Babel
babel 核心库主要是:
- @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
- @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
- @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
- @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
- @babel/code-frame 可以创建友好的报错信息
- @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
- @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。
================================================
FILE: packages/docs/cn/src/article/bundle.md
================================================
# Bundle
Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:
- 编译能力
- 插件机制
- HMR
- cli 和命令行能力
================================================
FILE: packages/docs/cn/src/article/design_mode.md
================================================
# 23 种经典设计模式
> 设计模式 `Design Pattern` 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。。
在《设计模式:可复用面向对象软件的基础》一书中所介绍的 23 种经典设计模式,不过设计模式并不仅仅只有这 23 种,随着软件开发行业的发展,越来越多的新模式不断诞生并得以应用。有经验的开发者在学习设计模式可以和过往的经验互相印证,更容易理解这些设计模式。
设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素。问题描述了应该在何时使用模式,它包含了设计中存在的问题以及问题存在的原因。解决方案描述了一个设计模式的组成成分,以及这些组成成分之间的相互关系,各自的职责和协作方式,通常解决方案通过 `UML` 类图和核心代码来进行描述。效果描述了模式的优缺点以及在使用模式时应权衡的问题。
**为什么要学习设计模式**:
- 设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作
- 设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂
- 大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码
- 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统
- 学习设计模式将有助于初学者更加深入地理解面向对象思想
**储备知识**:
- 抽象类:一般抽象类都是作为基类,比如说「电脑」就可以作为一个抽象类,根据抽象类派生出「台式电脑」和「笔记本电脑」2 种具体类。一般不对抽象类进行实例化。
- 组合优于继承:不能滥用继承来拓展功能,配合组合会更灵活。同样拿「电脑」抽象类来举例,如果使用继承,区分不同类型的「电脑」我们可以派生出「台式电脑」和「笔记本电脑」,如果再增加一个维度,根据品牌又能继续细分出「联想台式电脑」、「联想笔记本电脑」、「苹果台式电脑」和「苹果笔记本电脑」等等,如果再增加一个维度继续细分下去,显然继承是无法胜任的。这个时候可以使用继承加组合方式,组合的对象也可以进行抽象化设计:
```ts
// 品牌
interface Brand {
// ...
}
interface Lenovo extends Brand {
// ...
}
interface Apple extends Brand {
// ...
}
// CPU
interface CPU {
// ...
}
interface Inter extends CPU {
// ...
}
interface AMD extends CPU {
// ...
}
// 电脑
interface Computer {
// ...
}
interface DesktopComputer extends Computer {}
interface NotebookComputer extends Computer {}
```
## 一、UML 类图
每个模式都有相应的对象结构图,同时为了展示对象间的交互细节,有些时候会用到 `UML` 图来介绍其如何运行。这里不会将 `UML` 的各种元素都提到,只想讲讲类图中各个类之间的关系,能看懂类图中各个类之间的线条、箭头代表什么意思后,也就足够应对日常的工作和交流。同时,我们应该能将类图所表达的含义和最终的代码对应起来。有了这些知识,看后面章节的设计模式结构图就没有什么问题了。
<!-- 本文中大部分是 UML 类图,也有个别简易流程图。由于文中部分模式并未配图,你可以在 [这里](../../../assets/article/designPattern/UML/创建型/单例.jpg) 查看我在网络上收集的完整 23 种设计模式 UML 类图。 -->
### 1.1 继承
继承用一条带空心箭头的直接表示。

### 1.2 实现
实现关系用一条带空心箭头的虚线表示。

### 1.3 组合
与聚合关系一样,组合关系同样表示整体由部分构成的语义。比如公司由多个部门组成,但组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了。例如,公司不存在了,部门也将不存在了。

### 1.4 聚合
聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义,例如一个部门由多个员工组成。与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。例如,部门撤销了,人员不会消失,他们依然存在。

### 1.5 关联
关联关系是用一条直线表示的,它描述不同类的对象之间的结构关系,它是一种静态关系,通常与运行状态无关,一般由常识等因素决定的。它一般用来定义对象之间静态的、天然的结构,所以,关联关系是一种“强关联”的关系。
比如,乘车人和车票之间就是一种关联关系,学生和学校就是一种关联关系,关联关系默认不强调方向,表示对象间相互知道。如果特别强调方向,如下图,表示 A 知道 B,但 B 不知道 A。

### 1.6 依赖
依赖关系是用一套带箭头的虚线表示的,如 A 依赖于 B,他描述一个对象在运行期间会用到另一个对象的关系。
与关联关系不同的是,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。显然,依赖也有方向,双向依赖是一种非常糟糕的结构,我们总是应该保持单向依赖,杜绝双向依赖的产生。

## 二、六大原则
### 2.1 开闭原则
> 一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。
为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在`Java`、`C#`等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。
**优点:实践开闭原则的优点在于可以在不改动原有代码的前提下给程序扩展功能。增加了程序的可扩展性,同时也降低了程序的维护成本。**
### 2.2 里氏替换原则
> 所有引用基类对象的地方能够透明地使用其子类的对象
里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类。但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。
例如有两个类,一个类为`BaseClass`,另一个是`SubClass`类,并且`SubClass`类是`BaseClass`类的子类,那么一个方法如果可以接受一个`BaseClass`类型的基类对象`base`的话,如:`method1(base)`,那么它必然可以接受一个`BaseClass`类型的子类对象`sub`,`method1(sub)`能够正常运行。反过来的代换不成立,如一个方法`method2`接受`BaseClass`类型的子类对象`sub`为参数:`method2(sub)`,那么一般而言不可以有`method2(base)`,除非是重载方法。
里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
**优点:可以检验继承使用的正确性,约束继承在使用上的泛滥。**
### 2.3 依赖倒置原则
> 抽象不应该依赖于具体类,具体类应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。
在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。
**优点:通过抽象来搭建框架,建立类和类的关联,以减少类间的耦合性。而且以抽象搭建的系统要比以具体实现搭建的系统更加稳定,扩展性更高,同时也便于维护。**
### 2.4 单一职责原则
> 一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。
单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。
**优点:如果类与方法的职责划分得很清晰,不但可以提高代码的可读性,更实际性地更降低了程序出错的风险,因为清晰的代码会让 bug 无处藏身,也有利于 bug 的追踪,也就是降低了程序的维护成本。**
### 2.5 迪米特法则(最少知道原则)
> 一个软件实体应当尽可能少地与其他实体发生相互作用
如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。
迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。
在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及。在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。在类的设计上,只要有可能,一个类型应当设计成不变类。在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
**优点:实践迪米特法则可以良好地降低类与类之间的耦合,减少类与类之间的关联程度,让类与类之间的协作更加直接。**
### 2.6 接口分离原则
> 使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。
在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护。接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。
**优点:避免同一个接口里面包含不同类职责的方法,接口责任划分更加明确,符合高内聚低耦合的思想。**
### 2.7 合成复用原则(六大之外的)
> 尽量使用对象组合,而不是继承来达到复用的目的
合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用功能的目的。简而言之,复用时要尽量使用组合/聚合关系(关联关系),少用继承。
在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度。一个类的变化对其他类造成的影响相对较少,其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。
**优点:避免复用时滥用继承,合理使用组合关系,增加灵活性。**
### 2.8 六大原则 - 学习心得
六大原则中,**开闭原则**、**里氏替换原则**、**依赖倒置原则** 联系比较紧密,后两者是实现开闭原则重要前提,使用中通过抽象化设计具有很好的可拓展性和可维护性。
**知道最少原则** 可以降低耦合,减少不必要的交互,主张设计接口和类要简单易使用,将复杂的逻辑封装并提供简单易用的接口。
**单一职责原则** 使项目中的类和方法根据职责细分,避免单个类负担过重。职责越多,被复用的可能性就越小或使用起来越麻烦。
**接口分离原则** 将功能复杂的接口细分成多个特定功能的接口,只做该做的事情,降低耦合,但是细化粒度不能太细,容易导致接口过多。单一职责原则强调单个类内部根据职责细分的设计,接口分离原则强调类之间的耦合,尽量建立最小的依赖关系。
## 三、模式分类
《设计模式:可复用面向对象软件的基础》一书中设计模式有 23 个,它们各具特色,每个模式都为某一个可重复的设计问题提供了一套解决方案。根据它们的用途,设计模式可分为创建型 (`Creational`),结构型 (`Structural`) 和行为型 (`Behavioral`) 三种,其中创建型模式主要用于描述如何创建对象,结构型模式主要用于描述如何实现类或对象的组合,行为型模式主要用于描述类或对象怎样交互以及怎样分配职责。
此外,根据某个模式主要是用于处理类之间的关系还是对象之间的关系,设计模式还可以分为类模式和对象模式。我们经常将两种分类方式结合使用,如单例模式是对象创建型模式,模板方法模式是类行为型模式。
### 3.1 创建型
创建型模式 (`Creational Pattern`) 对类的实例化过程进行了抽象,能够将模块中对象的创建和对象的使用分离。为了使结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。
1. 简单工厂模式(`Simple Factory Pattern`)
2. 工厂方法模式(`Factory Method Pattern`)
3. 抽象工厂模式(`Abstract Factory Pattern`)
4. 单例模式(`Singleton Pattern`)
5. 生成器模式(`Builder Pattern`)
6. 原型模式(`Prototype Pattern`)
### 3.2 结构型
结构型模式 (`Structural Pattern`) 描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。结构型模式可以分为类结构型模式和对象结构型模式:
- 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。
- 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。
1. 外观模式
2. 适配器模式
3. 桥接模式
4. 代理模式
5. 装饰者模式
6. 享元模式
### 3.3 行为型
行为型模式 (`Behavioral Pattern`) 是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。
1. 职责链模式
2. 命令模式
3. 解释器模式
4. 迭代器模式
5. 中介者模式
6. 备忘录模式
7. 观察者模式
8. 状态模式
9. 策略模式
10. 模板方法模式
11. 访问者模式
## 四、创建型
### 4.1 简单工厂模式
> 简单工厂模式 (`Simple Factory Pattern`):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。

**举例:**
简单工厂模式像一个代工厂,一个工厂可以生产多种产品。举个例子,一个饮料加工厂同时帮百事可乐和可口可乐生产,加工厂根据输入参数`Type`来生产不同的产品。
```ts
// 可乐抽象类
interface Cola {}
// 可口可乐产品类
interface CocaCola extends Cola {}
// 百事可乐产品类
interface PepsiCola extends Cola {}
```
```ts
// 简单工厂实现
// SimpleFactory
const createColaWithType = (type: number) => {
switch (type) {
case 0:
return new CocaCola();
case 1:
return new PepsiCola();
default:
return null;
break;
}
};
```
```ts
// 0 生产可口可乐
const cocaCola: CocaCola = createColaWithType(0);
// 1 生产百事可乐
const pepsiCola: PepsiCola = createColaWithType(1);
```
**优点:**
- 使用者只需要给工厂类传入一个正确的约定好的参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合。
- 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,减少开发者的记忆成本。
**缺点:**
- 如果业务上添加新产品的话,就需要修改工厂类原有的判断逻辑,这其实是违背了开闭原则的。
- 在产品类型较多时,有可能造成工厂逻辑过于复杂。所以简单工厂模式比较适合产品种类比较少而且增多的概率很低的情况。
### 4.2 工厂方法模式
> 工厂方法模式 (`Factory Method Pattern`) 又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

**举例:**
工厂方法和简单工厂有一些区别,简单工厂是由一个代工厂生产不同的产品,而工厂方法是对工厂进行抽象化,不同产品都由专门的具体工厂来生产。可口可乐工厂专门生产可口可乐,百事可乐工厂专门生产百事可乐。
```ts
// 工厂抽象类
class Cola {}
// 可口可乐工厂
class CocaCola extends Cola {}
// 百事可乐工厂
class PepsiCola extends Cola {}
```
```ts
// 根据不同的工厂类生产不同的产品
const cocaCola = new CocaCola();
const pepsiCola = new PepsiCola();
```
**优点:**
- 用户只需要关心其所需产品对应的具体工厂是哪一个即可,不需要关心产品的创建细节,也不需要知道具体产品类的类名。
- 当系统中加入新产品时,不需要修改抽象工厂和抽象产品提供的接口,也无须修改客户端和其他的具体工厂和具体产品,而只要添加一个具体工厂和与其对应的具体产品就可以了,符合了开闭原则。
**缺点:**
- 当系统中加入新产品时,除了需要提供新的产品类之外,还要提供与其对应的具体工厂类。因此系统中类的个数将成对增加,增加了系统的复杂度。
### 4.3 抽象工厂模式
抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。
> 抽象工厂模式 (Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

**举例:**
抽象工厂和工厂方法不同的地方在于,生产产品的工厂是抽象的。举例,可口可乐公司生产可乐的同时,也需要生产装可乐的瓶子和箱子,瓶子和箱子也是可口可乐专属定制的,同样百事可乐公司也会有这个需求。这个时候我们的工厂不仅仅是生产可乐饮料的工厂,还必须同时生产同一主题的瓶子和箱子,所以它是一个抽象的主题工厂,专门生产同一主题的不同商品。
```ts
// 可乐抽象类和派生类
class Cola {}
class CocaCola extends Cola {}
class PepsiCola extends Cola {}
// 瓶子抽象类和派生类
class Bottle {}
class CocaColaBottle extends Bottle {}
class PepsiColaBottle extends Bottle {}
// 箱子抽象类和派生类
class Box {}
class CocaColaBox extends Box {}
class PepsiColaBox extends Box {}
// 工厂抽象类
const Factory = {
createCola: () => new Cola(),
createBottle: () => new Bottle(),
createBox: () => new Box(),
};
// 可口可乐主题工厂
const CocaColaFactory = {
createCola: () => new CocaCola(),
createBottle: () => new CocaColaBottle(),
createBox: () => new CocaColaBox(),
};
// 百事可乐主题工厂
const PepsiColaFactory = {
createCola: () => new PepsiCola(),
createBottle: () => new PepsiColaBottle(),
createBox: () => new PepsiColaBox(),
};
```
```ts
// 可口可乐主题
const cocaCola = CocaColaFactory.createCola();
const cocaColaBottle = CocaColaFactory.createBottle();
const cocaColaBox = CocaColaFactory.createBox();
// 百事可乐主题
const pepsiCola = PepsiColaFactory.createCola();
const pepsiColaBottle = PepsiColaFactory.createBottle();
const pepsiColaBox = PepsiColaFactory.createBox();
```
**优点:**
- 具体产品在应用层代码隔离,不需要关心产品细节。只需要知道自己需要的产品是属于哪个工厂的即可 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
**缺点:**
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
### 4.4 单例模式
> 单例模式 (`Singleton Pattern`):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

**举例:**
单例模式下,对应类只能生成一个实例。就像一个王国只能有一个国王,一旦王国里的事务多起来,这唯一的国王也容易职责过重。
```ts
class Singleton {}
function createSingleton() {
let instance;
return function () {
if (!instance) return new Singleton();
return instance;
};
}
```
**优点:**
- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。
- 因为该类在系统内存中只存在一个对象,所以可以节约系统资源。
**缺点:**
- 由于单例模式中没有抽象层,因此单例类很难进行扩展。
- 对于有垃圾回收系统的语言 Java,C# 来说,如果对象长时间不被利用,则可能会被回收。那么如果这个单例持有一些数据的话,在回收后重新实例化时就不复存在了。
### 4.5 生成器模式
> 生成器模式 (Builder Pattern):也叫创建者模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出 (创建) 的是什么,而不关心创建的过程。而建造者模式关心的是创建这个对象的整个过程,甚至于创建对象的每一个细节。

**举例:**
生成器模式的主要角色如下:
1. 生成器:接口生命再所有类型生成器中通用的产品构造步骤
2. 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
3. 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口
4. 指挥者:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置
5. 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
```ts
// 抽象建造者
abstract class Builder {
public abstract buildPartA(): void;
public abstract buildPartB(): void;
public abstract buildPartC(): void;
public abstract buildProduct(): Product;
}
// 具体建造者
class ConcreteBuilder extends Builder {
private product: Product;
constructor(product: Product) {
super();
this.product = product;
}
public buildPartA(): void {}
public buildPartB(): void {}
public buildPartC(): void {}
// 最终组建一个产品
public buildProduct(): Product {
return this.product;
}
}
// 产品角色
class Product {
public doSomething(): void {
// 独立业务
}
}
// 指挥者
class Director {
private _builder: Builder;
constructor(builder: Builder) {
this._builder = builder;
}
set builder(builder: Builder) {
this._builder = builder;
}
// 将处理建造的流程交给指挥者
public constructorProduct() {
this._builder.buildPartA();
this._builder.buildPartB();
this._builder.buildPartC();
return this._builder.buildProduct();
}
}
// 使用
const builder: Builder = new ConcreteBuilder(new Product());
const director: Director = new Director(builder);
const product: Product = director.constructorProduct();
```
**优点:**
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
- 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
- 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
**缺点:**
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。
### 4.6 原型模式
> 原型模式(`Prototype Pattern`): 用原型实例指向创建对象的类,使用于创建新的对象的类的共享原型的属性与方法。

**举例:**
原型模式就像复印技术,根据原对象复印出一个新对象,并根据需求对新对象进行微调。
```ts
// 因为不是构造函数,所以不用大写
const car = {
drive: function () {},
name: '马自达 3',
};
// 使用 Object.create 创建一个新车 x
const anotherCar = Object.create(someCar);
anotherCar.name = '丰田佳美';
```
```ts
const vehiclePrototype = {
init: function (carModel) {
this.model = carModel;
},
getModel: function () {
console.log('车辆模具是:' + this.model);
},
};
function vehicle(model) {
function F() {}
F.prototype = vehiclePrototype;
const f = new F();
f.init(model);
return f;
}
const car = vehicle('福特 Escort');
car.getModel();
```
**优点:**
- 可以利用原型模式简化对象的创建过程,尤其是对一些创建过程繁琐,包含对象层级比较多的对象来说,使用原型模式可以节约系统资源,提高对象生成的效率。
- 可以很方便得通过改变值来生成新的对象:有些对象之间的差别可能只在于某些值的不同;用原型模式可以快速复制出新的对象并手动修改值即可。
**缺点:**
- 对象包含的所有对象都需要配备一个克隆的方法,这就使得在对象层级比较多的情况下,代码量会很大,也更加复杂。
## 五、结构型
### 5.1 装饰模式
> 装饰模式 (`Decorator Pattern`) :向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式,它是作为现有的类的一个包装。
可以将装饰器理解为游戏人物购买的装备,例如 LOL 中的英雄刚开始游戏时只有基础的攻击力和法强。但是在购买的装备后,在触发攻击和技能时,能够享受到装备带来的输出加成。我们可以理解为购买的装备给英雄的攻击和技能的相关方法进行了装饰。

**举例:**
装饰模式贴合开闭原则,在不改变原有类的情况下,对父类进行改造或新增功能。
装饰类
```ts
@annotation
class MyClass {}
function annotation(target) {
target.annotated = true;
}
```
装饰方法或属性
```js
class MyClass {
@readonly
method() {}
}
function readonly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
```
**优点:**
- 比继承更加灵活:不同于在编译期起作用的继承;装饰者模式可以在运行时扩展一个对象的功能。另外也可以通过配置文件在运行时选择不同的装饰器,从而实现不同的行为。也可以通过不同的组合,可以实现不同效果。
- 符合“开闭原则”:装饰者和被装饰者可以独立变化。用户可以根据需要增加新的装饰类,在使用时再对其进行组合,原有代码无须改变。
**缺点:**
- 装饰者模式需要创建一些具体装饰类,会增加系统的复杂度。
### 5.2 外观模式
> 外观模式 (Facade Pattern):外观模式定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。使得子系统更容易使用,不仅简化类中的接口,而且实现调用者和接口的解耦。外观模式又称为门面模式,它是一种结构型设计模式模式。

**举例:**
外观模式提供了简单明确的接口,但是在内部众多子系统功能进行整合。就像图片缓存,内部包含了涉及到其他子系统的如缓存、下载等处理,外观模式将这些复杂的逻辑都隐藏了。在兼容浏览器事件绑定,你只需要调一个`addMyEvent`接口就可以了,达到解耦合的目的。
```js
const addMyEvent = function (el, ev, fn) {
if (el.addEventListener) {
el.addEventListener(ev, fn, false);
} else if (el.attachEvent) {
el.attachEvent('on' + ev, fn);
} else {
el['on' + ev] = fn;
}
};
```
**优点:**
- 实现了客户端与子系统间的解耦:客户端无需知道子系统的接口,简化了客户端调用子系统的调用过程,使得子系统使用起来更加容易。同时便于子系统的扩展和维护。
- 符合迪米特法则(最少知道原则):子系统只需要将需要外部调用的接口暴露给外观类即可,而且他的接口则可以隐藏起来。
**缺点:**
- 违背了开闭原则:在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的代码。
### 5.3 代理模式
> 代理模式 (Proxy Pattern) :为某个对象提供一个代理,并由这个代理对象控制对原对象的访问。

**举例:**
代理模式像一个房屋中介,买家只能通过中介来买房,代理具备被代理类的所有功能,就像房东有卖房功能,中介也具有卖房功能。此外代理实例还可以帮助被代理实例进行一些额外处理,比如中介可以帮助房东筛选优质买家的功能,帮助房东 pass 掉一些不符合条件的买家。还有消息队列也是该模式。
参考`koa`中的代理模式,把`response`上的一些属性和方法代理出来,方便使用
```js
/**
* Response delegation.
*/
const delegate = require('delegates');
const prototype = (module.exports = {});
delegate(prototype, 'response')
.method('attachment')
.method('redirect')
.method('remove')
.method('vary')
.method('has')
.method('set')
.method('append')
.method('flushHeaders')
.access('status')
.access('message')
.access('body')
.access('length')
.access('type')
.access('lastModified')
.access('etag')
.getter('headerSent')
.getter('writable');
```
对`context`,`request`,`response`做一个代理,保护真正的`context`,`request`,`response`
```js
this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
```
**优点:**
- 降低系统的耦合度:代理模式能够协调调用者和被调用者,在一定程度上降低了系 统的耦合度。
- 不同类型的代理可以对客户端对目标对象的访问进行不同的控制:
- 远程代理,使得客户端可以访问在远程机器上的对象,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
- 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
- 保护代理可以控制客户端对真实对象的使用权限。
**缺点:**
- 由于在客户端和被代理对象之间增加了代理对象,因此可能会让客户端请求的速度变慢。
### 5.4 享元模式
> 享元模式 (`Flyweight Pattern`):享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。运用共享技术复用大量细粒度的对象,降低程序内存的占用,提高程序的性能。以下情况可以使用享元模式:有大量相似的对象,占用了大量内存。对象中大部分状态可以抽离为外部状态。

**举例:**
举例,音乐服务根据收费划分出免费用户和会员用户,免费用户只能听部分免费音乐,会员用户可以听全部的音乐,并且可以下载。虽然权限上二者间有一些区别,但是他们所享受的音乐来是自于同一个音乐库,这样所有的音乐都只需要保存一份就可以了。另外如果出现音乐库里没有的音乐时,则需要新增该音乐,然后其他服务也可以享受新增的音乐,相当于享元池或缓存池的功能。
享元模式区保证共享内部状态如音乐库,而外部状态根据不同需求定制如各种访问权限,使用中不能去改变内部状态,以达到共享的目的。
```ts
// 音乐服务
const MusicService = {}
// 共享的音乐库
const musicLibrary = {};
// 听音乐
const listenToMusic = (music) => {
...
}
// 下载音乐
const downloadMusic = (music) => {
...
}
// 免费音乐服务
const FreeMusicService = {
listenFreeMusic: (music)=>{
if(isMusicFree(music)){
// 如果是免费则播放
listenToMusic()
}else{
// 如果是收费音乐,则提示用户升级 Vip
console.log("please upgrade to Vip")
}
}
}
// Vip 音乐服务
const VipMusicService = {
// 可以听全部的音乐
listenMusic
// 可以下载音乐
downloadMusic
}
```
**优点:**
- 使用享元模可以减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份,降低系统的使用内存,也可以提性能。
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
**缺点:**
- 使用享元模式需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
- 对象在缓冲池中的复用需要考虑线程问题。
### 5.5 桥接模式
> 桥接模式 (`Simple Factory Pattern`):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

**举例:**
球和人都可以进行运动,但球有运动和颜色,人可以运动和说话。对共同部分进行抽象。
```js
class Speed {
// 运动模块
constructor(x, y) {
this.x = x;
this.y = y;
}
run() {
console.log(`运动起来 ${this.x} + ${this.y}`);
}
}
class Color {
// 着色模块
constructor(cl) {
this.color = cl;
}
draw() {
console.log(`绘制颜色 ${this.color}`);
}
}
class Speak {
constructor(wd) {
this.word = wd;
}
say() {
console.log(`说话 ${this.word}`);
}
}
class Ball {
// 创建球类,可以着色和运动
constructor(x, y, cl) {
this.speed = new Speed(x, y);
this.color = new Color(cl);
}
init() {
this.speed.run();
this.color.draw();
}
}
class Man {
// 人类,可以运动和说话
constructor(x, y, wd) {
this.speed = new Speed(x, y);
this.speak = new Speak(wd);
}
init() {
this.speed.run();
this.speak.say();
}
}
const man = new Man(1, 2, 'hello ?');
man.init(); // 运动起来 1 + 2 说话 hello?
```
**优点:**
- 扩展性好,符合开闭原则:将抽象与实现分离,让二者可以独立变化
**缺点:**
- 在设计之前,需要识别出两个独立变化的维度。
### 5.6 适配器模式
> 适配器模式 (`Adapter Pattern`) :适配器模式是用来解决两个接口不兼容的情况,不需要改变已有的接口,通过包装一层的方式,实现两个接口正常协作。当我们试图调用模块或者对象的某个接口时,却发现这个接口的格式并不符合目前的需求,则可以用适配器模式。

**举例:**
事件绑定兼容各浏览器
```js
function addEvent(ele, event, callback) {
if (ele.addEventListener) {
ele.addEventListener(event, callback)
} else if(ele.attachEvent) {
ele.attachEvent('on' + event, callback)
} else {
ele['on' + event] = callback
}
}
```
**优点:**
- 符合开闭原则:使用适配器而不需要改变现有类,提高类的复用性。
- 目标类和适配器类解耦,提高程序扩展性。
**缺点:**
- 增加了系统的复杂性
## 六、行为型
### 6.1 职责链模式
> 职责链模式 (Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。

**举例:**
场景:某电商针对已付过定金的用户有优惠政策,在正式购买后,已经支付过 500 元定金的用户会收到 100 元的优惠券,200 元定金的用户可以收到 50 元优惠券,没有支付过定金的用户只能正常购买。
```js
const order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay == true) {
console.log('500 元定金预购,得到 100 元优惠劵');
} else {
return 'nextSuccess';
}
};
const order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('200 元定金预购,得到 50 元優惠卷');
} else {
return 'nextSuccess';
}
};
const orderCommon = function (orderType, pay, stock) {
if (orderType == 3 && stock > 0) {
console.log('普通購買,无優惠卷');
} else {
console.log('库存不够');
}
};
//链路代码
const chain = function (fn) {
this.fn = fn;
this.successor = null;
};
chain.prototype.setNext = function (successor) {
this.successor = successor;
};
chain.prototype.init = function () {
const result = this.fn.apply(this, arguments);
if (result == 'nextSuccess') {
this.successor.init.apply(this.successor, arguments);
}
};
const order500New = new chain(order500);
const order200New = new chain(order200);
const orderCommonNew = new chain(orderCommon);
order500New.setNext(order200New);
order200New.setNext(orderCommonNew);
order500New.init(3, true, 500); // 普通购买,无优惠券
```
**优点:**
- 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
- 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
- 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
- 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。
**缺点:**
- 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
- 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
- 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。
### 6.2 命令模式
> 命令模式 (`Command Pattern`):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;命令模式是一种对象行为型模式,其别名为动作 (`Action`) 模式或事务 (`Transaction`) 模式。
命令模式由三种角色构成:
1. 发布者 `invoker`(发出命令,调用命令对象,不知道如何执行与谁执行);
2. 接收者 `receiver` (提供对应接口处理请求,不知道谁发起请求);
3. 命令对象 `command`(接收命令,调用接收者对应接口处理发布者的请求)。
发布者 invoker 和接收者 receiver 各自独立,将请求封装成命令对象 command,请求的具体执行由命令对象 command 调用接收者 receiver 对应接口执行。

**举例:**
和之前代理模式中的举例有些相似,不过命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。例如遥控器是一个调用者,不同按钮代表不同的命令,而电视是接收者。
```js
class Receiver {
// 接收者类
execute() {
console.log('接收者执行请求');
}
}
class Command {
// 命令对象类
constructor(receiver) {
this.receiver = receiver;
}
execute() {
// 调用接收者对应接口执行
console.log('命令对象->接收者->对应接口执行');
this.receiver.execute();
}
}
class Invoker {
// 发布者类
constructor(command) {
this.command = command;
}
invoke() {
// 发布请求,调用命令对象
console.log('发布者发布请求');
this.command.execute();
}
}
const warehouse = new Receiver(); // 仓库
const order = new Command(warehouse); // 订单
const client = new Invoker(order); // 客户
client.invoke();
```
**优点:**
- 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
- 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
- 可以比较容易地设计一个命令队列或宏命令(组合命令)。
- 为请求的撤销 (Undo) 和恢复 (Redo) 操作提供了一种设计和实现方案。
**缺点:**
- 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。
### 6.3 解释器模式
> 解释器模式 (`Interpreter Pattern`):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

**举例:**
给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
```js
class Context {
constructor() {
this._list = []; // 存放 终结符表达式
this._sum = 0; // 存放 非终结符表达式 (运算结果)
}
get sum() {
return this._sum;
}
set sum(newValue) {
this._sum = newValue;
}
add(expression) {
this._list.push(expression);
}
get list() {
return [...this._list];
}
}
class PlusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error('TypeError');
}
context.sum = ++context.sum;
}
}
class MinusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error('TypeError');
}
context.sum = --context.sum;
}
}
/** 以下是测试代码 **/
const context = new Context();
// 依次添加:加法 | 加法 | 减法 表达式
context.add(new PlusExpression());
context.add(new PlusExpression());
context.add(new MinusExpression());
// 依次执行:加法 | 加法 | 减法 表达式
context.list.forEach((expression) => expression.interpret(context));
console.log(context.sum);
```
**优点:**
- 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
- 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
- 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
- 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。
**缺点:**
- 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
- 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
### 6.4 迭代器模式
> 迭代器模式 (`Iterator Pattern`):一个相对简单的模式,目前绝大多数语言都内置了迭代器,以至于大家都不觉得这是一种设计模式。迭代器并不只迭代数组,迭代器可以中止。提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标 (`Cursor`)。迭代器模式是一种对象行为型模式。

**举例:**
迭代器帮助请求方获取数据,避免直接操作数据聚合类,使数据聚合类专注存储数据。具体应用有分页等功能,分页功能的迭代器将专门负责操作分页数据,将操作逻辑和数据源分离。
```js
var each = function (arr, callback) {
for (var i = 0, len = arr.length; i < len; i++) {
callback.call(arr[i], i, arr[i]);
}
};
each([1, 2, 3, 4, 5], function (i, el) {
console.log('index: ', i);
console.log('item: ', el);
});
```
**优点:**
- 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
- 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
- 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。
**缺点:**
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
- 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如 JDK 内置迭代器 Iterator 就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类 ListIterator 等来实现,而 ListIterator 迭代器无法用于操作 Set 类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。
### 6.5 中介者模式
> 中介者模式`(Mediator Pattern`):对象和对象之间借助第三方中介者进行通信。用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

**举例:**
中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系。所有成员通过中介者交互,方便拓展新的成员,例如下面的例子,一场测试结束后,公布结果:告知解答出题目的人挑战成功,否则挑战失败。在这段代码中 A、B、C 之间没有直接发生关系,而是通过另外的 playerMiddle 对象建立链接,姑且将之当成是中介者模式了。
```js
const player = function (name) {
this.name = name;
playerMiddle.add(name);
};
player.prototype.win = function () {
playerMiddle.win(this.name);
};
player.prototype.lose = function () {
playerMiddle.lose(this.name);
};
const playerMiddle = (function () {
//将就用下这个 demo, 这个函数充当中介者
const players = [];
const winArr = [];
const loseArr = [];
return {
add: function (name) {
players.push(name);
},
win: function (name) {
winArr.push(name);
if (winArr.length + loseArr.length === players.length) {
this.show();
}
},
lose: function (name) {
loseArr.push(name);
if (winArr.length + loseArr.length === players.length) {
this.show();
}
},
show: function () {
for (let winner of winArr) {
console.log(winner + '挑戰成功;');
}
for (let loser of loseArr) {
console.log(loser + '挑战失败;');
}
},
};
})();
const a = new player('A 选手');
const b = new player('B 选手');
const c = new player('C 选手');
a.win();
b.lose();
c.win();
// A 选手挑战成功;
// B 选手挑战成功;
// C 选手挑战失败;
```
**优点:**
- 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
- 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
- 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。
**缺点:**
- 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
### 6.6 备忘录模式
> 备忘录模式 (`Memento Pattern`):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便日后对象使用或者对象恢复到以前的某个状态。它是一种对象行为型模式,其别名为 Token。

**举例:**
备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。
当我们开发一个分页组件的时候,点击下一页获取新的数据,但是当点击上一页时,又重新获取数据,造成无谓的流量浪费,这时可以对数据进行缓存。
```js
// 备忘录模式伪代码
var Page = function () {
// 通过 cache 对象缓存数据
var cache = {};
return function (page, fn) {
if (cache[page]) {
showPage(page, cache[page]);
} else {
$.post('/url', function (data) {
showPage(page, data);
cache[page] = data;
});
}
fn && fn();
};
};
```
**优点:**
- 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
- 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。
**缺点:**
- 资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。
### 6.7 观察者模式
> 观察者模式 (`Observer Pattern)`:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布 - 订阅(`Publish/Subscribe`)模式、模型 - 视图(`Model/View`)模式、源 - 监听器(`Source/Listener`)模式或从属者(`Dependents`)模式。观察者模式是一种对象行为型模式。

**举例:**
观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。
在`JavaScript`中观察者模式的实现主要用事件模型,`DOM`事件。
```js
// 发布者
var pub = function () {
console.log('欢迎订阅!');
};
// 订阅者
var sub = document.body;
// 订阅者实现订阅
sub.addEventListener('click', pub, false);
```
**优点:**
- 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
- 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
- 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
**缺点:**
- 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
### 6.8 状态模式
> 状态模式 (`State Pattern`):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象 (`Objects for States`),其实就是用一个对象或者数组记录一组状态,每个状态对应一个实现,实现的时候根据状态挨个去运行实现。状态模式是一种对象行为型模式。

**举例:**
状态模式用于解决复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,所以对象在不同状态下具有不同行为时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。
比如超级玛丽,就可能同时有好几个状态比如 跳跃,移动,射击,蹲下 等,如果对这些动作一个个进行处理判断,需要多个 if-else 或者 switch 不仅丑陋不说,而且在遇到有组合动作的时候,实现就会变的更为复杂,这里可以使用状态模式来实现。
状态模式的思路是:首先创建一个状态对象或者数组,内部保存状态变量,然后内部封装好每种动作对应的状态,然后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。
```js
class SuperMarry {
constructor() {
this._currentState = [];
this.states = {
jump() {
console.log('跳跃!');
},
move() {
console.log('移动!');
},
shoot() {
console.log('射击!');
},
squat() {
console.log('蹲下!');
},
};
}
change(arr) {
// 更改当前动作
this._currentState = arr;
return this;
}
go() {
console.log('触发动作');
this._currentState.forEach((T) => this.states[T] && this.states[T]());
return this;
}
}
new SuperMarry()
.change(['jump', 'shoot'])
.go() // 触发动作 跳跃!射击!
.go() // 触发动作 跳跃!射击!
.change(['squat'])
.go(); // 触发动作 蹲下!
```
**优点:**
- 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
- 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
**缺点:**
- 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
- 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
### 6.9 策略模式
> 策略模式 (`Strategy Pattern`):定义一些列算法,把他们封装起来,并且可以相互替换。就是把看似毫无联系的代码提取封装、复用,使之更容易被理解和拓展。常见的用于一次 if 判断、switch 枚举、数据字典等流程判断语句中。也称为政策模式 (`Policy`)。策略模式是一种对象行为型模式。

**举例:**
使用策略模式时,我们可以定义一些策略类,每一个策略类中封装一种具体的算法。在这里,每一个封装算法的类我们都可以称之为一种策略,根据传入不同的策略类,使环境类执行不同策略类中的算法。
在游戏中,我们每玩完一局游戏都有对用户进行等级评价,比如 S 级 4 倍经验,A 级 3 倍经验,B 级 2 倍经验,其他 1 倍经验,用函数来表达如下:
```js
// 改为策略模式 分成两个函数来写
const strategy = {
S: function (experience) {
return 4 * experience;
},
A: function (experience) {
return 3 * experience;
},
B: function (experience) {
return 2 * experience;
},
};
// getExperience 可以复用
function getExperience(strategy, level, experience) {
return level in strategy ? strategy[level](experience) : experience;
}
var s = getExperience(strategy, 'S', 100);
var a = getExperience(strategy, 'A', 100);
console.log(s, a); // 400 300
```
```js
// 指令处理集合
var compileUtil = {
// v-text 更新视图原理
text: function(node, vm, exp) {
this.bind(node, vm, exp, 'text');
},
// v-html 更新视图原理
html: function(node, vm, exp) {
this.bind(node, vm, exp, 'html');
},
// v-class 绑定原理
class: function(node, vm, exp) {
this.bind(node, vm, exp, 'class');
},
bind: function(node, vm, exp, dir) {
// 不同指令触发视图更新
var updaterFn = updater[dir + 'Updater'];
updaterFn && updaterFn(node, this._getVMVal(vm, exp));
new Watcher(vm, exp, function(value, oldValue) {
updaterFn && updaterFn(node, value, oldValue);
});
}
......
}
```
**优点:**
- 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。
- 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合“单一职责原则”,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。
- 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码 (Hard Coding) 在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
- 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。
**缺点:**
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
- 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
- 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。
### 6.10 模板方法模式
> 模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

**举例:**
模板方法模式的使用场景
- 模板方法模式常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员继承框架的结构之后,负责往里面填空
- 钩子方法:各种框架中的钩子函数往往在初始化时就规定各个钩子函数的名称以及执行时机,对于使用者只需要在钩子函数中注入自定义逻辑代码即可
- 回调函数:回调函数在特定的时机执行,但是具体的操作交给具体的函数实现。把变化的部分封装成一个函数剩下的就成了模板
模板方法模式具体应用又分为三类:
- 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。
- 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
- 钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。
泡一杯咖啡
先我们先来泡一杯咖啡,一般来说,泡咖啡的步骤通常如下:
1.先把水煮沸;
2.用沸水冲泡咖啡;
3.把咖啡倒进杯子;
4.加糖和牛奶。
我们用 es5 来得到一杯香浓的咖啡吧:
```js
var Coffee = function () {};
Coffee.prototype.boilWater = function () {
console.log('水煮开了');
};
Coffee.prototype.brewCoffeeGriends = function () {
console.log('用沸水冲泡咖啡');
};
Coffee.prototype.pourInCup = function () {
console.log('把咖啡倒进杯子');
};
Coffee.prototype.addSugarAndMilk = function () {
console.log('加糖和牛奶');
};
// 封装 将实现的细节交给类的内部
Coffee.prototype.init = function () {
this.boilWater();
this.brewCoffeeGriends();
this.pourInCup();
this.addSugarAndMilk();
};
var coffee = new Coffee();
coffee.init();
```
泡一壶茶
其实呢,泡茶的步骤跟泡咖啡的步骤相差不大,大致是这样的:
1.把水煮沸;
2.用沸水浸泡茶叶;
3.把茶水倒进杯子;
4.加柠檬。
来,咱用 es6 来泡茶:
```js
class Tea {
constructor() {}
boilWater() {
console.log('把水烧开');
}
steepTeaBag() {
console.log('浸泡茶叶');
}
pourInCup() {
console.log('倒进杯子');
}
addLemon() {
console.log('加柠檬');
}
init() {
this.boilWater();
this.steepTeaBag();
this.pourInCup();
this.addLemon();
}
}
var tea = new Tea();
tea.init();
```
现在到了思考的时间,我们刚刚泡了一杯咖啡和一壶茶,有没有觉得这两个过程是大同小异的。我们能很容易的就找出他们的共同点,不同点就是原料不同嘛,茶和咖啡,我们可以把他们抽象为"饮料"哇;泡的方式不同嘛,一个是冲泡,一个是浸泡,我们可以把这个行为抽象为"泡";加入的调料也不同咯,加糖和牛奶,加柠檬,它们也可以抽象为"调料"吖。
这么一分析,是不是很清楚了吖,我们整理一下就是:
1.把水煮沸;
2.用沸水冲泡饮料;
3.把饮料倒进杯子;
4.加调料。
大家请注意!大家请注意!主角来了!之前我们已经扔出了概念,所以我们现在可以创建一个抽象父类来表示泡一杯饮料的过程。那么,抽象父类?
抽象类?
抽象类是不能被实例化的,一定是用来继承的。继承了抽象类的所有子类都将拥有跟抽象类一致的接口方法,抽象类的主要作用就是为它的子类定义这些公共接口。
通过上面分析,这里具体来说就是要把泡茶和泡咖啡的共同步骤共同点找出来,封装到父类,也就是抽象类中,然后不同的步骤写在子类中,也就是茶和咖啡中。抽象类既然不能被实例化,不怕啊,子类就是他的实例化。
泡饮料啦!
```js
var Beverage = function () {};
Beverage.prototype.boilWater = function () {
console.log('把水煮沸');
};
Beverage.prototype.brew = function () {};
Beverage.prototype.pourInCup = function () {};
Beverage.prototype.addCondiments = function () {};
// 抽象方法
Beverage.prototype.init = function () {
this.boilWater();
this.brew();
this.pourInCup();
this.addCondiments();
};
var Coffee = function () {
// 将父类的构造方法拿来执行一下
Beverage.apply(this, arguments);
// 就像 es6 的 super 执行 执行后 this 才会有对象的属性
};
Coffee.prototype = new Beverage();
var coffee = new Coffee();
coffee.init();
var Tea = function () {};
Tea.prototype = new Beverage();
Tea.prototype.brew = function () {
console.log('用沸水浸泡茶叶');
};
Tea.prototype.pourInCup = function () {
console.log('把茶叶倒进杯子');
};
Tea.prototype.addCondiments = function () {
console.log('加柠檬');
};
var tea = new Tea();
tea.init();
```
这里既泡了咖啡又泡了茶,是不是没有之前那么繁琐呢,这里的代码可是很高级的呢。
这里用一个父类 Beverage 来表示 Coffee 和 Tea,然后子类就是后面的 Coffee 和 Tea 啦,因为这里的 Beverage 是一个抽象的存在,需要子类来继承它。泡饮品的流程,可以理解为一个模板模式,抽象类 Beverage,抽象方法 init() 在子类中实现。js 的继承是基于原型链的继承,这里 prototype 就是类的原型链。这里由于 coffee 对象和 tea 对象的原型 prototype 上都没有对应的 init(),所以请求会顺着原型链,找到父类 Beverage 的 init()。子类寻找对应的属性和方法的时候会顺着原型链去查找,先找自己,没有找到会顺着去父类里面查找。
Beverage.prototype.init 被称为模板方法的原因是,该方法中封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。
**优点:**
- 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
- 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
- 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
- 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。
**缺点:**
- 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。
### 6.11 访问者模式
> 访问者模式 (`Visitor Pattern`):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

**举例:**
访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。
在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为「对象结构」,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。
```js
// 访问者模式:DOM 事件绑定
var bindEvent = function(dom, type, fn, data) {
if (dom.addEventListener) {
dom.addEventListener(type, fn, false);
} else if (dom.attachEvent) {
// dom.attachEvent('on'+type, fn);
var data = data || {};
dom.attachEvent('on' + type, function(e) {
// 在 IE 中 this 指向 window,使用 call 改变 this 的指向
fn.call(dom, e, data);
});
} else {
dom['on' + type] = fn;
}
}
function $(id) {
return document.getElementById(id);
}
bindEvent($(demo), 'click', function() {
// this 指向 dom 对象
this.style.background = 'red';
});
bindEvent($('btn'), 'click', function(e, data) {
$('text').innerHTML = e.type + data.text + this.tagName;
}, { text: 'demo' });
```
访问者模式的思想就是在不改变操作对象的同时,为它添加新的操作方法,以实现对操作对象的访问。我们知道,call 和 apply 的作用就是更改函数执行时的作用域,这正是访问者模式的精髓。通过 call、apply 这两种方式我们就可以让某个对象在其它作用域中运行。
```js
// 数组方法封装
var Visitor = (function() {
return {
splice: function() {
var args = Array.prototype.splice.call(arguments, 1);
return Array.prototype.splice.apply(arguments[0], args);
},
push: function() {
var len = arguments[0].length || 0;
var args = this.splice(arguments, 1);
arguments[0].length = len + arguments.length - 1;
return Array.prototype.push.apply(arguments[0], args);
},
pop: function() {
return Array.prototype.pop.apply(arguments[0]);
}
}
})();
var a = new Object();
Visitor.push(a,1,2,3,4);
Visitor.push(a,4,5,6);
Visitor.pop(a);
Visitor.splice(a,2);
```
访问者模式解决了数据与数据的操作方法之间的耦合,让数据的操作方法独立于数据,使其可以自由演变。因此,访问者模式更适合于那些数据稳定、但数据的操作方法易变的环境下。
**优点:**
- 增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
- 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
- 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。
**缺点:**
- 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
- 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。
## 总结
系统地学习设计模式后,你可以在过往的开发经历中发现,设计模式是无处不在的。在学习设计模式之前的很多时候我们是凭借过往经验和智慧来完善系统的设计,而这些经验很多和某个设计模式的思想不谋而合。
还有一些地方没有完全理解,文中有误之处还望不吝指出。
## 参考资料
- [Study-Plan](https://github.com/xietao3/Study-Plan)
- [javaScript 设计模式统计](https://zhuanlan.zhihu.com/p/472719016)
- [ES6 系列之我们来聊聊装饰器](https://juejin.cn/post/6844903713866252296)
- [设计模式之生成器模式](https://segmentfault.com/a/1190000038250020)
- [https://juejin.im/user/57f8ffda2e958a005581e3c0/posts](https://juejin.im/user/57f8ffda2e958a005581e3c0/posts)
- [https://design-patterns.readthedocs.io/zh_CN/latest/index.html](https://design-patterns.readthedocs.io/zh_CN/latest/index.html)
- [https://blog.csdn.net/lovelion/article/details/17517213](https://blog.csdn.net/lovelion/article/details/17517213)
- [https://github.com/skyming/Trip-to-iOS-Design-Patterns](https://github.com/skyming/Trip-to-iOS-Design-Patterns)
================================================
FILE: packages/docs/cn/src/article/doc_preview.md
================================================
<h1> 最全的 docx,pptx,xlsx(excel),pdf 文件预览方案总结 </h1>
最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下
1. 花钱解决 (使用市面上现有的文件预览服务)
1. 微软
2. google
3. 阿里云 IMM
4. XDOC
5. Office Web 365
6. wps 开放平台
2. 前端方案
1. pptx 的预览方案
2. pdf 的预览方案
3. docx 的预览方案
4. xlsx(excel) 的预览方案
5. 前端预览方案总结
3. 服务端方案
1. openOffice
2. kkFileView
3. onlyOffice
如果有其他人也遇到了同样的问题,有了这篇文章,希望能更方便的解决。
基本涵盖了所有解决方案。因此,标题写上 **最全** 的文件预览方案调研总结,应该不为过吧。
## 一:市面上现有的文件预览服务
### 1.微软
`docx`,`pptx`,`xlsx`可以说是`office`三件套,那自然得看一下 **微软官方** 提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。
记得`encodeURL`
```js
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}
```
#### (1).PPTX 预览效果:

- 优点:还原度很高,功能很丰富,可以选择翻页,甚至支持点击播放动画。
- 缺点:不知道是不是墙的原因,加载稍慢。
#### (2).Excel 预览效果:

#### (3).Doxc 预览效果

#### (4).PDF 预览效果
这个我测试没有成功,返回了一个错误,其他人可以试试。

#### (5).总的来说
对于`docx`,`pptx`,`xlsx`都有较好的支持,`pdf`不行。
还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在`office`官方网站上甚至找不到介绍这个东西的地方。
目前只能找到一个`Q&A`:https://answers.microsoft.com/en-us/msoffice/forum/all/what-is-the-status-of-viewofficeappslivecom/830fd75c-9b47-43f9-89c9-4303703fd7f6
微软官方人员回答表示:

翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件`10MB`,建议用于 **查看互联网上公开的文件**。
但经过某些用户测试发现:

使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间会失效。
### 2.Google Drive 查看器
接入简单,同 `Office Web Viewer`,只需要把 `src` 改为`https://drive.google.com/viewer?url=${encodeURIComponent(url)}`即可。
限制`25MB`,支持以下格式:

测试效果,支持`docx,pptx,xlsx,pdf`预览,但`pptx`预览的效果不如微软,没有动画效果,样式有小部分会错乱。
**由于某些众所周知的原因,不可用**
### 3.阿里云 IMM
官方文档如下:https://help.aliyun.com/document_detail/63273.html

付费使用
### 4.XDOC 文档预览
说了一些大厂的,在介绍一些其他的,**需要自行分辨**
官网地址:https://view.xdocin.com/view-xdocin-com_6x5f4x.htm

### 5.Office Web 365
需要注意的是,虽然名字很像`office`,但我们看网页的`Copyright`可以发现,其实是一个西安的公司,**不是微软**。
但毕竟也提供了文件预览的服务
官网地址:https://www.officeweb365.com/

### 6.WPS 开放平台
官方地址:https://solution.wps.cn/

付费使用,价格如下:

## 二:前端处理方案
### 1.pptx 的预览方案
先查一下有没有现成的轮子,目前`pptx`的开源预览方案能找到的只有这个:https://github.com/g21589/PPTX2HTML。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。
简单来说就是,没有。对于这种情况,我们可以自行解析,主要步骤如下:
1. 查询`pptx`的国际标准
2. 解析`pptx`文件
3. 渲染成`html`或者`canvas`进行展示
我们先去找一下`pptx`的国际标准,官方地址:[officeopenxml](http://officeopenxml.com/)
先解释下什么是`officeopenxml`:
> Office OpenXML,也称为 OpenXML 或 OOXML,是一种基于 XML 的办公文档格式,包括文字处理文档、电子表格、演示文稿以及图表、图表、形状和其他图形材料。该规范由微软开发,并于 2006 年被 ECMA 国际采用为 ECMA-376。第二个版本于 2008 年 12 月发布,第三个版本于 2011 年 6 月发布。该规范已被 ISO 和 IEC 采用为 ISO/IEC 29500。
> 虽然 Microsoft 继续支持较旧的二进制格式 (.doc、.xls 和.ppt),但 OOXML 现在是所有 Microsoft Office 文档 (.docx、.xlsx 和.pptx) 的默认格式。
由此可见,`Office OpenXML`由微软开发,目前已经是国际标准。接下来我们看一下`pptx`里面有哪些内容,具体可以看`pptx`的官方标准:[officeopenxml-pptx](http://officeopenxml.com/anatomyofOOXML-pptx.php)
> PresentationML 或.pptx 文件是一个**zip 文件**,其中包含许多“部分”(通常是 UTF-8 或 UTF-16 编码)或 XML 文件。该包还可能包含其他媒体文件,例如图像。该结构根据 OOXML 标准 ECMA-376 第 2 部分中概述的开放打包约定进行组织。

根据国际标准,我们知道,`pptx`文件本质就是一个`zip`文件,其中包含许多部分:
> 部件的数量和类型将根据演示文稿中的内容而有所不同,但始终会有一个 [Content_Types].xml、一个或多个关系(.rels)部件和一个演示文稿部件(演示文稿.xml),它位于 ppt 文件夹中,用于 Microsoft Powerpoint 文件。通常,还将至少有一个幻灯片部件,以及一张母版幻灯片和一张版式幻灯片,从中形成幻灯片。
那么`js`如何读取`zip`呢?
找到一个工具:https://www.npmjs.com/package/jszip
于是我们可以开始尝试解析`pptx`了。
```ts
import JSZip from 'jszip';
// 加载 pptx 数据
const zip = await JSZip.loadAsync(pptxData);
```
- 解析`[Content_Types].xml`
每个`pptx`必然会有一个 `[Content_Types].xml`。此文件包含包中部件的所有内容类型的列表。每个部件及其类型都必须列在 `[Content_Types].xml` 中。通过它里面的内容,可以解析其他的文件数据
```ts
const filesInfo = await getContentTypes(zip);
async function getContentTypes(zip: JSZip) {
const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
const subObj = ContentTypesJson['Types']['Override'];
const slidesLocArray = [];
const slideLayoutsLocArray = [];
for (let i = 0; i < subObj.length; i++) {
switch (subObj[i]['attrs']['ContentType']) {
case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
slidesLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
break;
case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
break;
default:
}
}
return {
slides: slidesLocArray,
slideLayouts: slideLayoutsLocArray,
};
}
```
- 解析演示文稿
先获取`ppt`目录下的`presentation.xml`演示文稿的大小
由于演示文稿是`xml`格式,要真正的读取内容需要执行 `readXmlFile`
```ts
const slideSize = await getSlideSize(zip);
async function getSlideSize(zip: JSZip) {
const content = await readXmlFile(zip, 'ppt/presentation.xml');
const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs'];
return {
width: (parseInt(sldSzAttrs['cx']) * 96) / 914400,
height: (parseInt(sldSzAttrs['cy']) * 96) / 914400,
};
}
```
- 加载主题
根据 `officeopenxml`的标准解释
> 每个包都包含一个关系部件,用于定义其他部件之间的关系以及与包外部资源的关系。这样可以将关系与内容分开,并且可以轻松地更改关系,而无需更改引用目标的源。
> 除了包的关系部分之外,作为一个或多个关系源的每个部件都有自己的关系部分。每个这样的关系部件都可以在部件的\_rels 子文件夹中找到,并通过在部件名称后附加“.rels”来命名。
其中主题的相关信息就在`ppt/_rels/presentation.xml.rels`中
```ts
async function loadTheme(zip: JSZip) {
const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels');
const relationshipArray = preResContent['Relationships']['Relationship'];
let themeURI;
if (relationshipArray.constructor === Array) {
for (let i = 0; i < relationshipArray.length; i++) {
if (
relationshipArray[i]['attrs']['Type'] ===
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
) {
themeURI = relationshipArray[i]['attrs']['Target'];
break;
}
}
} else if (
relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
) {
themeURI = relationshipArray['attrs']['Target'];
}
if (themeURI === undefined) {
throw Error("Can't open theme file.");
}
return readXmlFile(zip, 'ppt/' + themeURI);
}
```
后续`ppt`里面的其他内容,都可以这么去解析。根据`officeopenxml`标准,可能包含:
Part | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Comments Authors | Contains information about each author who has added a comment to the presentation. |
| Comments | Contains comments for a single slide. |
| Handout Master | Contains the look, position, and size of the slides, notes, header and footer text, date, or page number on the presentation's handout. There can be only one such part. |
| Notes Master | Contains information about the content and formatting of all notes pages. There can be only one such part. |
| Notes Slide | Contains the notes for a single slide. |
| Presentation | Contains the definition of a slide presentation. There must be one and only one such part. See [Presentation](http://officeopenxml.com/PrPresentation.php). |
| Presentation Properties | Contains all of the presentation's properties. There must be one and only one such part. |
| Slide | Contains the content of a single slide. |
| Slide Layout | Contains the definition for a slide template. It defines the default appearance and positioning of drawing objects on the slide. There must be one or more such parts. |
| Slide Master | Contains the master definition of formatting, text, and objects that appear on each slide in the presentation that is derived from the slide master. There must be one or more such parts. |
| Slide Synchronization Data | Contains properties specifying the current state of a slide that is being synchronized with a version of the slide stored on a central server. |
| User-Defined Tags | Contains a set of user-defined properties for an object in a presentation. There can be zero or more such parts. |
| View Properties | Contains display properties for the presentation.
等等内容,我们根据标准一点点解析并渲染就好了。
完整源码:[ranui](https://github.com/chaxus/ran/tree/main/packages/ranui)
使用文档:[preview 组件](https://chaxus.github.io/ran/src/ranui/preview/)
### 2.pdf 的预览方案
#### (1).iframe 和 embed
`pdf`比较特别,一般的浏览器默认支持预览`pdf`。因此,我们可以使用浏览器的能力:
```html
<iframe src="viewFileUrl" />
```
但这样就完全依赖浏览器,对`PDF`的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。
`embed`的解析方式也是一样,这里不举例子了
#### (2)pdfjs
npm: <https://www.npmjs.com/package/pdfjs-dist>
github 地址:<https://github.com/mozilla/pdfjs-dist>
由`mozilla`出品,就是我们常见的`MDN`的老大。
而且目前 火狐浏览器 使用的 PDF 预览就是采用这个,我们可以用火狐浏览器打开`pdf`文件,查看浏览器使用的`js`就能发现

需要注意的是,最新版`pdf.js`限制了`node`版本,需要大于等于`18`
github 链接:https://github.com/mozilla/pdf.js/blob/master/package.json

如果你项目`node`版本小于这个情况,可能会无法使用。
如果遇到这种情况,可以用以前版本,以前的版本没有限制。
具体使用情况如下:
- 完整源码:https://github.com/chaxus/ran/tree/main/packages/ranui
- 使用文档:https://chaxus.github.io/ran/src/ranui/preview/
```ts
import * as pdfjs from 'pdfjs-dist';
import * as pdfjsWorker from 'pdfjs-dist/build/pdf.work.entry';
interface Viewport {
width: number;
height: number;
viewBox: Array<number>;
}
interface RenderContext {
canvasContext: CanvasRenderingContext2D | null;
transform: Array<number>;
viewport: Viewport;
}
interface PDFPageProxy {
pageNumber: number;
getViewport: () => Viewport;
render: (options: RenderContext) => void;
}
interface PDFDocumentProxy
gitextract_yjd90j70/ ├── .editorconfig ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── ci.yml │ ├── pages-build-site.yml │ └── semantic-pull-request.yml ├── .gitignore ├── .jscpd.json ├── .prettierignore ├── .prettierrc.json ├── .vscode/ │ ├── c_cpp_properties.json │ ├── launch.json │ ├── markdown.code-snippets │ ├── ranui-components.code-snippets │ ├── settings.json │ └── ts.json.code-snippets ├── LICENSE ├── SECURITY.md ├── bin/ │ ├── build.sh │ ├── clean.sh │ ├── install.sh │ ├── lint.sh │ ├── nvm.sh │ ├── preinstall.sh │ └── test.sh ├── eslint.config.js ├── index.html ├── package.json ├── packages/ │ ├── cpro/ │ │ ├── package.json │ │ ├── readme.md │ │ └── sum.cpp │ ├── debug/ │ │ ├── koaStatic/ │ │ │ ├── index.ts │ │ │ └── readme.md │ │ ├── nginxconf/ │ │ │ ├── agency.conf │ │ │ └── readme.md │ │ ├── package.json │ │ └── tsconfig.json │ ├── docs/ │ │ ├── .vitepress/ │ │ │ ├── common/ │ │ │ │ ├── index.ts │ │ │ │ └── sw.ts │ │ │ ├── components/ │ │ │ │ ├── Layout.vue │ │ │ │ └── TOTP.vue │ │ │ ├── composition/ │ │ │ │ └── useBasic.ts │ │ │ ├── config.ts │ │ │ ├── lang/ │ │ │ │ ├── en.json │ │ │ │ ├── index.ts │ │ │ │ └── zh-CN.json │ │ │ ├── langs/ │ │ │ │ ├── cn/ │ │ │ │ │ └── index.ts │ │ │ │ └── en/ │ │ │ │ └── index.ts │ │ │ ├── lib/ │ │ │ │ └── constant.ts │ │ │ ├── plugins/ │ │ │ │ └── env.ts │ │ │ └── theme/ │ │ │ ├── index.ts │ │ │ ├── styles/ │ │ │ │ ├── index.less │ │ │ │ └── vars.less │ │ │ └── theme.less │ │ ├── bin/ │ │ │ └── build.sh │ │ ├── cn/ │ │ │ ├── index.md │ │ │ └── src/ │ │ │ ├── article/ │ │ │ │ ├── ai/ │ │ │ │ │ └── index.md │ │ │ │ ├── ast_parse/ │ │ │ │ │ └── tokenizer.md │ │ │ │ ├── babel.md │ │ │ │ ├── bundle.md │ │ │ │ ├── design_mode.md │ │ │ │ ├── doc_preview.md │ │ │ │ ├── functional_programming.md │ │ │ │ ├── imagemin.md │ │ │ │ ├── javascript/ │ │ │ │ │ └── dom_load.md │ │ │ │ ├── math/ │ │ │ │ │ └── linear_algebra.md │ │ │ │ ├── sort/ │ │ │ │ │ ├── bubble/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── bucket/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── count/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── heap/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── index.md │ │ │ │ │ ├── insert/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── merge/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── quick/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── radix/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── select/ │ │ │ │ │ │ └── index.md │ │ │ │ │ └── shell/ │ │ │ │ │ └── index.md │ │ │ │ ├── system_design.md │ │ │ │ ├── typescript/ │ │ │ │ │ ├── calculate.md │ │ │ │ │ ├── index.md │ │ │ │ │ ├── pattern.md │ │ │ │ │ ├── reconstruction.md │ │ │ │ │ ├── recursion.md │ │ │ │ │ └── union_type.md │ │ │ │ ├── video.md │ │ │ │ └── visual.md │ │ │ ├── blockchain/ │ │ │ │ ├── index.md │ │ │ │ └── web3.md │ │ │ ├── note/ │ │ │ │ ├── centos.md │ │ │ │ ├── docker.md │ │ │ │ ├── libreoffice2wasm.md │ │ │ │ └── ubuntu.md │ │ │ ├── ranui/ │ │ │ │ ├── button/ │ │ │ │ │ └── index.md │ │ │ │ ├── checkbox/ │ │ │ │ │ └── index.md │ │ │ │ ├── icon/ │ │ │ │ │ └── index.md │ │ │ │ ├── image/ │ │ │ │ │ └── index.md │ │ │ │ ├── index.md │ │ │ │ ├── input/ │ │ │ │ │ └── index.md │ │ │ │ ├── loading/ │ │ │ │ │ └── index.md │ │ │ │ ├── math/ │ │ │ │ │ └── index.md │ │ │ │ ├── message/ │ │ │ │ │ └── index.md │ │ │ │ ├── modal/ │ │ │ │ │ └── index.md │ │ │ │ ├── player/ │ │ │ │ │ └── index.md │ │ │ │ ├── popover/ │ │ │ │ │ └── index.md │ │ │ │ ├── preview/ │ │ │ │ │ └── index.md │ │ │ │ ├── progress/ │ │ │ │ │ └── index.md │ │ │ │ ├── radar/ │ │ │ │ │ └── index.md │ │ │ │ ├── select/ │ │ │ │ │ └── index.md │ │ │ │ ├── skeleton/ │ │ │ │ │ └── index.md │ │ │ │ ├── tab/ │ │ │ │ │ └── index.md │ │ │ │ └── tabs/ │ │ │ │ └── index.md │ │ │ ├── ranuts/ │ │ │ │ ├── binary_tree/ │ │ │ │ │ └── index.md │ │ │ │ ├── bundler/ │ │ │ │ │ └── index.md │ │ │ │ ├── file/ │ │ │ │ │ ├── append_file.md │ │ │ │ │ ├── file_info.md │ │ │ │ │ ├── read_dir.md │ │ │ │ │ ├── read_file.md │ │ │ │ │ ├── watch_file.md │ │ │ │ │ └── write_file.md │ │ │ │ ├── index.md │ │ │ │ ├── mime_type/ │ │ │ │ │ └── mime_type.md │ │ │ │ ├── mode/ │ │ │ │ │ └── subscribe.md │ │ │ │ └── utils/ │ │ │ │ ├── add_class_to_element.md │ │ │ │ ├── add_num_sym.md │ │ │ │ ├── append_url.md │ │ │ │ ├── chain.md │ │ │ │ ├── change_hump_to_lower_case.md │ │ │ │ ├── check_encoding.md │ │ │ │ ├── clear_br.md │ │ │ │ ├── clear_str.md │ │ │ │ ├── clone_deep.md │ │ │ │ ├── compose.md │ │ │ │ ├── connection.md │ │ │ │ ├── convert_image_to_base64.md │ │ │ │ ├── create.md │ │ │ │ ├── create_document_fragment.md │ │ │ │ ├── create_object_url.md │ │ │ │ ├── create_signal.md │ │ │ │ ├── current_device.md │ │ │ │ ├── debounce.md │ │ │ │ ├── duration_handler.md │ │ │ │ ├── encode_url.md │ │ │ │ ├── escape_html.md │ │ │ │ ├── filter_obj.md │ │ │ │ ├── format_json.md │ │ │ │ ├── get_all_query_string.md │ │ │ │ ├── get_cookie.md │ │ │ │ ├── get_cookie_by_name.md │ │ │ │ ├── get_extensions.md │ │ │ │ ├── get_frame.md │ │ │ │ ├── get_host.md │ │ │ │ ├── get_matching_sentences.md │ │ │ │ ├── get_performance.md │ │ │ │ ├── get_pixel_ratio.md │ │ │ │ ├── get_query.md │ │ │ │ ├── get_window.md │ │ │ │ ├── handle_console.md │ │ │ │ ├── handle_error.md │ │ │ │ ├── handle_fetch_hook.md │ │ │ │ ├── hex_to_rgb.md │ │ │ │ ├── image_request.md │ │ │ │ ├── index.md │ │ │ │ ├── is_bang_device.md │ │ │ │ ├── is_client.md │ │ │ │ ├── is_equal.md │ │ │ │ ├── is_image_size.md │ │ │ │ ├── is_mobile.md │ │ │ │ ├── is_safari.md │ │ │ │ ├── is_string.md │ │ │ │ ├── is_weixin.md │ │ │ │ ├── local_storage.md │ │ │ │ ├── mathjs.md │ │ │ │ ├── md5.md │ │ │ │ ├── memoize.md │ │ │ │ ├── merge.md │ │ │ │ ├── network_speed.md │ │ │ │ ├── noop.md │ │ │ │ ├── ocr.md │ │ │ │ ├── per_to_num.md │ │ │ │ ├── performance_time.md │ │ │ │ ├── querystring.md │ │ │ │ ├── random_color.md │ │ │ │ ├── random_string.md │ │ │ │ ├── range.md │ │ │ │ ├── remove_class_to_element.md │ │ │ │ ├── remove_ghosting.md │ │ │ │ ├── retain.md │ │ │ │ ├── rgb_to_hex.md │ │ │ │ ├── script_on_load.md │ │ │ │ ├── set_attribute_by_global.md │ │ │ │ ├── set_mime.md │ │ │ │ ├── str2xml.md │ │ │ │ ├── str_parse.md │ │ │ │ ├── sync_hook.md │ │ │ │ ├── task.md │ │ │ │ ├── throttle.md │ │ │ │ ├── time_format.md │ │ │ │ ├── timestamp_to_time.md │ │ │ │ ├── to_string.md │ │ │ │ ├── totp.md │ │ │ │ ├── transform_number.md │ │ │ │ └── transform_text.md │ │ │ └── types/ │ │ │ ├── TS类型.md │ │ │ ├── 模式匹配.md │ │ │ ├── 类型运算.md │ │ │ └── 高级类型.md │ │ ├── index.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── hls/ │ │ │ │ ├── 5_1701577744714/ │ │ │ │ │ ├── 5.key │ │ │ │ │ ├── 5.m3u8 │ │ │ │ │ ├── 5_00000.ts │ │ │ │ │ ├── 5_00001.ts │ │ │ │ │ ├── 5_00002.ts │ │ │ │ │ ├── 5_00003.ts │ │ │ │ │ ├── 5_00004.ts │ │ │ │ │ ├── 5_00005.ts │ │ │ │ │ └── 5_00006.ts │ │ │ │ ├── 5_1701577771368/ │ │ │ │ │ ├── 5.key │ │ │ │ │ ├── 5.m3u8 │ │ │ │ │ ├── 5_00000.ts │ │ │ │ │ ├── 5_00001.ts │ │ │ │ │ ├── 5_00002.ts │ │ │ │ │ ├── 5_00003.ts │ │ │ │ │ ├── 5_00004.ts │ │ │ │ │ ├── 5_00005.ts │ │ │ │ │ └── 5_00006.ts │ │ │ │ └── example.m3u8 │ │ │ ├── manifest.json │ │ │ └── sw.js │ │ ├── src/ │ │ │ ├── article/ │ │ │ │ ├── ast_parse/ │ │ │ │ │ └── tokenizer.md │ │ │ │ ├── babel.md │ │ │ │ ├── bundle.md │ │ │ │ ├── design_mode.md │ │ │ │ ├── functional_programming.md │ │ │ │ ├── imagemin.md │ │ │ │ ├── javascript/ │ │ │ │ │ └── dom_load.md │ │ │ │ ├── sort/ │ │ │ │ │ ├── bubble/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── bucket/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── count/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── heap/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── index.md │ │ │ │ │ ├── insert/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── merge/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── quick/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── radix/ │ │ │ │ │ │ └── index.md │ │ │ │ │ ├── select/ │ │ │ │ │ │ └── index.md │ │ │ │ │ └── shell/ │ │ │ │ │ └── index.md │ │ │ │ └── typescript/ │ │ │ │ ├── calculate.md │ │ │ │ ├── index.md │ │ │ │ ├── pattern.md │ │ │ │ ├── reconstruction.md │ │ │ │ ├── recursion.md │ │ │ │ └── union_type.md │ │ │ ├── ranui/ │ │ │ │ ├── button/ │ │ │ │ │ └── index.md │ │ │ │ ├── checkbox/ │ │ │ │ │ └── index.md │ │ │ │ ├── icon/ │ │ │ │ │ └── index.md │ │ │ │ ├── image/ │ │ │ │ │ └── index.md │ │ │ │ ├── index.md │ │ │ │ ├── input/ │ │ │ │ │ └── index.md │ │ │ │ ├── loading/ │ │ │ │ │ └── index.md │ │ │ │ ├── math/ │ │ │ │ │ └── index.md │ │ │ │ ├── message/ │ │ │ │ │ └── index.md │ │ │ │ ├── modal/ │ │ │ │ │ └── index.md │ │ │ │ ├── player/ │ │ │ │ │ └── index.md │ │ │ │ ├── popover/ │ │ │ │ │ └── index.md │ │ │ │ ├── preview/ │ │ │ │ │ └── index.md │ │ │ │ ├── progress/ │ │ │ │ │ └── index.md │ │ │ │ ├── radar/ │ │ │ │ │ └── index.md │ │ │ │ ├── select/ │ │ │ │ │ └── index.md │ │ │ │ ├── skeleton/ │ │ │ │ │ └── index.md │ │ │ │ ├── tab/ │ │ │ │ │ └── index.md │ │ │ │ └── tabs/ │ │ │ │ └── index.md │ │ │ ├── ranuts/ │ │ │ │ ├── binary_tree/ │ │ │ │ │ └── index.md │ │ │ │ ├── bundler/ │ │ │ │ │ └── index.md │ │ │ │ ├── file/ │ │ │ │ │ ├── append_file.md │ │ │ │ │ ├── file_info.md │ │ │ │ │ ├── read_dir.md │ │ │ │ │ ├── read_file.md │ │ │ │ │ ├── watch_file.md │ │ │ │ │ └── write_file.md │ │ │ │ ├── index.md │ │ │ │ ├── mime_type/ │ │ │ │ │ └── mime_type.md │ │ │ │ ├── mode/ │ │ │ │ │ └── subscribe.md │ │ │ │ └── utils/ │ │ │ │ ├── add_class_to_element.md │ │ │ │ ├── add_num_sym.md │ │ │ │ ├── append_url.md │ │ │ │ ├── chain.md │ │ │ │ ├── change_hump_to_lower_case.md │ │ │ │ ├── check_encoding.md │ │ │ │ ├── clear_br.md │ │ │ │ ├── clear_str.md │ │ │ │ ├── clone_deep.md │ │ │ │ ├── compose.md │ │ │ │ ├── connection.md │ │ │ │ ├── convert_image_to_base64.md │ │ │ │ ├── create.md │ │ │ │ ├── create_document_fragment.md │ │ │ │ ├── create_object_url.md │ │ │ │ ├── create_signal.md │ │ │ │ ├── current_device.md │ │ │ │ ├── debounce.md │ │ │ │ ├── duration_handler.md │ │ │ │ ├── encode_url.md │ │ │ │ ├── escape_html.md │ │ │ │ ├── filter_obj.md │ │ │ │ ├── format_json.md │ │ │ │ ├── get_all_query_string.md │ │ │ │ ├── get_cookie.md │ │ │ │ ├── get_cookie_by_name.md │ │ │ │ ├── get_extensions.md │ │ │ │ ├── get_frame.md │ │ │ │ ├── get_host.md │ │ │ │ ├── get_matching_sentences.md │ │ │ │ ├── get_performance.md │ │ │ │ ├── get_pixel_ratio.md │ │ │ │ ├── get_query.md │ │ │ │ ├── get_window.md │ │ │ │ ├── handle_console.md │ │ │ │ ├── handle_error.md │ │ │ │ ├── handle_fetch_hook.md │ │ │ │ ├── hex_to_rgb.md │ │ │ │ ├── image_request.md │ │ │ │ ├── index.md │ │ │ │ ├── is_bang_device.md │ │ │ │ ├── is_client.md │ │ │ │ ├── is_equal.md │ │ │ │ ├── is_image_size.md │ │ │ │ ├── is_mobile.md │ │ │ │ ├── is_safari.md │ │ │ │ ├── is_string.md │ │ │ │ ├── is_weixin.md │ │ │ │ ├── local_storage.md │ │ │ │ ├── mathjs.md │ │ │ │ ├── md5.md │ │ │ │ ├── memoize.md │ │ │ │ ├── merge.md │ │ │ │ ├── network_speed.md │ │ │ │ ├── noop.md │ │ │ │ ├── ocr.md │ │ │ │ ├── per_to_num.md │ │ │ │ ├── performance_time.md │ │ │ │ ├── querystring.md │ │ │ │ ├── random_color.md │ │ │ │ ├── random_string.md │ │ │ │ ├── range.md │ │ │ │ ├── remove_class_to_element.md │ │ │ │ ├── remove_ghosting.md │ │ │ │ ├── retain.md │ │ │ │ ├── rgb_to_hex.md │ │ │ │ ├── script_on_load.md │ │ │ │ ├── set_attribute_by_global.md │ │ │ │ ├── set_mime.md │ │ │ │ ├── str2xml.md │ │ │ │ ├── str_parse.md │ │ │ │ ├── sync_hook.md │ │ │ │ ├── task.md │ │ │ │ ├── throttle.md │ │ │ │ ├── time_format.md │ │ │ │ ├── timestamp_to_time.md │ │ │ │ ├── to_string.md │ │ │ │ ├── totp.md │ │ │ │ ├── transform_number.md │ │ │ │ └── transform_text.md │ │ │ └── types/ │ │ │ ├── TS类型.md │ │ │ ├── 模式匹配.md │ │ │ ├── 类型运算.md │ │ │ └── 高级类型.md │ │ ├── tsconfig.json │ │ ├── typings.d.ts │ │ ├── variable/ │ │ │ └── SERVICE_WORK_VERSION.ts │ │ └── vue/ │ │ └── loading.vue │ ├── im/ │ │ ├── app/ │ │ │ ├── controllers/ │ │ │ │ ├── home.ts │ │ │ │ ├── im.ts │ │ │ │ └── user.ts │ │ │ ├── index.ts │ │ │ ├── lib/ │ │ │ │ ├── constant.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── request.ts │ │ │ │ ├── response.ts │ │ │ │ └── vite.ts │ │ │ ├── router.config.ts │ │ │ ├── routes.ts │ │ │ └── types/ │ │ │ └── index.ts │ │ ├── bin/ │ │ │ └── dev.sh │ │ ├── client/ │ │ │ ├── app.tsx │ │ │ ├── assets/ │ │ │ │ └── base.css │ │ │ ├── client.tsx │ │ │ ├── components/ │ │ │ │ ├── backdrop/ │ │ │ │ │ ├── index.module.less │ │ │ │ │ └── index.tsx │ │ │ │ └── loading/ │ │ │ │ ├── index.module.less │ │ │ │ └── index.tsx │ │ │ ├── lib/ │ │ │ │ ├── eventSource.ts │ │ │ │ ├── hook.ts │ │ │ │ └── index.ts │ │ │ ├── pages/ │ │ │ │ └── home/ │ │ │ │ └── index.tsx │ │ │ ├── router/ │ │ │ │ └── index.tsx │ │ │ └── server.tsx │ │ ├── package.json │ │ ├── readme.md │ │ ├── rest/ │ │ │ └── user.rest │ │ ├── tsconfig.json │ │ ├── typings.d.ts │ │ ├── views/ │ │ │ └── index.html │ │ └── vite.config.ts │ ├── image-process/ │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── CMakeUserPresets.json │ │ ├── conanfile.txt │ │ ├── index.ts │ │ ├── main.c │ │ ├── makefile │ │ ├── package.json │ │ ├── readme.md │ │ └── src/ │ │ ├── image_processing.c │ │ └── image_processing.h │ ├── ml/ │ │ ├── assets/ │ │ │ ├── dataset/ │ │ │ │ ├── ChnSentiCorp_htl_all.csv │ │ │ │ ├── kc_house_data.csv │ │ │ │ └── min_label_review.csv │ │ │ └── ebook/ │ │ │ └── txt/ │ │ │ ├── JaneEyre.txt │ │ │ ├── TheHunchbackofNotre-Dame.txt │ │ │ ├── camelXiangzi.txt │ │ │ ├── princekin.txt │ │ │ ├── shakespeare.txt │ │ │ ├── snowWhite.txt │ │ │ ├── theThreeKingdoms.txt │ │ │ ├── theWealthOfNations.txt │ │ │ ├── training_data_1748151735437.json │ │ │ └── walden.txt │ │ ├── bin/ │ │ │ └── build.sh │ │ ├── client/ │ │ │ ├── components/ │ │ │ │ ├── BinaryModel.tsx │ │ │ │ ├── Emotion.tsx │ │ │ │ ├── LineModel.tsx │ │ │ │ └── MultiModel.tsx │ │ │ ├── index.tsx │ │ │ └── lib.ts │ │ ├── config/ │ │ │ ├── build.es.ts │ │ │ └── build.umd.ts │ │ ├── index.html │ │ ├── index.ts │ │ ├── package.json │ │ ├── readme.md │ │ ├── server/ │ │ │ └── index.ts │ │ ├── src/ │ │ │ └── ebook/ │ │ │ ├── index.ts │ │ │ └── trainData.ts │ │ ├── tsconfig.json │ │ ├── typings.d.ts │ │ └── vite.config.ts │ ├── precss/ │ │ └── sass/ │ │ ├── _base.scss │ │ ├── _function.scss │ │ └── styles/ │ │ ├── animation.scss │ │ ├── common.scss │ │ ├── global.css │ │ ├── mixin/ │ │ │ ├── bangs.scss │ │ │ ├── ellipsis.scss │ │ │ ├── index.scss │ │ │ ├── make-animation.scss │ │ │ ├── px2rem.scss │ │ │ ├── screen.scss │ │ │ ├── supports-safe-area-insets.scss │ │ │ └── thinBorder.scss │ │ ├── themes.scss │ │ └── variables.scss │ ├── ranite/ │ │ ├── bin/ │ │ │ └── ranite │ │ ├── package.json │ │ ├── readme.md │ │ ├── src/ │ │ │ ├── client/ │ │ │ │ └── client.ts │ │ │ └── node/ │ │ │ ├── ModuleGraph.ts │ │ │ ├── cli.ts │ │ │ ├── constants.ts │ │ │ ├── hmr.ts │ │ │ ├── optimizer/ │ │ │ │ ├── index.ts │ │ │ │ ├── preBundlePlugin.ts │ │ │ │ └── scanPlugin.ts │ │ │ ├── plugin.ts │ │ │ ├── pluginContainer.ts │ │ │ ├── plugins/ │ │ │ │ ├── assets.ts │ │ │ │ ├── clientInject.ts │ │ │ │ ├── css.ts │ │ │ │ ├── esbuild.ts │ │ │ │ ├── importAnalysis.ts │ │ │ │ ├── index.ts │ │ │ │ ├── react-hmr.ts │ │ │ │ └── resolve.ts │ │ │ ├── server/ │ │ │ │ ├── index.ts │ │ │ │ └── middlewares/ │ │ │ │ ├── indexHtml.ts │ │ │ │ ├── static.ts │ │ │ │ └── transform.ts │ │ │ ├── server.ts │ │ │ ├── utils.ts │ │ │ └── ws.ts │ │ ├── tsconfig.json │ │ └── tsup.config.ts │ ├── ranui/ │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── README.zh-CN.md │ │ ├── assets/ │ │ │ ├── image/ │ │ │ │ └── failImage.ts │ │ │ └── js/ │ │ │ ├── hls.js │ │ │ └── katex/ │ │ │ ├── katex-es-core.js │ │ │ └── katex-es.js │ │ ├── babel.config.cjs │ │ ├── base.less │ │ ├── bin/ │ │ │ ├── build.sh │ │ │ └── test.sh │ │ ├── build/ │ │ │ ├── config.es.ts │ │ │ ├── config.sha.ts │ │ │ ├── config.ts │ │ │ └── config.umd.ts │ │ ├── components/ │ │ │ ├── button/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── checkbox/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── colorpicker/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── dropdown/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── form/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── icon/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── image/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── input/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── loading/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── math/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── message/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── modal/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── player/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── popover/ │ │ │ │ ├── content/ │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.ts │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── progress/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── radar/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── scratch/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── select/ │ │ │ │ ├── dropdown-item/ │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.ts │ │ │ │ └── option/ │ │ │ │ └── index.ts │ │ │ ├── skeleton/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── tab/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ └── tabpane/ │ │ │ ├── index.less │ │ │ └── index.ts │ │ ├── demo/ │ │ │ └── react.tsx │ │ ├── index.html │ │ ├── index.ts │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── plugins/ │ │ │ ├── auto-import-file.ts │ │ │ ├── load-style.ts │ │ │ └── load-svg.ts │ │ ├── readme.md │ │ ├── rollup.d.ts │ │ ├── shadowless/ │ │ │ ├── icon/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ ├── input/ │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ │ └── select/ │ │ │ ├── index.less │ │ │ ├── index.ts │ │ │ └── option/ │ │ │ └── index.ts │ │ ├── shadowless.ts │ │ ├── tests/ │ │ │ └── button.spec.ts │ │ ├── theme/ │ │ │ ├── color.less │ │ │ ├── font.less │ │ │ └── index.less │ │ ├── tsconfig.json │ │ ├── typings.d.ts │ │ ├── utils/ │ │ │ ├── color.ts │ │ │ ├── image.ts │ │ │ ├── index.ts │ │ │ ├── math.ts │ │ │ └── tween.ts │ │ └── vite.config.ts │ ├── ranuts/ │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── README.zh-CN.md │ │ ├── assets/ │ │ │ └── wasm/ │ │ │ └── word/ │ │ │ ├── LICENSE_APACHE │ │ │ ├── LICENSE_MIT │ │ │ ├── wasmjieba-web.d.ts │ │ │ ├── wasmjieba-web.js │ │ │ ├── wasmjieba-web_bg.wasm │ │ │ └── wasmjieba-web_bg.wasm.d.ts │ │ ├── bin/ │ │ │ ├── build.sh │ │ │ └── test.sh │ │ ├── build/ │ │ │ ├── build.es.ts │ │ │ ├── build.umd.ml.ts │ │ │ ├── build.umd.node.ts │ │ │ ├── build.umd.ts │ │ │ ├── build.umd.utils.ts │ │ │ └── build.umd.wasm.ts │ │ ├── docs/ │ │ │ ├── binaryTree/ │ │ │ │ └── index.md │ │ │ ├── file/ │ │ │ │ └── index.md │ │ │ ├── index.md │ │ │ ├── sort/ │ │ │ │ ├── bubble/ │ │ │ │ │ └── index.md │ │ │ │ ├── bucket/ │ │ │ │ │ └── index.md │ │ │ │ ├── count/ │ │ │ │ │ └── index.md │ │ │ │ ├── heap/ │ │ │ │ │ └── index.md │ │ │ │ ├── index.md │ │ │ │ ├── insert/ │ │ │ │ │ └── index.md │ │ │ │ ├── merge/ │ │ │ │ │ └── index.md │ │ │ │ ├── quick/ │ │ │ │ │ └── index.md │ │ │ │ ├── radix/ │ │ │ │ │ └── index.md │ │ │ │ └── select/ │ │ │ │ └── index.md │ │ │ └── utils/ │ │ │ ├── compose.md │ │ │ ├── index.md │ │ │ └── task.md │ │ ├── examples/ │ │ │ ├── clone-deep-example.ts │ │ │ └── is-equal-example.ts │ │ ├── index.html │ │ ├── index.ts │ │ ├── package.json │ │ ├── plugins/ │ │ │ └── vite-plugins-banner.ts │ │ ├── readme.md │ │ ├── rollup.d.ts │ │ ├── src/ │ │ │ ├── arithmetic/ │ │ │ │ └── index.ts │ │ │ ├── ml/ │ │ │ │ ├── index.ts │ │ │ │ └── ocr.ts │ │ │ ├── node/ │ │ │ │ ├── appendFile.ts │ │ │ │ ├── body.ts │ │ │ │ ├── color.ts │ │ │ │ ├── command.ts │ │ │ │ ├── ctx2req.ts │ │ │ │ ├── fileInfo.ts │ │ │ │ ├── fs.ts │ │ │ │ ├── get.ts │ │ │ │ ├── getIPAdress.ts │ │ │ │ ├── index.ts │ │ │ │ ├── isColorSupported.ts │ │ │ │ ├── paresUrl.ts │ │ │ │ ├── readDir.ts │ │ │ │ ├── readFile.ts │ │ │ │ ├── router.ts │ │ │ │ ├── send.ts │ │ │ │ ├── server.ts │ │ │ │ ├── startTask.ts │ │ │ │ ├── stream.ts │ │ │ │ ├── taskEnd.ts │ │ │ │ ├── traverse.ts │ │ │ │ ├── watchFile.ts │ │ │ │ ├── websocket.ts │ │ │ │ ├── writeFile.ts │ │ │ │ └── ws.ts │ │ │ ├── optimize/ │ │ │ │ ├── index.ts │ │ │ │ └── promise.ts │ │ │ ├── ran/ │ │ │ │ ├── build-react.md │ │ │ │ ├── commit.ts │ │ │ │ ├── dom.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.ts │ │ │ │ ├── min.ts │ │ │ │ ├── reconcile.ts │ │ │ │ └── schedule.ts │ │ │ ├── sort/ │ │ │ │ ├── bubble.ts │ │ │ │ ├── bucket.ts │ │ │ │ ├── count.ts │ │ │ │ ├── heap.ts │ │ │ │ ├── index.ts │ │ │ │ ├── insert.ts │ │ │ │ ├── merge.ts │ │ │ │ ├── quick.ts │ │ │ │ ├── radix.ts │ │ │ │ ├── randomArray.ts │ │ │ │ ├── select.ts │ │ │ │ └── shell.ts │ │ │ ├── utils/ │ │ │ │ ├── audioRecorder.ts │ │ │ │ ├── behavior.ts │ │ │ │ ├── bom.ts │ │ │ │ ├── color.ts │ │ │ │ ├── compose.ts │ │ │ │ ├── console.ts │ │ │ │ ├── debounce.ts │ │ │ │ ├── device.ts │ │ │ │ ├── dom.ts │ │ │ │ ├── error.ts │ │ │ │ ├── func.ts │ │ │ │ ├── img.ts │ │ │ │ ├── index.ts │ │ │ │ ├── memoize.ts │ │ │ │ ├── mimeType.ts │ │ │ │ ├── monitor.ts │ │ │ │ ├── network.ts │ │ │ │ ├── noop.ts │ │ │ │ ├── number.ts │ │ │ │ ├── obj.ts │ │ │ │ ├── performance.ts │ │ │ │ ├── queue.ts │ │ │ │ ├── report.ts │ │ │ │ ├── request.ts │ │ │ │ ├── script.ts │ │ │ │ ├── signal.ts │ │ │ │ ├── storage.ts │ │ │ │ ├── str.ts │ │ │ │ ├── subscribe.ts │ │ │ │ ├── throttle.ts │ │ │ │ ├── time.ts │ │ │ │ ├── totp/ │ │ │ │ │ ├── sha/ │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── common.ts │ │ │ │ │ │ ├── converters.ts │ │ │ │ │ │ ├── custom_types.ts │ │ │ │ │ │ ├── license_header.es3.txt │ │ │ │ │ │ ├── license_header.es6.txt │ │ │ │ │ │ ├── primitives_32.ts │ │ │ │ │ │ ├── primitives_64.ts │ │ │ │ │ │ ├── sha.ts │ │ │ │ │ │ ├── sha1.ts │ │ │ │ │ │ ├── sha256.ts │ │ │ │ │ │ ├── sha3.ts │ │ │ │ │ │ └── sha512.ts │ │ │ │ │ └── totp.ts │ │ │ │ └── visual/ │ │ │ │ ├── application.ts │ │ │ │ ├── demo/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── nodeHierarchy.html │ │ │ │ │ └── sankey.ts │ │ │ │ ├── enums.ts │ │ │ │ ├── event/ │ │ │ │ │ ├── boundary.ts │ │ │ │ │ ├── event.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── graphics/ │ │ │ │ │ ├── graphics.ts │ │ │ │ │ ├── graphicsData.ts │ │ │ │ │ ├── graphicsGeometry.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── math/ │ │ │ │ │ ├── bezier.ts │ │ │ │ │ ├── enums.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── matrix.ts │ │ │ │ │ └── transform.ts │ │ │ │ ├── render/ │ │ │ │ │ ├── batchRenderer.ts │ │ │ │ │ ├── canvasRenderer.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── render.ts │ │ │ │ │ ├── utils/ │ │ │ │ │ │ ├── batch/ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── float.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── verticy.ts │ │ │ │ │ │ ├── webgl/ │ │ │ │ │ │ │ ├── batchPool.ts │ │ │ │ │ │ │ ├── initShader.ts │ │ │ │ │ │ │ └── shaders.ts │ │ │ │ │ │ └── webgpu/ │ │ │ │ │ │ └── shaders.ts │ │ │ │ │ ├── webGPURenderer.ts │ │ │ │ │ └── webGlRenderer.ts │ │ │ │ ├── shape/ │ │ │ │ │ ├── circle.ts │ │ │ │ │ ├── ellipse.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── polygon.ts │ │ │ │ │ ├── rectangle.ts │ │ │ │ │ ├── roundedRectangle.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── style/ │ │ │ │ │ ├── fill.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── line.ts │ │ │ │ ├── types.ts │ │ │ │ └── vertex/ │ │ │ │ ├── container.ts │ │ │ │ ├── index.ts │ │ │ │ ├── point.ts │ │ │ │ └── vertex.ts │ │ │ ├── vnode/ │ │ │ │ ├── chainDom.ts │ │ │ │ ├── h.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── htmlDomApi.ts │ │ │ │ ├── init.ts │ │ │ │ ├── is.ts │ │ │ │ ├── modules/ │ │ │ │ │ ├── attributes.ts │ │ │ │ │ ├── class.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── listeners.ts │ │ │ │ │ ├── props.ts │ │ │ │ │ └── style.ts │ │ │ │ └── vnode.ts │ │ │ ├── wasm/ │ │ │ │ ├── index.ts │ │ │ │ └── word.ts │ │ │ └── wicket/ │ │ │ ├── bridge.ts │ │ │ └── index.ts │ │ ├── test/ │ │ │ ├── arithmetic.test.ts │ │ │ ├── cloneDeep.test.ts │ │ │ ├── encodeUrl.test.ts │ │ │ ├── escapeHtml.test.ts │ │ │ ├── is-equal.test.ts │ │ │ ├── mimeType.test.ts │ │ │ ├── server.test.ts │ │ │ ├── sort.test.ts │ │ │ ├── status.test.ts │ │ │ ├── totp.test.ts │ │ │ ├── utils/ │ │ │ │ ├── compose.test.ts │ │ │ │ ├── mergeObj.test.ts │ │ │ │ └── ocr.test.ts │ │ │ ├── visual/ │ │ │ │ └── math.test.ts │ │ │ ├── vnode/ │ │ │ │ ├── index.html │ │ │ │ ├── index.ts │ │ │ │ ├── server.ts │ │ │ │ └── vnode.ts │ │ │ ├── websocket.test.ts │ │ │ └── writeFile.test.ts │ │ ├── tsconfig.json │ │ ├── typings.d.ts │ │ └── vite.config.ts │ ├── rust/ │ │ ├── index.md │ │ └── start.md │ ├── solidity/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── bin/ │ │ │ ├── compile.sh │ │ │ ├── eth.sh │ │ │ └── test.sh │ │ ├── blockchain-data-structure.md │ │ ├── consensus.md │ │ ├── contracts/ │ │ │ └── Lock.sol │ │ ├── encryption.md │ │ ├── eth/ │ │ │ ├── doc/ │ │ │ │ ├── Foundry.md │ │ │ │ ├── ethers.md │ │ │ │ ├── introduce.md │ │ │ │ └── pragma.md │ │ │ └── project/ │ │ │ ├── crowdFund/ │ │ │ │ ├── contracts/ │ │ │ │ │ ├── CrowdFund.sol │ │ │ │ │ └── artifacts/ │ │ │ │ │ ├── CrowdFund.json │ │ │ │ │ ├── CrowdFund_metadata.json │ │ │ │ │ ├── IERC20.json │ │ │ │ │ ├── IERC20_metadata.json │ │ │ │ │ └── build-info/ │ │ │ │ │ └── 51a87644e167c2c0acbed68604ab9364.json │ │ │ │ └── readme.md │ │ │ ├── cryptoKitty/ │ │ │ │ ├── contracts/ │ │ │ │ │ └── cryptoKitty.sol │ │ │ │ └── readme.md │ │ │ ├── deploy.md │ │ │ └── fungibleToken/ │ │ │ ├── .states/ │ │ │ │ └── vm-shanghai/ │ │ │ │ └── state.json │ │ │ ├── contracts/ │ │ │ │ ├── FungibleToken.sol │ │ │ │ └── artifacts/ │ │ │ │ ├── FungibleToken.json │ │ │ │ ├── FungibleToken_metadata.json │ │ │ │ └── build-info/ │ │ │ │ └── 161b7ad96fda298680715448c4a2ef7f.json │ │ │ └── readme.md │ │ ├── hardhat.config.ts │ │ ├── ignition/ │ │ │ └── modules/ │ │ │ └── Lock.ts │ │ ├── index.md │ │ ├── package.json │ │ ├── pos.md │ │ ├── pow.md │ │ ├── program.md │ │ ├── remix.md │ │ ├── signature.md │ │ ├── start.md │ │ ├── test/ │ │ │ └── Lock.ts │ │ ├── tsconfig.json │ │ ├── wallet.md │ │ └── web3-wallet.md │ └── visual/ │ ├── bin/ │ │ └── build.sh │ ├── build/ │ │ ├── build.es.ts │ │ └── build.umd.ts │ ├── components/ │ │ ├── bar/ │ │ │ └── index.ts │ │ ├── line/ │ │ │ └── index.ts │ │ ├── pie/ │ │ │ └── index.ts │ │ └── sankey/ │ │ ├── data.ts │ │ └── index.ts │ ├── docs/ │ │ ├── demo.glsl │ │ ├── fourColor.glsl │ │ ├── glsl.md │ │ ├── index.md │ │ ├── random.md │ │ ├── red.glsl │ │ ├── start.md │ │ ├── texture.md │ │ ├── ux.md │ │ └── yellow.glsl │ ├── index.html │ ├── index.ts │ ├── package.json │ ├── src/ │ │ ├── application.ts │ │ ├── enums.ts │ │ ├── event/ │ │ │ ├── boundry.ts │ │ │ ├── enums.ts │ │ │ ├── event.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── graphics/ │ │ │ ├── geometry.ts │ │ │ ├── graphics.ts │ │ │ ├── graphicsData.ts │ │ │ └── index.ts │ │ ├── render/ │ │ │ ├── canvasRender.ts │ │ │ ├── index.ts │ │ │ ├── render.ts │ │ │ ├── webGLRender.ts │ │ │ └── webGPURender.ts │ │ ├── shape/ │ │ │ ├── bezier.ts │ │ │ ├── circle.ts │ │ │ ├── ellipse.ts │ │ │ ├── enums.ts │ │ │ ├── fill.ts │ │ │ ├── index.ts │ │ │ ├── line.ts │ │ │ ├── polygon.ts │ │ │ ├── rectangle.ts │ │ │ ├── roundedRectangle.ts │ │ │ ├── shape.ts │ │ │ └── types.ts │ │ ├── transform/ │ │ │ ├── enums.ts │ │ │ ├── index.ts │ │ │ ├── matrix.ts │ │ │ ├── transform.ts │ │ │ └── types.ts │ │ ├── types.ts │ │ └── vertex/ │ │ ├── container.ts │ │ ├── index.ts │ │ ├── point.ts │ │ └── vertex.ts │ ├── tsconfig.json │ ├── typings.d.ts │ └── vite.config.ts ├── pnpm-workspace.yaml ├── readme-zh_CN.md └── readme.md
SYMBOL INDEX (2452 symbols across 243 files)
FILE: packages/cpro/sum.cpp
function sum (line 6) | std::string sum(double a,double b) {
function EMSCRIPTEN_BINDINGS (line 11) | EMSCRIPTEN_BINDINGS(myModule) {
FILE: packages/debug/koaStatic/index.ts
constant PORT (line 12) | const PORT = 5555;
constant STATIC_DIR (line 14) | const STATIC_DIR = 'dist';
FILE: packages/docs/.vitepress/common/index.ts
constant GTAG (line 3) | const GTAG = 'https://www.googletagmanager.com/gtag/js?id=G-0MPS5WH1C0';
constant GOOGLE_ANALYSE (line 5) | const GOOGLE_ANALYSE = `;window.dataLayer = window.dataLayer || [];funct...
constant BD_ANALYSE (line 7) | const BD_ANALYSE = `
constant PREVIEW_CODE (line 17) | const PREVIEW_CODE = `
constant DESCRIPTION (line 37) | const DESCRIPTION =
constant HOME (line 40) | const HOME = 'https://chaxus.github.io/ran/';
constant BASE_PATH (line 42) | const BASE_PATH = '/ran/';
constant HOME_ICON (line 44) | const HOME_ICON = `${HOME}home.svg`;
constant UTILS_PATH (line 46) | const UTILS_PATH = `${HOME}src/ranuts/utils/`;
constant RANUI_PATH (line 48) | const RANUI_PATH = `${HOME}src/ranui/`;
constant ARTICLE_PATH (line 50) | const ARTICLE_PATH = `${HOME}src/article/designMode.html`;
constant KEY_WORDS (line 52) | const KEY_WORDS = 'ran,component,components,ui,design,ranui,web-componen...
constant GITHUB (line 54) | const GITHUB = 'https://github.com/chaxus/ran';
constant SERVICE_WORK (line 56) | const SERVICE_WORK = `
constant SET_FONT_SIZE (line 80) | const SET_FONT_SIZE = `
FILE: packages/docs/.vitepress/lib/constant.ts
type INPUT_STATUS (line 1) | enum INPUT_STATUS {
type LANGS_DICT (line 7) | enum LANGS_DICT {
constant RAN_CHAXUS_LANG (line 12) | const RAN_CHAXUS_LANG = 'ran_chaxus_lang';
constant LOADED_LOCALES (line 14) | const LOADED_LOCALES: string[] = [];
constant LANG_MESSAGES (line 16) | const LANG_MESSAGES = {
type I18N_MODE (line 25) | enum I18N_MODE {
constant PWA_INSTALL_ID (line 29) | const PWA_INSTALL_ID = 'PWA_INSTALL_ID';
constant PWA_ELEMENT_NAME (line 30) | const PWA_ELEMENT_NAME = 'pwa-install';
constant MANIFEST_PATH_ROOT (line 31) | const MANIFEST_PATH_ROOT = '/ran/manifest.json';
FILE: packages/docs/.vitepress/plugins/env.ts
type Env (line 12) | interface Env {
FILE: packages/docs/.vitepress/theme/index.ts
type ImportMeta (line 15) | interface ImportMeta {
method enhanceApp (line 39) | enhanceApp({ app }: EnhanceAppContext): void {
FILE: packages/docs/public/sw.js
constant CACHE_NAME (line 1) | const CACHE_NAME = 'chaxus_ran_' + VERSION
constant IGNORE_REQUEST_LIST (line 3) | const IGNORE_REQUEST_LIST = [
constant REQUEST_METHOD (line 15) | const REQUEST_METHOD = {
constant RESPONSE_STATUS (line 19) | const RESPONSE_STATUS = {
constant SERVICE_WORK (line 23) | const SERVICE_WORK = {
FILE: packages/docs/typings.d.ts
type Window (line 2) | interface Window {
type Process (line 8) | interface Process {
FILE: packages/docs/variable/SERVICE_WORK_VERSION.ts
constant SERVICE_WORK_VERSION (line 1) | const SERVICE_WORK_VERSION = '1763186055';
FILE: packages/im/app/controllers/home.ts
class HomeController (line 14) | class HomeController {
method index (line 15) | async index(ctx: Context): Promise<void> {
FILE: packages/im/app/controllers/im.ts
constant STR (line 3) | const STR =
class IMController (line 6) | class IMController {
method dialog (line 7) | dialog(ctx: Context): void {
FILE: packages/im/app/controllers/user.ts
class UserController (line 3) | class UserController {
method login (line 4) | async login(ctx: Context): Promise<void> {
method list (line 14) | async list(ctx: Context): Promise<void> {
FILE: packages/im/app/lib/constant.ts
constant DDTOKEN (line 2) | const DDTOKEN = '4e6add99ad420323a61b0ad4caa4940ec2806670a20ff00d32adbe8...
constant ADMINISTRATOR (line 3) | const ADMINISTRATOR = 1;
constant HTML_PATH_DEV (line 5) | const HTML_PATH_DEV = '../../views/index.html';
constant FORMAT (line 6) | const FORMAT = 'utf-8';
constant TEMPLATE_REPLACE (line 7) | const TEMPLATE_REPLACE = '<!--ssr-outlet-->';
constant RENDER_PATH_DEV (line 8) | const RENDER_PATH_DEV = '/client/server.tsx';
constant HTML_PATH_PROD (line 9) | const HTML_PATH_PROD = '../../dist/client/views/index.html';
constant RENDER_PATH_PROD (line 10) | const RENDER_PATH_PROD = '../../dist/server/server.js';
constant HTML_PATH_MAP (line 11) | const HTML_PATH_MAP: Record<string, string> = {
constant RENDER_PATH_MAP (line 15) | const RENDER_PATH_MAP: Record<string, string> = {
constant PRODUCTION (line 20) | const PRODUCTION = 'production';
constant PRODUCTION_DIR (line 22) | const PRODUCTION_DIR = '../../dist/';
constant DEVELOPMENT_DIR (line 23) | const DEVELOPMENT_DIR = '../../dist/views/';
constant PORT (line 25) | const PORT = 30102;
constant LOCAL_URL (line 26) | const LOCAL_URL = `http://localhost:${PORT}`;
constant TYPE_OPJECT (line 27) | const TYPE_OPJECT = '[object Object]';
constant TYPE_FUNCTION (line 28) | const TYPE_FUNCTION = '[object Function]';
constant MIME_TYPES (line 30) | const MIME_TYPES: Record<string, string> = {
FILE: packages/im/app/lib/index.ts
class HtmlWritable (line 5) | class HtmlWritable extends Writable {
method constructor (line 8) | constructor() {
method getHtml (line 14) | getHtml(): string {
method getFragment (line 18) | getFragment(): string {
method _write (line 22) | _write(chunk: Uint8Array, _: string, callback = noop): void {
method _final (line 27) | _final(callback = noop): void {
FILE: packages/im/app/lib/request.ts
function parseURL (line 5) | function parseURL(requestUrl: string): { query: UrlWithParsedQuery['quer...
function extractParams (line 15) | function extractParams(pathname: string, pathPattern: string): Record<st...
FILE: packages/im/app/types/index.ts
type Controller (line 4) | type Controller = Record<string, Record<string, Function>>;
type Chemical (line 6) | type Chemical = Record<string, string>;
type RequestBody (line 8) | type RequestBody = any;
type ResponseWriteChunk (line 10) | type ResponseWriteChunk = any;
type ContextRquest (line 12) | interface ContextRquest {
type ContextResponse (line 20) | interface ContextResponse {
type Context (line 26) | interface Context {
FILE: packages/im/client/app.tsx
function RoutesContent (line 13) | function RoutesContent(): JSX.Element {
FILE: packages/im/client/components/backdrop/index.tsx
type BackDropProps (line 9) | interface BackDropProps {
FILE: packages/im/client/lib/eventSource.ts
type RequestOption (line 1) | interface RequestOption {
type EventSourceStatus (line 8) | enum EventSourceStatus {
class EventStreamFetch (line 15) | class EventStreamFetch {
method constructor (line 18) | constructor() {
class EventStreamSource (line 96) | class EventStreamSource {
method constructor (line 100) | constructor() {
FILE: packages/im/client/lib/index.ts
type Polygon (line 1) | interface Polygon {
FILE: packages/im/client/pages/home/index.tsx
type IMResponse (line 4) | interface IMResponse {
FILE: packages/im/client/router/index.tsx
type Redirect (line 14) | interface Redirect {
FILE: packages/im/client/server.tsx
function render (line 8) | function render(ctx: Context, options: RenderToPipeableStreamOptions = {...
FILE: packages/image-process/main.c
function main (line 5) | int main(int argc, char **argv) {
FILE: packages/image-process/src/image_processing.c
function process_image (line 6) | int process_image(const char *infile, const char *outfile) {
FILE: packages/ml/client/components/BinaryModel.tsx
type Window (line 13) | interface Window {
type TensorLike2D (line 22) | type TensorLike2D =
type HouseSaleDataSet (line 33) | interface HouseSaleDataSet extends TensorContainerObject {
class BinaryModel (line 127) | class BinaryModel {
FILE: packages/ml/client/components/Emotion.tsx
type Window (line 13) | interface Window {
type TextEmotionData (line 93) | interface TextEmotionData extends TensorContainerObject {
class EmotionModel (line 98) | class EmotionModel {
method constructor (line 107) | constructor() {
FILE: packages/ml/client/components/LineModel.tsx
type Window (line 13) | interface Window {
type TensorLike2D (line 21) | type TensorLike2D =
type HouseSaleDataSet (line 32) | interface HouseSaleDataSet extends TensorContainerObject {
class LineModel (line 37) | class LineModel {
FILE: packages/ml/client/components/MultiModel.tsx
type TensorLike2D (line 17) | type TensorLike2D =
type HouseSaleDataSet (line 28) | interface HouseSaleDataSet extends TensorContainerObject {
class MultiModel (line 140) | class MultiModel {
FILE: packages/ml/client/lib.ts
type TfVersion (line 6) | interface TfVersion {
type TfInfo (line 16) | interface TfInfo {
type Normalise (line 27) | interface Normalise {
function createLotsOfTensors (line 36) | function createLotsOfTensors(): void {
FILE: packages/ml/src/ebook/index.ts
type Window (line 5) | interface Window {
type ChapterInfo (line 13) | interface ChapterInfo {
type TrainingData (line 20) | interface TrainingData {
type ModelData (line 25) | interface ModelData {
class ChapterDetector (line 32) | class ChapterDetector {
method buildVocabulary (line 48) | private buildVocabulary(content: string) {
method preprocessText (line 64) | private preprocessText(text: string): number[] {
method generateLabels (line 80) | private generateLabels(text: string, chapters: ChapterInfo[]): string[] {
method buildModel (line 119) | private async buildModel() {
method saveModel (line 176) | public async saveModel(): Promise<ModelData> {
method loadModel (line 211) | public async loadModel(file: File): Promise<void> {
method train (line 229) | public async train(
method detectChapters (line 331) | public async detectChapters(contents: string[]): Promise<ChapterInfo[]...
function processEbook (line 460) | async function processEbook(contents: string[], modelFile?: File): Promi...
FILE: packages/ml/src/ebook/trainData.ts
function generateTrainingData (line 15) | async function generateTrainingData(directory: string): Promise<Training...
function saveTrainingData (line 61) | function saveTrainingData(data: TrainingData[], outputPath: string): void {
function loadTrainingData (line 87) | function loadTrainingData(filePath: string): TrainingData[] {
function main (line 100) | async function main(): Promise<void> {
FILE: packages/ranite/src/client/client.ts
type Update (line 9) | interface Update {
function handleMessage (line 16) | async function handleMessage(payload: any) {
type HotModule (line 33) | interface HotModule {
type HotCallback (line 38) | interface HotCallback {
function acceptDeps (line 53) | function acceptDeps(deps: string[], callback: any) {
method accept (line 67) | accept(deps: any) {
method prune (line 76) | prune(cb: (data: any) => void) {
function fetchUpdate (line 86) | async function fetchUpdate({ path, timestamp }: Update) {
function updateStyle (line 119) | function updateStyle(id: string, content: string): void {
function removeStyle (line 134) | function removeStyle(id: string): void {
FILE: packages/ranite/src/node/ModuleGraph.ts
type ResolvedId (line 3) | interface ResolvedId extends ModuleOptions {
type ModuleInfo (line 7) | interface ModuleInfo extends ModuleOptions {
type ExistingRawSourceMap (line 29) | interface ExistingRawSourceMap {
type SourceMapInput (line 39) | type SourceMapInput = ExistingRawSourceMap | string | null | { mappings:...
type AcornNode (line 41) | interface AcornNode {
type SourceDescription (line 46) | interface SourceDescription extends Partial<PartialNull<ModuleOptions>> {
type NullValue (line 52) | type NullValue = null | undefined | void;
type TransformResult (line 54) | type TransformResult = string | NullValue | Partial<SourceDescription>;
type CustomPluginOptions (line 56) | type CustomPluginOptions = Record<string, any>;
type ModuleOptions (line 58) | interface ModuleOptions {
type PartialNull (line 65) | type PartialNull<T> = {
type PartialResolvedId (line 68) | interface PartialResolvedId extends Partial<PartialNull<ModuleOptions>> {
class ModuleNode (line 81) | class ModuleNode {
method constructor (line 109) | constructor(url: string) {
class ModuleGraph (line 115) | class ModuleGraph {
method constructor (line 123) | constructor(
method getModuleById (line 128) | getModuleById(id: string): ModuleNode | undefined {
method getModuleByUrl (line 132) | async getModuleByUrl(rawUrl: string): Promise<ModuleNode | undefined> {
method ensureEntryFromUrl (line 141) | async ensureEntryFromUrl(rawUrl: string): Promise<ModuleNode> {
method updateModuleInfo (line 155) | async updateModuleInfo(mod: ModuleNode, importedModules: Set<string | ...
method invalidateModule (line 172) | invalidateModule(file: string): void {
method _resolve (line 184) | private async _resolve(url: string): Promise<{ url: string; resolvedId...
FILE: packages/ranite/src/node/cli.ts
function parseOptions (line 10) | function parseOptions() {
FILE: packages/ranite/src/node/constants.ts
constant EXTERNAL_TYPES (line 4) | const EXTERNAL_TYPES = [
constant JS_TYPES_RE (line 26) | const JS_TYPES_RE = /\.(?:j|t)sx?$|\.mjs$/;
constant BARE_IMPORT_RE (line 28) | const BARE_IMPORT_RE = /^[\w@][^:]/;
constant QEURY_RE (line 29) | const QEURY_RE = /\?.*$/s;
constant HASH_RE (line 30) | const HASH_RE = /#.*$/s;
constant PRE_BUNDLE_DIR (line 32) | const PRE_BUNDLE_DIR = path.join('node_modules', '.ranite');
constant DEFAULT_EXTENSIONS (line 34) | const DEFAULT_EXTENSIONS = ['.tsx', '.ts', '.jsx', 'js'];
constant HMR_HEADER (line 35) | const HMR_HEADER = 'ranite-hmr';
constant CLIENT_PUBLIC_PATH (line 36) | const CLIENT_PUBLIC_PATH = '/@ranite/client';
constant HMR_PORT (line 37) | const HMR_PORT = 24678;
FILE: packages/ranite/src/node/hmr.ts
function bindingHMREvents (line 5) | function bindingHMREvents(serverContext: ServerContext): void {
FILE: packages/ranite/src/node/optimizer/index.ts
function optimize (line 8) | async function optimize(root: string): Promise<void> {
FILE: packages/ranite/src/node/optimizer/preBundlePlugin.ts
function preBundlePlugin (line 19) | function preBundlePlugin(deps: Set<string>): Plugin {
FILE: packages/ranite/src/node/optimizer/scanPlugin.ts
function scanPlugin (line 7) | function scanPlugin(deps: Set<string>): Plugin {
FILE: packages/ranite/src/node/plugin.ts
type CustomPluginOptions (line 3) | type CustomPluginOptions = Record<string, any>;
type ModuleOptions (line 5) | interface ModuleOptions {
type PartialNull (line 12) | type PartialNull<T> = {
type NullValue (line 16) | type NullValue = null | undefined | void;
type ServerHook (line 18) | type ServerHook = (server: ServerContext) => (() => void) | void | Promi...
type Plugin (line 21) | interface Plugin {
type AcornNode (line 30) | interface AcornNode {
type ExistingRawSourceMap (line 36) | interface ExistingRawSourceMap {
type SourceMapInput (line 46) | type SourceMapInput = ExistingRawSourceMap | string | null | { mappings:...
type SourceDescription (line 48) | interface SourceDescription extends Partial<PartialNull<ModuleOptions>> {
type PartialResolvedId (line 54) | interface PartialResolvedId extends Partial<PartialNull<ModuleOptions>> {
type LoadResult (line 59) | type LoadResult = SourceDescription | string | NullValue;
type ResolvedId (line 61) | interface ResolvedId extends ModuleOptions {
FILE: packages/ranite/src/node/pluginContainer.ts
type PluginContainer (line 3) | interface PluginContainer {
class Context (line 16) | class Context {
method resolve (line 17) | async resolve(id: string, importer?: string) {
method resolveId (line 30) | async resolveId(id: string, importer?: string) {
method load (line 48) | async load(id) {
method transform (line 66) | async transform(code, id) {
FILE: packages/ranite/src/node/plugins/assets.ts
function assetPlugin (line 4) | function assetPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/clientInject.ts
function clientInjectPlugin (line 7) | function clientInjectPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/css.ts
function cssPlugin (line 7) | function cssPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/esbuild.ts
function esbuildTransformPlugin (line 7) | function esbuildTransformPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/importAnalysis.ts
function importAnalysisPlugin (line 9) | function importAnalysisPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/index.ts
function resolvePlugins (line 10) | function resolvePlugins(): Plugin[] {
FILE: packages/ranite/src/node/plugins/react-hmr.ts
function loadPlugin (line 8) | function loadPlugin(path: string): Promise<any> {
constant RUNTIME_PUBLIC_PATH (line 15) | const RUNTIME_PUBLIC_PATH = '/@react-refresh';
function reactHMRPlugin (line 76) | function reactHMRPlugin(): Plugin {
FILE: packages/ranite/src/node/plugins/resolve.ts
function resolvePlugin (line 12) | function resolvePlugin(): Plugin {
FILE: packages/ranite/src/node/server/index.ts
type ServerContext (line 17) | interface ServerContext {
function startDevServer (line 27) | async function startDevServer(): Promise<void> {
FILE: packages/ranite/src/node/server/middlewares/indexHtml.ts
function indexHtmlMiddleware (line 6) | function indexHtmlMiddleware(serverContext: ServerContext): NextHandleFu...
FILE: packages/ranite/src/node/server/middlewares/static.ts
function staticMiddleware (line 6) | function staticMiddleware(): NextHandleFunction {
FILE: packages/ranite/src/node/server/middlewares/transform.ts
function transformRequest (line 8) | async function transformRequest(url: string, serverContext: ServerContex...
function transformMiddleware (line 33) | function transformMiddleware(serverContext: ServerContext): NextHandleFu...
FILE: packages/ranite/src/node/utils.ts
constant INTERNAL_LIST (line 5) | const INTERNAL_LIST = [CLIENT_PUBLIC_PATH, '/@react-refresh'];
function slash (line 7) | function slash(p: string): string {
function normalizePath (line 14) | function normalizePath(id: string): string {
function isImportRequest (line 33) | function isImportRequest(url: string): boolean {
function isInternalRequest (line 37) | function isInternalRequest(url: string): boolean {
function removeImportQuery (line 41) | function removeImportQuery(url: string): string {
function isPlainObject (line 45) | function isPlainObject(obj: any): boolean {
function getShortName (line 49) | function getShortName(file: string, root: string): string {
FILE: packages/ranite/src/node/ws.ts
function createWebSocketServer (line 5) | function createWebSocketServer(): {
FILE: packages/ranui/assets/js/hls.js
function r (line 7) | function r(t, e) {
function i (line 19) | function i(t) {
function n (line 34) | function n(t, e) {
function a (line 43) | function a(t, e, r) {
function s (line 46) | function s(t, e, r) {
function o (line 54) | function o() {
function l (line 68) | function l(t, e) {
function u (line 71) | function u(t) {
function h (line 81) | function h(t, e) {
function d (line 91) | function d() {
function c (line 101) | function c(t, e, r) {
function f (line 114) | function f(t) {
function g (line 138) | function g(t, e) {
function v (line 143) | function v(t, e) {
function m (line 174) | function m(t) {
function p (line 187) | function p(t) {
function D (line 383) | function D(t) {
function I (line 387) | function I(t, e) {
function t (line 406) | function t(e) {
function x (line 462) | function x(t) {
function t (line 466) | function t(t, e) {
function t (line 569) | function t(t) {
function e (line 625) | function e(e, r) {
function e (line 737) | function e(e, r, i, n, a) {
function t (line 783) | function t(t) {
function V (line 914) | function V(t) {
function Y (line 919) | function Y(t) {
function W (line 937) | function W(t) {
function $ (line 952) | function $(t) {
function Z (line 965) | function Z(t) {
function tt (line 977) | function tt(t) {
function rt (line 991) | function rt(t, e, r) {
function yt (line 1135) | function yt() {
function Rt (line 1148) | function Rt(t) {
function At (line 1151) | function At(t, e) {
function kt (line 1155) | function kt(t, e) {
function bt (line 1159) | function bt(t, e) {
function Dt (line 1162) | function Dt(t, e, r) {
function It (line 1165) | function It(t, e) {
function wt (line 1181) | function wt(t) {
function Ct (line 1204) | function Ct(t) {
function _t (line 1239) | function _t(t) {
function Pt (line 1247) | function Pt(t) {
function xt (line 1255) | function xt(t, e) {
function Ft (line 1259) | function Ft(t, e) {
function Mt (line 1337) | function Mt(t, e) {
function Ot (line 1344) | function Ot(t, e, r, i) {
function Nt (line 1394) | function Nt(t) {
function Ut (line 1404) | function Ut(t, e, r) {
function t (line 1443) | function t(t, e, r, i, n) {
function Ht (line 1551) | function Ht(t) {
function Vt (line 1554) | function Vt(t, e, r) {
function Yt (line 1562) | function Yt(t, e) {
function Wt (line 1579) | function Wt(t, e, r) {
function jt (line 1598) | function jt(t, e, r) {
function qt (line 1609) | function qt() {
function Qt (line 1681) | function Qt(t, e) {
function t (line 1711) | function t() {}
function ie (line 2076) | function ie(t, e, r) {
function ne (line 2091) | function ne(t) {
function ae (line 2095) | function ae(t, e) {
function se (line 2115) | function se(t, e, r) {
function oe (line 2119) | function oe(t, e) {
function le (line 2125) | function le(t, e, r, i) {
function ue (line 2133) | function ue(t, e, r) {
function pe (line 2149) | function pe(t) {
function ye (line 2159) | function ye(t, e) {
function t (line 2164) | function t(t) {
function Ee (line 2553) | function Ee(t, e) {
function Se (line 2562) | function Se(t, e) {
function Le (line 2578) | function Le(t) {
function Re (line 2584) | function Re(t, e, r, i) {
function De (line 2622) | function De() {
function we (line 2634) | function we(t, e) {
function t (line 2638) | function t(t) {
function t (line 2863) | function t(t) {
function t (line 3045) | function t(t, e, r) {
function t (line 3067) | function t(t) {
function Ue (line 3163) | function Ue(t, e) {
function Be (line 3177) | function Be(t, e, r, i, n, a) {
function Ge (line 3212) | function Ge(t, e) {
function Ke (line 3325) | function Ke(t, e) {
function He (line 3330) | function He(t, e) {
function Ve (line 3336) | function Ve(t, e, r) {
function Ye (line 3340) | function Ye(t, e, r) {
function We (line 3348) | function We(t) {
function je (line 3358) | function je(t, e) {
function qe (line 3362) | function qe(t, e) {
function Xe (line 3366) | function Xe(t) {
function ze (line 3369) | function ze(t, e, r, i) {
function $e (line 3390) | function $e(t, e, r, i) {
function Je (line 3400) | function Je(t, e, r) {
function Ze (line 3405) | function Ze(t, e, r) {
function t (line 3418) | function t(t) {
function t (line 3721) | function t(t, e) {
function e (line 3945) | function e(e, r) {
function dr (line 4340) | function dr(t, e, r) {
function cr (line 4346) | function cr(t) {
function t (line 4358) | function t(t) {
function yr (line 4601) | function yr(t) {
function Tr (line 4611) | function Tr(t) {
function t (line 4616) | function t(t) {
function Lr (line 4825) | function Lr(t, e) {
function Rr (line 4843) | function Rr(t, e) {
function e (line 4849) | function e(e) {
function t (line 4856) | function t(t) {
function t (line 5059) | function t() {
function t (line 5115) | function t() {}
function Cr (line 5197) | function Cr(t, e) {
function _r (line 5207) | function _r(t, e) {
function Pr (line 5213) | function Pr(t, e) {
function xr (line 5217) | function xr(t, e, r) {
function Fr (line 5263) | function Fr(t, e) {
function t (line 5277) | function t(t, e) {
function t (line 5288) | function t(t, e) {
function t (line 5299) | function t() {
function t (line 5503) | function t(t, e) {
function e (line 5640) | function e(e, r, i, n, a) {
function Zr (line 6695) | function Zr() {
function ti (line 6698) | function ti(t, e) {
function t (line 6706) | function t() {
function ii (line 6809) | function ii(t, e) {
function ni (line 6812) | function ni(t, e) {
function ai (line 6815) | function ai(t, e) {
function si (line 6818) | function si(t, e) {
function oi (line 6821) | function oi(t, e) {
function li (line 6832) | function li(t, e, r, i, n) {
function ui (line 6886) | function ui(t) {
function hi (line 6889) | function hi(t, e, r, i, n) {
function e (line 6915) | function e(e, r) {
function t (line 6967) | function t(t, e) {
function Ti (line 7135) | function Ti(t, e, r, i, n) {
function Ei (line 7151) | function Ei(t, e) {
function Si (line 7176) | function Si(t, e) {
function Li (line 7179) | function Li(t, e) {
function Ri (line 7182) | function Ri(t, e) {
function t (line 7193) | function t(t) {
function t (line 7393) | function t(t, e, r) {
function t (line 7466) | function t(t, e, r) {
function Ii (line 7924) | function Ii(t, e, r, i) {
function wi (line 7927) | function wi(t, e) {
function Ci (line 7930) | function Ci(t, e) {
function _i (line 7933) | function _i(t, e, r, i) {
function Pi (line 7971) | function Pi(t) {
function xi (line 8022) | function xi(t, e) {
function e (line 8036) | function e() {
function t (line 8076) | function t() {}
function t (line 8120) | function t() {}
function Ui (line 8881) | function Ui(t, e, r, i) {
function Bi (line 8886) | function Bi(t, e) {
function t (line 8903) | function t(t, e, r, i) {
function Vi (line 9386) | function Vi(t, e) {
function Yi (line 9392) | function Yi(t, e, r, i) {
function Wi (line 9404) | function Wi(t, e, r) {
function t (line 9440) | function t() {
function Qi (line 9654) | function Qi(t, e) {
function t (line 9679) | function t(t, e, r, i, n) {
function tn (line 9891) | function tn(t) {
function i (line 9924) | function i() {}
function n (line 9925) | function n(t, e, r) {
function a (line 9928) | function a(t, e, i, a, s) {
function s (line 9941) | function s(t, e) {
function o (line 9944) | function o() {
function sn (line 10052) | function sn(t, e) {
function on (line 10061) | function on(t, e) {
function ln (line 10064) | function ln(t, e, r) {
function e (line 10148) | function e(e, r, i, n) {
function t (line 10393) | function t(t, e, r, i) {
function e (line 10584) | function e(e, r, i) {
function t (line 11417) | function t(t, e, r) {
function t (line 11449) | function t(t, e, r, i) {
function t (line 11502) | function t(t) {
function t (line 11804) | function t() {
function e (line 11838) | function e(e, r, i) {
function e (line 12385) | function e(e) {
function Tn (line 12592) | function Tn(t, e) {
function En (line 12597) | function En(t, e) {
function e (line 12606) | function e(e, r, i) {
method length (line 12880) | get length() {
function e (line 12892) | function e(e) {
function An (line 13155) | function An(t) {
function t (line 13163) | function t(t) {
function t (line 13211) | function t(t) {
function t (line 13908) | function t() {
function t (line 13926) | function t(t, e, r, i, n) {
function t (line 13996) | function t(t, e, r, i, n, a) {
function t (line 14026) | function t(t) {
function t (line 14105) | function t(t) {
function t (line 14235) | function t(t, e, r) {
function t (line 14402) | function t(t, e, r) {
function jn (line 14586) | function jn(t, e, r) {
function qn (line 14589) | function qn(t, e, r) {
function t (line 14593) | function t(t, e) {
function r (line 14632) | function r(t, e) {
function i (line 14638) | function i(t) {
function n (line 14641) | function n(t) {
function a (line 14649) | function a(e, a, s) {
function t (line 14861) | function t() {}
function $n (line 14871) | function $n(t) {
function t (line 14879) | function t() {
function Zn (line 14913) | function Zn(t, e, r, i) {
function ra (line 14923) | function ra(t, e, r) {
function ia (line 14995) | function ia(t) {
function t (line 14999) | function t() {
function r (line 15013) | function r() {
function la (line 15105) | function la(t, e, r) {
function ua (line 15108) | function ua(t, e, r, i, n, a, s) {
function ga (line 15194) | function ga(t, e, r, i) {
function va (line 15269) | function va(t, e, r) {
function ma (line 15273) | function ma(t) {
function pa (line 15279) | function pa(t, e) {
function ya (line 15291) | function ya(t, e, r) {
function Ta (line 15294) | function Ta(t) {
function Ea (line 15297) | function Ea(t, e) {
function t (line 15330) | function t(t) {
function La (line 15744) | function La(t, e) {
function t (line 15748) | function t(t) {
function t (line 15912) | function t(t) {
function t (line 15990) | function t(e) {
function e (line 16836) | function e(e, r) {
function t (line 16855) | function t(e) {
function t (line 17008) | function t(t) {
function t (line 17045) | function t(t) {
function t (line 17182) | function t(t) {
function Oa (line 17436) | function Oa(t, e, r, i) {
function Na (line 17457) | function Na(t, e, r, i) {
function t (line 17477) | function t(t) {
function t (line 17665) | function t(t) {
function Ha (line 17825) | function Ha(t, e) {
function e (line 17829) | function e(e, r, i) {
function ja (line 18026) | function ja(t) {
function qa (line 18035) | function qa(t) {
function t (line 18052) | function t(e) {
FILE: packages/ranui/assets/js/katex/katex-es-core.js
class SourceLocation (line 5) | class SourceLocation {
method constructor (line 8) | constructor(lexer, start, end) {
method range (line 28) | static range(first, second) {
class Token (line 57) | class Token {
method constructor (line 60) | constructor(
method range (line 78) | range(
class ParseError (line 95) | class ParseError {
method constructor (line 98) | constructor(
function escape (line 203) | function escape(text) {
function getDefaultValue (line 407) | function getDefaultValue(schema) {
class Settings (line 438) | class Settings {
method constructor (line 439) | constructor(options) {
method reportNonstrict (line 476) | reportNonstrict(errorCode, errorMsg, token) {
method useStrictBehavior (line 513) | useStrictBehavior(errorCode, errorMsg, token) {
method isTrusted (line 555) | isTrusted(context) {
class Style (line 579) | class Style {
method constructor (line 580) | constructor(id, size, cramped) {
method sup (line 592) | sup() {
method sub (line 599) | sub() {
method fracNum (line 607) | fracNum() {
method fracDen (line 615) | fracDen() {
method cramp (line 623) | cramp() {
method text (line 630) | text() {
method isTight (line 637) | isTight() {
function scriptFromCodepoint (line 768) | function scriptFromCodepoint(codepoint) {
function supportedCodepoint (line 796) | function supportedCodepoint(codepoint) {
class DocumentFragment (line 1249) | class DocumentFragment {
method constructor (line 1252) | constructor(children) {
method hasClass (line 1267) | hasClass(className) {
method toNode (line 1272) | toNode() {
method toMarkup (line 1281) | toMarkup() {
method toText (line 1295) | toText() {
function setFontMetrics (line 3581) | function setFontMetrics(fontName, metrics) {
function getCharacterMetrics (line 3592) | function getCharacterMetrics(character, font, mode) {
function getGlobalMetrics (line 3630) | function getGlobalMetrics(size) {
class Options (line 3701) | class Options {
method constructor (line 3702) | constructor(data) {
method extend (line 3738) | extend(extension) {
method havingStyle (line 3764) | havingStyle(style) {
method havingCrampedStyle (line 3779) | havingCrampedStyle() {
method havingSize (line 3787) | havingSize(size) {
method havingBaseStyle (line 3804) | havingBaseStyle(style) {
method havingBaseSizing (line 3821) | havingBaseSizing() {
method withColor (line 3845) | withColor(color) {
method withPhantom (line 3854) | withPhantom() {
method withFont (line 3864) | withFont(font) {
method withTextFontFamily (line 3873) | withTextFontFamily(fontFamily) {
method withTextFontWeight (line 3883) | withTextFontWeight(fontWeight) {
method withTextFontShape (line 3893) | withTextFontShape(fontShape) {
method sizingClasses (line 3904) | sizingClasses(oldOptions) {
method baseSizingClasses (line 3916) | baseSizingClasses() {
method fontMetrics (line 3927) | fontMetrics() {
method getColor (line 3937) | getColor() {
class Span (line 4187) | class Span {
method constructor (line 4188) | constructor(classes, children, options, style) {
method setAttribute (line 4206) | setAttribute(attribute, value) {
method hasClass (line 4209) | hasClass(className) {
method toNode (line 4212) | toNode() {
method toMarkup (line 4215) | toMarkup() {
class Anchor (line 4224) | class Anchor {
method constructor (line 4225) | constructor(href, classes, children, options) {
method setAttribute (line 4237) | setAttribute(attribute, value) {
method hasClass (line 4240) | hasClass(className) {
method toNode (line 4243) | toNode() {
method toMarkup (line 4246) | toMarkup() {
class Img (line 4254) | class Img {
method constructor (line 4255) | constructor(src, alt, style) {
method hasClass (line 4268) | hasClass(className) {
method toNode (line 4271) | toNode() {
method toMarkup (line 4286) | toMarkup() {
class SymbolNode (line 4316) | class SymbolNode {
method constructor (line 4317) | constructor(text, height, depth, italic, skew, width, classes, style) {
method hasClass (line 4353) | hasClass(className) {
method toNode (line 4361) | toNode() {
method toMarkup (line 4390) | toMarkup() {
class SvgNode (line 4429) | class SvgNode {
method constructor (line 4430) | constructor(children, attributes) {
method toNode (line 4436) | toNode() {
method toMarkup (line 4451) | toMarkup() {
class PathNode (line 4468) | class PathNode {
method constructor (line 4469) | constructor(pathName, alternate) {
method toNode (line 4475) | toNode() {
method toMarkup (line 4485) | toMarkup() {
class LineNode (line 4493) | class LineNode {
method constructor (line 4494) | constructor(attributes) {
method toNode (line 4498) | toNode() {
method toMarkup (line 4510) | toMarkup() {
function assertSymbolDomNode (line 4521) | function assertSymbolDomNode(group) {
function assertSpan (line 4528) | function assertSpan(group) {
function defineSymbol (line 4578) | function defineSymbol(mode, font, group, replace, name, acceptUnicodeCha...
function defineFunction (line 6266) | function defineFunction(_ref) {
function defineFunctionBuilders (line 6299) | function defineFunctionBuilders(_ref2) {
function buildHTMLUnbreakable (line 6579) | function buildHTMLUnbreakable(children, options) {
function buildHTML (line 6599) | function buildHTML(tree, options) {
function newDocumentFragment (line 6700) | function newDocumentFragment(children) {
class MathNode (line 6709) | class MathNode {
method constructor (line 6710) | constructor(type, children, classes) {
method setAttribute (line 6725) | setAttribute(name, value) {
method getAttribute (line 6732) | getAttribute(name) {
method toNode (line 6739) | toNode() {
method toMarkup (line 6758) | toMarkup() {
method toText (line 6783) | toText() {
class TextNode (line 6791) | class TextNode {
method constructor (line 6792) | constructor(text) {
method toNode (line 6800) | toNode() {
method toMarkup (line 6808) | toMarkup() {
method toText (line 6816) | toText() {
class SpaceNode (line 6825) | class SpaceNode {
method constructor (line 6829) | constructor(width) {
method toNode (line 6861) | toNode() {
method toMarkup (line 6874) | toMarkup() {
method toText (line 6885) | toText() {
function buildMathML (line 7098) | function buildMathML(tree, texExpression, options, isDisplayMode, forMat...
function buildSvgSpan_ (line 7340) | function buildSvgSpan_() {
function assertNodeType (line 7524) | function assertNodeType(node, type) {
function assertSymbolNodeType (line 7538) | function assertSymbolNodeType(node) {
function checkSymbolNodeType (line 7552) | function checkSymbolNodeType(node) {
method handler (line 7954) | handler(_ref, args, optArgs) {
method htmlBuilder (line 7966) | htmlBuilder(group, options) {
method mathmlBuilder (line 8048) | mathmlBuilder(group, options) {
function htmlBuilder$9 (line 8074) | function htmlBuilder$9(group, options) {
function mathmlBuilder$8 (line 8078) | function mathmlBuilder$8(group, options) {
method handler (line 8127) | handler(_ref, args) {
method handler (line 8163) | handler(_ref2, args) {
method handler (line 8182) | handler(_ref3, args) {
method handler (line 8234) | handler(_ref, args) {
method htmlBuilder (line 8243) | htmlBuilder(group, options) {
method mathmlBuilder (line 8249) | mathmlBuilder(group, style) {
function cdArrow (line 8286) | function cdArrow(arrowChar, labels, parser) {
function parseCD (line 8330) | function parseCD(parser) {
method handler (line 8489) | handler(_ref, args) {
method htmlBuilder (line 8498) | htmlBuilder(group, options) {
method mathmlBuilder (line 8509) | mathmlBuilder(group, options) {
method handler (line 8531) | handler(_ref2, args) {
method htmlBuilder (line 8539) | htmlBuilder(group, options) {
method mathmlBuilder (line 8547) | mathmlBuilder(group, options) {
method handler (line 8562) | handler(_ref, args) {
method handler (line 8617) | handler(_ref, args) {
method handler (line 8639) | handler(_ref2, args) {
method handler (line 8673) | handler(_ref, args, optArgs) {
method htmlBuilder (line 8692) | htmlBuilder(group, options) {
method mathmlBuilder (line 8702) | mathmlBuilder(group, options) {
method handler (line 8775) | handler(_ref) {
method handler (line 8802) | handler(_ref2) {
method handler (line 8884) | handler(_ref3) {
method handler (line 8909) | handler(_ref4) {
function checkDelimiter (line 9830) | function checkDelimiter(delim, context) {
function assertParsed (line 9906) | function assertParsed(group) {
method handler (line 10327) | handler(_ref, args, optArgs) {
method handler (line 10350) | handler(_ref2, args, optArgs) {
method handler (line 10375) | handler(_ref3, args) {
method handler (line 10391) | handler(_ref4, args) {
method handler (line 10412) | handler(_ref5, args) {
function defineEnvironment (line 10458) | function defineEnvironment(_ref) {
function defineMacro (line 10497) | function defineMacro(name, body) {
function getHLines (line 10506) | function getHLines(parser) {
function getAutoTag (line 10538) | function getAutoTag(name) {
function parseArray (line 10551) | function parseArray(parser, _ref, style) {
function dCellStyle (line 10711) | function dCellStyle(envName) {
function setHLinePos (line 10766) | function setHLinePos(hlinesInGap) {
method handler (line 11228) | handler(context, args) {
method handler (line 11291) | handler(context) {
method handler (line 11362) | handler(context) {
method handler (line 11379) | handler(context, args) {
method handler (line 11425) | handler(context) {
method handler (line 11487) | handler(context) {
method handler (line 11529) | handler(context) {
method handler (line 11549) | handler(context) {
method handler (line 11569) | handler(context, args) {
method handler (line 11585) | handler(_ref, args) {
method handler (line 12066) | handler(_ref3) {
method handler (line 12113) | handler(_ref4, args) {
method handler (line 12174) | handler(_ref5, args) {
method handler (line 12362) | handler(_ref, args) {
method handler (line 12476) | handler(_ref, args) {
method htmlBuilder (line 12484) | htmlBuilder(group, options) {
method mathmlBuilder (line 12488) | mathmlBuilder(group, options) {
method handler (line 12761) | handler(_ref, args) {
method htmlBuilder (line 12790) | htmlBuilder(group, options) {
method mathmlBuilder (line 12793) | mathmlBuilder(group, options) {
method handler (line 12869) | handler(_ref, args) {
method handler (line 12896) | handler(context, args) {
method handler (line 13382) | handler(_ref3) {
method handler (line 13404) | handler(_ref4) {
method handler (line 13439) | handler(_ref5) {
method htmlBuilder (line 13593) | htmlBuilder(group, options) {
method mathmlBuilder (line 13599) | mathmlBuilder(group, options) {
method handler (line 13610) | handler(_ref, args) {
method htmlBuilder (line 13619) | htmlBuilder(group, options) {
method mathmlBuilder (line 13656) | mathmlBuilder(group, options) {
method handler (line 13785) | handler(_ref, args) {
method htmlBuilder (line 13796) | htmlBuilder(group, options) {
method mathmlBuilder (line 13813) | mathmlBuilder(group, options) {
method handler (line 13828) | handler(_ref) {
method handler (line 13845) | handler(_ref, args, optArgs) {
method htmlBuilder (line 13858) | htmlBuilder(group, options) {
method mathmlBuilder (line 13882) | mathmlBuilder(group, options) {
function sizingGroup (line 13903) | function sizingGroup(value, options, baseOptions) {
method handler (line 14087) | handler(_ref, args, optArgs) {
method htmlBuilder (line 14098) | htmlBuilder(group, options) {
method mathmlBuilder (line 14197) | mathmlBuilder(group, options) {
method handler (line 14219) | handler(_ref, args) {
method htmlBuilder (line 14237) | htmlBuilder(group, options) {
method mathmlBuilder (line 14243) | mathmlBuilder(group, options) {
method htmlBuilder (line 14295) | htmlBuilder(group, options) {
method mathmlBuilder (line 14443) | mathmlBuilder(group, options) {
method htmlBuilder (line 14524) | htmlBuilder(group, options) {
method mathmlBuilder (line 14527) | mathmlBuilder(group, options) {
method htmlBuilder (line 14555) | htmlBuilder(group, options) {
method mathmlBuilder (line 14558) | mathmlBuilder(group, options) {
method htmlBuilder (line 14569) | htmlBuilder(group, options) {
method mathmlBuilder (line 14572) | mathmlBuilder(group, options) {
method htmlBuilder (line 14619) | htmlBuilder(group, options) {
method mathmlBuilder (line 14643) | mathmlBuilder(group, options) {
method mathmlBuilder (line 14664) | mathmlBuilder(group, options) {
method handler (line 14739) | handler(_ref, args) {
method htmlBuilder (line 14749) | htmlBuilder(group, options) {
method mathmlBuilder (line 14754) | mathmlBuilder(group, options) {
method handler (line 14767) | handler(_ref, args) {
method htmlBuilder (line 14775) | htmlBuilder(group, options) {
method mathmlBuilder (line 14812) | mathmlBuilder(group, options) {
method handler (line 14832) | handler(_ref, args) {
method htmlBuilder (line 14840) | htmlBuilder(group, options) {
method mathmlBuilder (line 14858) | mathmlBuilder(group, options) {
method handler (line 14873) | handler(context, args, optArgs) {
method htmlBuilder (line 14880) | htmlBuilder(group, options) {
method mathmlBuilder (line 14898) | mathmlBuilder(group, options) {
class Lexer (line 14978) | class Lexer {
method constructor (line 14979) | constructor(input, settings) {
method setCatcode (line 14996) | setCatcode(char, code) {
method lex (line 15003) | lex() {
class Namespace (line 15043) | class Namespace {
method constructor (line 15050) | constructor(builtins, globalMacros) {
method beginGroup (line 15068) | beginGroup() {
method endGroup (line 15075) | endGroup() {
method endGroups (line 15097) | endGroups() {
method has (line 15107) | has(name) {
method get (line 15119) | get(name) {
method set (line 15134) | set(name, value, global) {
class MacroExpander (line 16236) | class MacroExpander {
method constructor (line 16237) | constructor(input, settings, mode) {
method feed (line 16257) | feed(input) {
method switchMode (line 16264) | switchMode(newMode) {
method beginGroup (line 16271) | beginGroup() {
method endGroup (line 16278) | endGroup() {
method endGroups (line 16286) | endGroups() {
method future (line 16294) | future() {
method popToken (line 16304) | popToken() {
method pushToken (line 16313) | pushToken(token) {
method pushTokens (line 16320) | pushTokens(tokens) {
method scanArgument (line 16328) | scanArgument(isOptional) {
method consumeSpaces (line 16352) | consumeSpaces() {
method consumeArg (line 16367) | consumeArg(delims) {
method consumeArgs (line 16437) | consumeArgs(numArgs, delimiters) {
method countExpansion (line 16461) | countExpansion(amount) {
method expandOnce (line 16487) | expandOnce(expandableOnly) {
method expandAfterFuture (line 16534) | expandAfterFuture() {
method expandNextToken (line 16542) | expandNextToken() {
method expandMacro (line 16565) | expandMacro(name) {
method expandTokens (line 16574) | expandTokens(tokens) {
method expandMacroAsText (line 16601) | expandMacroAsText(name) {
method _getExpansion (line 16614) | _getExpansion(name) {
method isDefined (line 16660) | isDefined(name) {
method isExpandable (line 16673) | isExpandable(name) {
class Parser (line 17216) | class Parser {
method constructor (line 17217) | constructor(input, settings) {
method expect (line 17238) | expect(text, consume) {
method consume (line 17253) | consume() {
method fetch (line 17262) | fetch() {
method switchMode (line 17272) | switchMode(newMode) {
method parse (line 17280) | parse() {
method subparse (line 17316) | subparse(tokens) {
method parseExpression (line 17342) | parseExpression(breakOnInfix, breakOnTokenText) {
method handleInfixNodes (line 17382) | handleInfixNodes(body) {
method handleSupSubscript (line 17432) | handleSupSubscript(
method formatUnsupportedCmd (line 17450) | formatUnsupportedCmd(text) {
method parseAtom (line 17476) | parseAtom(breakOnTokenText) {
method parseFunction (line 17615) | parseFunction(
method callFunction (line 17641) | callFunction(name, args, optArgs, token, breakOnTokenText) {
method parseArguments (line 17659) | parseArguments(
method parseGroupOfType (line 17702) | parseGroupOfType(name, type, optional) {
method consumeSpaces (line 17758) | consumeSpaces() {
method parseStringGroup (line 17768) | parseStringGroup(
method parseRegexGroup (line 17793) | parseRegexGroup(
method parseColorGroup (line 17815) | parseColorGroup(optional) {
method parseSizeGroup (line 17841) | parseSizeGroup(optional) {
method parseUrlGroup (line 17885) | parseUrlGroup(optional) {
method parseArgumentGroup (line 17909) | parseArgumentGroup(optional, mode) {
method parseGroup (line 17943) | parseGroup(
method formLigatures (line 17995) | formLigatures(group) {
method parseSymbol (line 18036) | parseSymbol() {
FILE: packages/ranui/build/config.ts
constant TIME_OUT (line 1) | const TIME_OUT = 1000;
constant PORT (line 3) | const PORT = 5173;
constant DEV_SERVER (line 5) | const DEV_SERVER = `http://localhost:${PORT}/`;
FILE: packages/ranui/components/button/index.ts
class Button (line 4) | class Button extends (HTMLElementSSR()!) {
method observedAttributes (line 11) | static get observedAttributes(): string[] {
method constructor (line 14) | constructor() {
method sheet (line 31) | get sheet(): string {
method sheet (line 34) | set sheet(value: string) {
method disabled (line 37) | get disabled(): boolean | string {
method disabled (line 40) | set disabled(value: boolean | string | undefined | null) {
method iconSize (line 49) | get iconSize(): string {
method iconSize (line 52) | set iconSize(value: string | undefined | null) {
method icon (line 60) | get icon(): string {
method icon (line 63) | set icon(value: string | null) {
method effect (line 71) | get effect(): string {
method effect (line 74) | set effect(value: string | null) {
method connectedCallback (line 142) | connectedCallback(): void {
method disconnectCallback (line 150) | disconnectCallback(): void {
method attributeChangedCallback (line 154) | attributeChangedCallback(name: string, oldValue: string, newValue: str...
function Custom (line 169) | function Custom() {
FILE: packages/ranui/components/checkbox/index.ts
type Context (line 4) | interface Context {
class Checkbox (line 8) | class Checkbox extends (HTMLElementSSR()!) {
method observedAttributes (line 14) | static get observedAttributes(): string[] {
method constructor (line 17) | constructor() {
method disabled (line 34) | get disabled(): string {
method disabled (line 37) | set disabled(value: string) {
method value (line 40) | get value(): string {
method value (line 47) | set value(value: string) {
method checked (line 57) | get checked(): string {
method checked (line 64) | set checked(value: string) {
method connectedCallback (line 103) | connectedCallback(): void {
method disconnectCallback (line 106) | disconnectCallback(): void {
method attributeChangedCallback (line 109) | attributeChangedCallback(name: string, oldValue: string, newValue: str...
function Custom (line 123) | function Custom() {
FILE: packages/ranui/components/colorpicker/index.ts
constant BOT_WIDTH (line 15) | const BOT_WIDTH = 8;
constant HUE (line 17) | const HUE = 360;
type Context (line 19) | interface Context {
type RGBA (line 28) | interface RGBA {
type Signal (line 35) | interface Signal<T> {
class ColorPicker (line 43) | class ColorPicker extends (HTMLElementSSR()!) {
method observedAttributes (line 69) | static get observedAttributes(): string[] {
method constructor (line 72) | constructor() {
method value (line 90) | get value(): string {
method value (line 93) | set value(value: string) {
method connectedCallback (line 423) | connectedCallback(): void {
method disconnectCallback (line 426) | disconnectCallback(): void {
method attributeChangedCallback (line 433) | attributeChangedCallback(n: string, o: string, v: string): void {
function Custom (line 442) | function Custom() {
FILE: packages/ranui/components/dropdown/index.ts
type ARROW_TYPE (line 7) | enum ARROW_TYPE {
class Dropdown (line 14) | class Dropdown extends (HTMLElementSSR()!) {
method observedAttributes (line 20) | static get observedAttributes(): string[] {
method constructor (line 23) | constructor() {
method transit (line 37) | get transit(): string {
method transit (line 40) | set transit(value: string) {
method arrow (line 47) | get arrow(): string {
method arrow (line 50) | set arrow(value: string) {
method show (line 57) | get show(): string {
method show (line 60) | set show(value: string) {
method connectedCallback (line 85) | connectedCallback(): void {
method disconnectedCallback (line 89) | disconnectedCallback(): void {
method attributeChangedCallback (line 92) | attributeChangedCallback(name: string, _: string, newValue: string): v...
function Custom (line 105) | function Custom() {
FILE: packages/ranui/components/form/index.ts
function Component (line 1) | function Component() {
FILE: packages/ranui/components/icon/index.ts
constant X_LINKS_NS (line 3) | const X_LINKS_NS = 'http://www.w3.org/1999/xlink';
constant X_LINK_HREF (line 4) | const X_LINK_HREF = 'xlink:href';
function Custom (line 6) | function Custom() {
FILE: packages/ranui/components/image/index.ts
function Custom (line 3) | function Custom() {
FILE: packages/ranui/components/input/index.ts
class Input (line 4) | class Input extends (HTMLElementSSR()!) {
method observedAttributes (line 5) | static get observedAttributes(): string[] {
method constructor (line 31) | constructor() {
method value (line 47) | get value(): string {
method value (line 54) | set value(value: string) {
method placeholder (line 67) | get placeholder(): string {
method placeholder (line 74) | set placeholder(value: string) {
method required (line 85) | get required(): string {
method required (line 92) | set required(value: string) {
method disabled (line 103) | get disabled(): string {
method disabled (line 110) | set disabled(value: string) {
method label (line 124) | get label(): string {
method label (line 130) | set label(value: string) {
method status (line 136) | get status(): string {
method status (line 142) | set status(value: string) {
method name (line 155) | get name(): string {
method name (line 162) | set name(value: string) {
method min (line 169) | get min(): string {
method min (line 176) | set min(value: string) {
method max (line 183) | get max(): string {
method max (line 190) | set max(value: string) {
method step (line 197) | get step(): string {
method step (line 204) | set step(value: string) {
method icon (line 211) | get icon(): string {
method icon (line 218) | set icon(value: string) {
method prefix (line 229) | get prefix(): string {
method prefix (line 236) | set prefix(value: string) {
method suffix (line 247) | get suffix(): string {
method suffix (line 254) | set suffix(value: string) {
method type (line 265) | get type(): string {
method type (line 272) | set type(value: string) {
method connectedCallback (line 437) | connectedCallback(): void {
method disconnectCallback (line 458) | disconnectCallback(): void {
method attributeChangedCallback (line 461) | attributeChangedCallback(name: string, oldValue: string, newValue: str...
function Custom (line 466) | function Custom() {
FILE: packages/ranui/components/loading/index.ts
type ICON_NAME_AMP (line 4) | enum ICON_NAME_AMP {
class Loading (line 36) | class Loading extends (HTMLElementSSR()!) {
method observedAttributes (line 38) | static get observedAttributes(): string[] {
method constructor (line 41) | constructor() {
method name (line 48) | get name(): ICON_NAME_AMP {
method name (line 53) | set name(value: string) {
method connectedCallback (line 447) | connectedCallback(): void {
method attributeChangedCallback (line 450) | attributeChangedCallback(k: string, o: string, n: string): void {
function Custom (line 459) | function Custom() {
FILE: packages/ranui/components/math/index.ts
class Math (line 3) | class Math extends (HTMLElementSSR()!) {
method observedAttributes (line 5) | static get observedAttributes(): string[] {
method constructor (line 8) | constructor() {
method latex (line 14) | get latex(): string {
method latex (line 18) | set latex(value: string) {
method render (line 21) | render(): void {
method connectedCallback (line 35) | connectedCallback(): void {
method attributeChangedCallback (line 38) | attributeChangedCallback(k: string, o: string, n: string): void {
function Custom (line 47) | async function Custom() {
FILE: packages/ranui/components/message/index.ts
function Custom (line 26) | function Custom() {
type Window (line 152) | interface Window {
FILE: packages/ranui/components/modal/index.ts
function Custom (line 1) | function Custom() {
FILE: packages/ranui/components/player/index.ts
constant PLAY_STATE_LIST (line 16) | const PLAY_STATE_LIST = ['play', 'playing', 'timeupdate'];
type Callback (line 20) | type Callback = (...args: unknown[]) => unknown;
type EventName (line 21) | type EventName = string | symbol;
type EventItem (line 22) | type EventItem = {
class SHook (line 28) | class SHook {
type HlsPlayer (line 38) | interface HlsPlayer {
type Level (line 47) | interface Level {
type Context (line 57) | interface Context {
type Hls (line 71) | interface Hls {
type HLS (line 79) | type HLS = Hls & (new () => HlsPlayer);
type Window (line 82) | interface Window {
constant SPEED (line 87) | const SPEED = [
class RanPlayer (line 95) | class RanPlayer extends (HTMLElementSSR()!) {
method observedAttributes (line 129) | static get observedAttributes(): string[] {
method constructor (line 136) | constructor() {
method src (line 275) | get src(): string {
method src (line 278) | set src(value: string) {
method debug (line 281) | get debug(): string {
method debug (line 284) | set debug(value: string) {
method volume (line 287) | get volume(): string {
method volume (line 290) | set volume(value: string) {
method currentTime (line 293) | get currentTime(): string {
method currentTime (line 296) | set currentTime(value: string) {
method playbackRate (line 299) | get playbackRate(): string {
method playbackRate (line 302) | set playbackRate(value: string) {
method connectedCallback (line 973) | connectedCallback(): void {
method disconnectCallback (line 992) | disconnectCallback(): void {
function Custom (line 1012) | function Custom() {
FILE: packages/ranui/components/popover/content/index.ts
class Content (line 5) | class Content extends (HTMLElementSSR()!) {
method constructor (line 9) | constructor() {
method connectedCallback (line 40) | connectedCallback(): void {
method disconnectCallback (line 43) | disconnectCallback(): void {
function Custom (line 48) | function Custom() {
FILE: packages/ranui/components/popover/index.ts
constant HOVER_TIME (line 19) | const HOVER_TIME = 16;
type PlacementDirection (line 21) | type PlacementDirection = Record<string, Record<string, string>>;
type PLACEMENT_TYPE (line 42) | enum PLACEMENT_TYPE {
class Popover (line 49) | class Popover extends (HTMLElementSSR()!) {
method observedAttributes (line 59) | static get observedAttributes(): string[] {
method constructor (line 65) | constructor() {
method placement (line 77) | get placement(): string {
method placement (line 80) | set placement(value: string) {
method arrow (line 83) | get arrow(): string {
method arrow (line 86) | set arrow(value: string) {
method trigger (line 89) | get trigger(): string {
method trigger (line 92) | set trigger(value: string) {
method getPopupContainerId (line 95) | get getPopupContainerId(): string {
method getPopupContainerId (line 98) | set getPopupContainerId(value: string) {
method connectedCallback (line 293) | connectedCallback(): void {
method disconnectCallback (line 304) | disconnectCallback(): void {
method attributeChangedCallback (line 310) | attributeChangedCallback(n: string, o: string, v: string): void {
function Custom (line 322) | function Custom() {
FILE: packages/ranui/components/progress/index.ts
class Progress (line 6) | class Progress extends (HTMLElementSSR()!) {
method constructor (line 13) | constructor() {
method observedAttributes (line 34) | static get observedAttributes(): string[] {
method percent (line 37) | get percent(): string {
method percent (line 46) | set percent(value: string) {
method total (line 50) | get total(): string {
method total (line 55) | set total(value: string) {
method type (line 58) | get type(): string {
method type (line 67) | set type(value: string) {
method animation (line 70) | get animation(): string {
method animation (line 79) | set animation(value: string) {
method dot (line 82) | get dot(): string {
method dot (line 91) | set dot(value: string) {
method connectedCallback (line 154) | connectedCallback(): void {
method disconnectCallback (line 163) | disconnectCallback(): void {
method attributeChangedCallback (line 170) | attributeChangedCallback(k: string, o: string, n: string): void {
function Custom (line 182) | function Custom() {
FILE: packages/ranui/components/radar/index.ts
type AbilityTags (line 4) | interface AbilityTags {
constant BACKGROUND_COLOR (line 13) | const BACKGROUND_COLOR = 'rgba(0,0,0,0)';
constant FONT_COLOR (line 14) | const FONT_COLOR = 'rgba(0,0,0,1)';
constant POLYGON_COLOR (line 15) | const POLYGON_COLOR = '#e6e6e6';
constant LINE_COLOR (line 16) | const LINE_COLOR = '#e6e6e6';
constant FONT_FAMILY (line 17) | const FONT_FAMILY = '黑体';
constant FILL_COLOR (line 18) | const FILL_COLOR = 'rgba(255,121,35,0.60)';
constant STROKE_COLOR (line 19) | const STROKE_COLOR = 'rgba(255,121,35,0.60)';
function Custom (line 21) | function Custom() {
FILE: packages/ranui/components/scratch/index.ts
class ScratchTicket (line 3) | class ScratchTicket extends (HTMLElementSSR()!) {
method observedAttributes (line 8) | static get observedAttributes(): string[] {
method constructor (line 11) | constructor() {
method attributeChangedCallback (line 106) | attributeChangedCallback(): void {
FILE: packages/ranui/components/select/dropdown-item/index.ts
class DropdownItem (line 6) | class DropdownItem extends (HTMLElementSSR()!) {
method observedAttributes (line 11) | static get observedAttributes(): string[] {
method constructor (line 14) | constructor() {
method value (line 31) | get value(): string {
method value (line 34) | set value(value: string) {
method active (line 41) | get active(): string {
method active (line 44) | set active(value: string) {
method title (line 51) | get title(): string {
method title (line 54) | set title(value: string) {
method connectedCallback (line 61) | connectedCallback(): void {
method attributeChangedCallback (line 66) | attributeChangedCallback(name: string, _: string, newValue: string): v...
function Custom (line 75) | function Custom() {
FILE: packages/ranui/components/select/index.ts
type Option (line 10) | interface Option {
type PlacementDirection (line 15) | type PlacementDirection = Record<string, Record<string, string>>;
class Select (line 32) | class Select extends (HTMLElementSSR()!) {
method observedAttributes (line 51) | static get observedAttributes(): string[] {
method constructor (line 65) | constructor() {
method value (line 103) | get value(): string {
method value (line 106) | set value(value: string) {
method defaultValue (line 113) | get defaultValue(): string {
method defaultValue (line 116) | set defaultValue(value: string) {
method showSearch (line 119) | get showSearch(): string {
method showSearch (line 122) | set showSearch(value: string) {
method type (line 125) | get type(): string {
method type (line 128) | set type(value: string) {
method placement (line 131) | get placement(): string {
method placement (line 134) | set placement(value: string) {
method sheet (line 137) | get sheet(): string {
method sheet (line 140) | set sheet(value: string) {
method getPopupContainerId (line 143) | get getPopupContainerId(): string {
method getPopupContainerId (line 146) | set getPopupContainerId(value: string) {
method dropdownclass (line 149) | get dropdownclass(): string {
method dropdownclass (line 152) | set dropdownclass(value: string) {
method trigger (line 155) | get trigger(): string {
method trigger (line 158) | set trigger(value: string) {
method disabled (line 161) | get disabled(): boolean {
method disabled (line 164) | set disabled(value: boolean | string | undefined | null) {
method handlerExternalCss (line 173) | handlerExternalCss(): void {
method connectedCallback (line 461) | connectedCallback(): void {
method disconnectCallback (line 469) | disconnectCallback(): void {
method attributeChangedCallback (line 479) | attributeChangedCallback(name: string, oldValue: string, newValue: str...
function Custom (line 495) | function Custom() {
FILE: packages/ranui/components/select/option/index.ts
function Custom (line 3) | function Custom() {
FILE: packages/ranui/components/skeleton/index.ts
function Skeleton (line 1) | function Skeleton() {
FILE: packages/ranui/components/tab/index.ts
function CustomElement (line 4) | function CustomElement() {
FILE: packages/ranui/components/tabpane/index.ts
type ExtendParentNode (line 1) | interface ExtendParentNode {
function CustomElement (line 5) | function CustomElement() {
FILE: packages/ranui/plugins/load-style.ts
type Options (line 2) | interface Options {
function loadStylePlugin (line 6) | function loadStylePlugin(options?: Options): Plugin {
FILE: packages/ranui/plugins/load-svg.ts
type Options (line 6) | interface Options {
function loadSvgPlugin (line 12) | function loadSvgPlugin(options: Options = {}): Plugin {
FILE: packages/ranui/rollup.d.ts
type BaseNodeWithoutComments (line 20) | interface BaseNodeWithoutComments {
type BaseNode (line 29) | interface BaseNode extends BaseNodeWithoutComments {
type NodeMap (line 34) | interface NodeMap {
type Node (line 59) | type Node = NodeMap[keyof NodeMap];
type Comment (line 61) | interface Comment extends BaseNodeWithoutComments {
type SourceLocation (line 66) | interface SourceLocation {
type Position (line 72) | interface Position {
type Program (line 79) | interface Program extends BaseNode {
type Directive (line 86) | interface Directive extends BaseNode {
type BaseFunction (line 92) | interface BaseFunction extends BaseNode {
type Function (line 102) | type Function = FunctionDeclaration | FunctionExpression | ArrowFunction...
type Statement (line 104) | type Statement =
type BaseStatement (line 126) | interface BaseStatement extends BaseNode {}
type EmptyStatement (line 128) | interface EmptyStatement extends BaseStatement {
type BlockStatement (line 132) | interface BlockStatement extends BaseStatement {
type StaticBlock (line 138) | interface StaticBlock extends Omit<BlockStatement, 'type'> {
type ExpressionStatement (line 142) | interface ExpressionStatement extends BaseStatement {
type IfStatement (line 147) | interface IfStatement extends BaseStatement {
type LabeledStatement (line 154) | interface LabeledStatement extends BaseStatement {
type BreakStatement (line 160) | interface BreakStatement extends BaseStatement {
type ContinueStatement (line 165) | interface ContinueStatement extends BaseStatement {
type WithStatement (line 170) | interface WithStatement extends BaseStatement {
type SwitchStatement (line 176) | interface SwitchStatement extends BaseStatement {
type ReturnStatement (line 182) | interface ReturnStatement extends BaseStatement {
type ThrowStatement (line 187) | interface ThrowStatement extends BaseStatement {
type TryStatement (line 192) | interface TryStatement extends BaseStatement {
type WhileStatement (line 199) | interface WhileStatement extends BaseStatement {
type DoWhileStatement (line 205) | interface DoWhileStatement extends BaseStatement {
type ForStatement (line 211) | interface ForStatement extends BaseStatement {
type BaseForXStatement (line 219) | interface BaseForXStatement extends BaseStatement {
type ForInStatement (line 225) | interface ForInStatement extends BaseForXStatement {
type DebuggerStatement (line 229) | interface DebuggerStatement extends BaseStatement {
type Declaration (line 233) | type Declaration = FunctionDeclaration | VariableDeclaration | ClassDecl...
type BaseDeclaration (line 235) | interface BaseDeclaration extends BaseStatement {}
type MaybeNamedFunctionDeclaration (line 237) | interface MaybeNamedFunctionDeclaration extends BaseFunction, BaseDeclar...
type FunctionDeclaration (line 244) | interface FunctionDeclaration extends MaybeNamedFunctionDeclaration {
type VariableDeclaration (line 248) | interface VariableDeclaration extends BaseDeclaration {
type VariableDeclarator (line 254) | interface VariableDeclarator extends BaseNode {
type ExpressionMap (line 260) | interface ExpressionMap {
type Expression (line 288) | type Expression = ExpressionMap[keyof ExpressionMap];
type BaseExpression (line 290) | interface BaseExpression extends BaseNode {}
type ChainElement (line 292) | type ChainElement = SimpleCallExpression | MemberExpression;
type ChainExpression (line 294) | interface ChainExpression extends BaseExpression {
type ThisExpression (line 299) | interface ThisExpression extends BaseExpression {
type ArrayExpression (line 303) | interface ArrayExpression extends BaseExpression {
type ObjectExpression (line 308) | interface ObjectExpression extends BaseExpression {
type PrivateIdentifier (line 313) | interface PrivateIdentifier extends BaseNode {
type Property (line 318) | interface Property extends BaseNode {
type PropertyDefinition (line 328) | interface PropertyDefinition extends BaseNode {
type FunctionExpression (line 336) | interface FunctionExpression extends BaseFunction, BaseExpression {
type SequenceExpression (line 342) | interface SequenceExpression extends BaseExpression {
type UnaryExpression (line 347) | interface UnaryExpression extends BaseExpression {
type BinaryExpression (line 354) | interface BinaryExpression extends BaseExpression {
type AssignmentExpression (line 361) | interface AssignmentExpression extends BaseExpression {
type UpdateExpression (line 368) | interface UpdateExpression extends BaseExpression {
type LogicalExpression (line 375) | interface LogicalExpression extends BaseExpression {
type ConditionalExpression (line 382) | interface ConditionalExpression extends BaseExpression {
type BaseCallExpression (line 389) | interface BaseCallExpression extends BaseExpression {
type CallExpression (line 393) | type CallExpression = SimpleCallExpression | NewExpression;
type SimpleCallExpression (line 395) | interface SimpleCallExpression extends BaseCallExpression {
type NewExpression (line 400) | interface NewExpression extends BaseCallExpression {
type MemberExpression (line 404) | interface MemberExpression extends BaseExpression, BasePattern {
type Pattern (line 412) | type Pattern = Identifier | ObjectPattern | ArrayPattern | RestElement |...
type BasePattern (line 414) | interface BasePattern extends BaseNode {}
type SwitchCase (line 416) | interface SwitchCase extends BaseNode {
type CatchClause (line 422) | interface CatchClause extends BaseNode {
type Identifier (line 428) | interface Identifier extends BaseNode, BaseExpression, BasePattern {
type Literal (line 433) | type Literal = SimpleLiteral | RegExpLiteral | BigIntLiteral;
type SimpleLiteral (line 435) | interface SimpleLiteral extends BaseNode, BaseExpression {
type RegExpLiteral (line 441) | interface RegExpLiteral extends BaseNode, BaseExpression {
type BigIntLiteral (line 451) | interface BigIntLiteral extends BaseNode, BaseExpression {
type UnaryOperator (line 458) | type UnaryOperator = '-' | '+' | '!' | '~' | 'typeof' | 'void' | 'delete';
type BinaryOperator (line 460) | type BinaryOperator =
type LogicalOperator (line 484) | type LogicalOperator = '||' | '&&' | '??';
type AssignmentOperator (line 486) | type AssignmentOperator =
type UpdateOperator (line 504) | type UpdateOperator = '++' | '--';
type ForOfStatement (line 506) | interface ForOfStatement extends BaseForXStatement {
type Super (line 511) | interface Super extends BaseNode {
type SpreadElement (line 515) | interface SpreadElement extends BaseNode {
type ArrowFunctionExpression (line 520) | interface ArrowFunctionExpression extends BaseExpression, BaseFunction {
type YieldExpression (line 526) | interface YieldExpression extends BaseExpression {
type TemplateLiteral (line 532) | interface TemplateLiteral extends BaseExpression {
type TaggedTemplateExpression (line 538) | interface TaggedTemplateExpression extends BaseExpression {
type TemplateElement (line 544) | interface TemplateElement extends BaseNode {
type AssignmentProperty (line 554) | interface AssignmentProperty extends Property {
type ObjectPattern (line 560) | interface ObjectPattern extends BasePattern {
type ArrayPattern (line 565) | interface ArrayPattern extends BasePattern {
type RestElement (line 570) | interface RestElement extends BasePattern {
type AssignmentPattern (line 575) | interface AssignmentPattern extends BasePattern {
type Class (line 581) | type Class = ClassDeclaration | ClassExpression;
type BaseClass (line 582) | interface BaseClass extends BaseNode {
type ClassBody (line 587) | interface ClassBody extends BaseNode {
type MethodDefinition (line 592) | interface MethodDefinition extends BaseNode {
type MaybeNamedClassDeclaration (line 601) | interface MaybeNamedClassDeclaration extends BaseClass, BaseDeclaration {
type ClassDeclaration (line 607) | interface ClassDeclaration extends MaybeNamedClassDeclaration {
type ClassExpression (line 611) | interface ClassExpression extends BaseClass, BaseExpression {
type MetaProperty (line 616) | interface MetaProperty extends BaseExpression {
type ModuleDeclaration (line 622) | type ModuleDeclaration =
type BaseModuleDeclaration (line 627) | interface BaseModuleDeclaration extends BaseNode {}
type ModuleSpecifier (line 629) | type ModuleSpecifier = ImportSpecifier | ImportDefaultSpecifier | Import...
type BaseModuleSpecifier (line 630) | interface BaseModuleSpecifier extends BaseNode {
type ImportDeclaration (line 634) | interface ImportDeclaration extends BaseModuleDeclaration {
type ImportSpecifier (line 640) | interface ImportSpecifier extends BaseModuleSpecifier {
type ImportExpression (line 645) | interface ImportExpression extends BaseExpression {
type ImportDefaultSpecifier (line 650) | interface ImportDefaultSpecifier extends BaseModuleSpecifier {
type ImportNamespaceSpecifier (line 654) | interface ImportNamespaceSpecifier extends BaseModuleSpecifier {
type ExportNamedDeclaration (line 658) | interface ExportNamedDeclaration extends BaseModuleDeclaration {
type ExportSpecifier (line 665) | interface ExportSpecifier extends BaseModuleSpecifier {
type ExportDefaultDeclaration (line 670) | interface ExportDefaultDeclaration extends BaseModuleDeclaration {
type ExportAllDeclaration (line 675) | interface ExportAllDeclaration extends BaseModuleDeclaration {
type AwaitExpression (line 681) | interface AwaitExpression extends BaseExpression {
constant VERSION (line 686) | const VERSION: string;
type NullValue (line 689) | type NullValue = null | undefined | void;
type MaybeArray (line 690) | type MaybeArray<T> = T | T[];
type MaybePromise (line 691) | type MaybePromise<T> = T | Promise<T>;
type PartialNull (line 693) | type PartialNull<T> = {
type RollupError (line 697) | interface RollupError extends RollupLog {
type RollupLog (line 703) | interface RollupLog {
type LogLevel (line 728) | type LogLevel = 'warn' | 'info' | 'debug';
type LogLevelOption (line 729) | type LogLevelOption = LogLevel | 'silent';
type SourceMapSegment (line 731) | type SourceMapSegment = [number] | [number, number, number, number] | [n...
type ExistingDecodedSourceMap (line 733) | interface ExistingDecodedSourceMap {
type ExistingRawSourceMap (line 744) | interface ExistingRawSourceMap {
type DecodedSourceMapOrMissing (line 755) | type DecodedSourceMapOrMissing =
type SourceMap (line 762) | interface SourceMap {
type SourceMapInput (line 773) | type SourceMapInput = ExistingRawSourceMap | string | null | { mappings:...
type ModuleOptions (line 775) | interface ModuleOptions {
type SourceDescription (line 782) | interface SourceDescription extends Partial<PartialNull<ModuleOptions>> {
type TransformModuleJSON (line 788) | interface TransformModuleJSON {
type ModuleJSON (line 799) | interface ModuleJSON extends TransformModuleJSON, ModuleOptions {
type PluginCache (line 807) | interface PluginCache {
type LoggingFunction (line 814) | type LoggingFunction = (log: RollupLog | string | (() => RollupLog | str...
type MinimalPluginContext (line 816) | interface MinimalPluginContext {
type EmittedAsset (line 824) | interface EmittedAsset {
type EmittedChunk (line 832) | interface EmittedChunk {
type EmittedPrebuiltChunk (line 842) | interface EmittedPrebuiltChunk {
type EmittedFile (line 851) | type EmittedFile = EmittedAsset | EmittedChunk | EmittedPrebuiltChunk;
type EmitFile (line 853) | type EmitFile = (emittedFile: EmittedFile) => string;
type ModuleInfo (line 855) | interface ModuleInfo extends ModuleOptions {
type GetModuleInfo (line 875) | type GetModuleInfo = (moduleId: string) => ModuleInfo | null;
type CustomPluginOptions (line 877) | interface CustomPluginOptions {
type LoggingFunctionWithPosition (line 881) | type LoggingFunctionWithPosition = (
type ParseAst (line 886) | type ParseAst = (input: string, options?: { allowReturnOutsideFunction?:...
type AbortSignal (line 890) | interface AbortSignal {}
type ParseAstAsync (line 893) | type ParseAstAsync = (
type PluginContext (line 898) | interface PluginContext extends MinimalPluginContext {
type PluginContextMeta (line 927) | interface PluginContextMeta {
type ResolvedId (line 932) | interface ResolvedId extends ModuleOptions {
type ResolvedIdMap (line 938) | interface ResolvedIdMap {
type PartialResolvedId (line 942) | interface PartialResolvedId extends Partial<PartialNull<ModuleOptions>> {
type ResolveIdResult (line 948) | type ResolveIdResult = string | NullValue | false | PartialResolvedId;
type ResolveIdResultWithoutNullValue (line 950) | type ResolveIdResultWithoutNullValue = string | false | PartialResolvedId;
type ResolveIdHook (line 952) | type ResolveIdHook = (
type ShouldTransformCachedModuleHook (line 959) | type ShouldTransformCachedModuleHook = (
type IsExternal (line 972) | type IsExternal = (source: string, importer: string | undefined, isResol...
type HasModuleSideEffects (line 974) | type HasModuleSideEffects = (id: string, external: boolean) => boolean;
type LoadResult (line 976) | type LoadResult = SourceDescription | string | NullValue;
type LoadHook (line 978) | type LoadHook = (this: PluginContext, id: string) => LoadResult;
type TransformPluginContext (line 980) | interface TransformPluginContext extends PluginContext {
type TransformResult (line 988) | type TransformResult = string | NullValue | Partial<SourceDescription>;
type TransformHook (line 990) | type TransformHook = (this: TransformPluginContext, code: string, id: st...
type ModuleParsedHook (line 992) | type ModuleParsedHook = (this: PluginContext, info: ModuleInfo) => void;
type RenderChunkHook (line 994) | type RenderChunkHook = (
type ResolveDynamicImportHook (line 1002) | type ResolveDynamicImportHook = (
type ResolveImportMetaHook (line 1009) | type ResolveImportMetaHook = (
type ResolveFileUrlHook (line 1015) | type ResolveFileUrlHook = (
type AddonHookFunction (line 1027) | type AddonHookFunction = (this: PluginContext, chunk: RenderedChunk) => ...
type AddonHook (line 1028) | type AddonHook = string | AddonHookFunction;
type ChangeEvent (line 1030) | type ChangeEvent = 'create' | 'update' | 'delete';
type WatchChangeHook (line 1031) | type WatchChangeHook = (this: PluginContext, id: string, change: { event...
type PluginImpl (line 1044) | type PluginImpl<O extends object = object, A = any> = (options?: O) => P...
type OutputBundle (line 1046) | interface OutputBundle {
type FunctionPluginHooks (line 1050) | interface FunctionPluginHooks {
type OutputPluginHooks (line 1093) | type OutputPluginHooks =
type InputPluginHooks (line 1105) | type InputPluginHooks = Exclude<keyof FunctionPluginHooks, OutputPluginH...
type SyncPluginHooks (line 1107) | type SyncPluginHooks =
type AsyncPluginHooks (line 1115) | type AsyncPluginHooks = Exclude<keyof FunctionPluginHooks, SyncPluginHoo...
type FirstPluginHooks (line 1117) | type FirstPluginHooks =
type SequentialPluginHooks (line 1126) | type SequentialPluginHooks =
type ParallelPluginHooks (line 1135) | type ParallelPluginHooks = Exclude<
type AddonHooks (line 1140) | type AddonHooks = 'banner' | 'footer' | 'intro' | 'outro';
type MakeAsync (line 1142) | type MakeAsync<Function_> = Function_ extends (this: infer This, ...para...
type ObjectHook (line 1146) | type ObjectHook<T, O = {}> = T | ({ handler: T; order?: 'pre' | 'post' |...
type PluginHooks (line 1148) | type PluginHooks = {
type OutputPlugin (line 1155) | interface OutputPlugin
type Plugin (line 1163) | interface Plugin<A = any> extends OutputPlugin, Partial<PluginHooks> {
type TreeshakingPreset (line 1168) | type TreeshakingPreset = 'smallest' | 'safest' | 'recommended';
type NormalizedTreeshakingOptions (line 1170) | interface NormalizedTreeshakingOptions {
type TreeshakingOptions (line 1180) | interface TreeshakingOptions extends Partial<Omit<NormalizedTreeshakingO...
type ManualChunkMeta (line 1185) | interface ManualChunkMeta {
type GetManualChunk (line 1189) | type GetManualChunk = (id: string, meta: ManualChunkMeta) => string | Nu...
type ExternalOption (line 1191) | type ExternalOption =
type GlobalsOption (line 1197) | type GlobalsOption = { [name: string]: string } | ((name: string) => str...
type InputOption (line 1199) | type InputOption = string | string[] | { [entryAlias: string]: string };
type ManualChunksOption (line 1201) | type ManualChunksOption = { [chunkAlias: string]: string[] } | GetManual...
type LogHandlerWithDefault (line 1203) | type LogHandlerWithDefault = (level: LogLevel, log: RollupLog, defaultHa...
type LogOrStringHandler (line 1205) | type LogOrStringHandler = (level: LogLevel | 'error', log: RollupLog | s...
type LogHandler (line 1207) | type LogHandler = (level: LogLevel, log: RollupLog) => void;
type ModuleSideEffectsOption (line 1209) | type ModuleSideEffectsOption = boolean | 'no-external' | string[] | HasM...
type PreserveEntrySignaturesOption (line 1211) | type PreserveEntrySignaturesOption = false | 'strict' | 'allow-extension...
type SourcemapPathTransformOption (line 1213) | type SourcemapPathTransformOption = (relativeSourcePath: string, sourcem...
type SourcemapIgnoreListOption (line 1215) | type SourcemapIgnoreListOption = (relativeSourcePath: string, sourcemapP...
type InputPluginOption (line 1217) | type InputPluginOption = MaybePromise<Plugin | NullValue | false | Input...
type InputOptions (line 1219) | interface InputOptions {
type InputOptionsWithPlugins (line 1242) | interface InputOptionsWithPlugins extends InputOptions {
type NormalizedInputOptions (line 1246) | interface NormalizedInputOptions {
type InternalModuleFormat (line 1267) | type InternalModuleFormat = 'amd' | 'cjs' | 'es' | 'iife' | 'system' | '...
type ModuleFormat (line 1269) | type ModuleFormat = InternalModuleFormat | 'commonjs' | 'esm' | 'module'...
type GeneratedCodePreset (line 1271) | type GeneratedCodePreset = 'es5' | 'es2015';
type NormalizedGeneratedCodeOptions (line 1273) | interface NormalizedGeneratedCodeOptions {
type GeneratedCodeOptions (line 1281) | interface GeneratedCodeOptions extends Partial<NormalizedGeneratedCodeOp...
type OptionsPaths (line 1285) | type OptionsPaths = Record<string, string> | ((id: string) => string);
type InteropType (line 1287) | type InteropType = 'compat' | 'auto' | 'esModule' | 'default' | 'default...
type GetInterop (line 1289) | type GetInterop = (id: string | null) => InteropType;
type AmdOptions (line 1291) | type AmdOptions = (
type NormalizedAmdOptions (line 1310) | type NormalizedAmdOptions = (
type AddonFunction (line 1324) | type AddonFunction = (chunk: RenderedChunk) => string | Promise<string>;
type OutputPluginOption (line 1326) | type OutputPluginOption = MaybePromise<OutputPlugin | NullValue | false ...
type HashCharacters (line 1328) | type HashCharacters = 'base64' | 'base36' | 'hex';
type OutputOptions (line 1330) | interface OutputOptions {
type NormalizedOutputOptions (line 1383) | interface NormalizedOutputOptions {
type WarningHandlerWithDefault (line 1434) | type WarningHandlerWithDefault = (warning: RollupLog, defaultHandler: Lo...
type SerializedTimings (line 1436) | interface SerializedTimings {
type PreRenderedAsset (line 1440) | interface PreRenderedAsset {
type OutputAsset (line 1446) | interface OutputAsset extends PreRenderedAsset {
type RenderedModule (line 1451) | interface RenderedModule {
type PreRenderedChunk (line 1459) | interface PreRenderedChunk {
type RenderedChunk (line 1470) | interface RenderedChunk extends PreRenderedChunk {
type OutputChunk (line 1484) | interface OutputChunk extends RenderedChunk {
type SerializablePluginCache (line 1491) | interface SerializablePluginCache {
type RollupCache (line 1495) | interface RollupCache {
type RollupOutput (line 1500) | interface RollupOutput {
type RollupBuild (line 1504) | interface RollupBuild {
type RollupOptions (line 1514) | interface RollupOptions extends InputOptions {
type MergedRollupOptions (line 1519) | interface MergedRollupOptions extends InputOptionsWithPlugins {
type ChokidarOptions (line 1525) | interface ChokidarOptions {
type RollupWatchHooks (line 1548) | type RollupWatchHooks = 'onError' | 'onStart' | 'onBundleStart' | 'onBun...
type WatcherOptions (line 1550) | interface WatcherOptions {
type RollupWatchOptions (line 1559) | interface RollupWatchOptions extends InputOptions {
type AwaitedEventListener (line 1564) | type AwaitedEventListener<T extends { [event: string]: (...parameters: a...
type AwaitingEventEmitter (line 1568) | interface AwaitingEventEmitter<T extends { [event: string]: (...paramete...
type RollupWatcherEvent (line 1596) | type RollupWatcherEvent =
type RollupWatcher (line 1609) | type RollupWatcher = AwaitingEventEmitter<{
type AstNode (line 1618) | interface AstNode {
type ProgramNode (line 1624) | type ProgramNode = Program & AstNode;
type RollupOptionsFunction (line 1630) | type RollupOptionsFunction = (
FILE: packages/ranui/shadowless/icon/index.ts
constant X_LINKS_NS (line 4) | const X_LINKS_NS = 'http://www.w3.org/1999/xlink';
constant X_LINK_HREF (line 5) | const X_LINK_HREF = 'xlink:href';
function Custom (line 7) | function Custom() {
FILE: packages/ranui/shadowless/input/index.ts
class Input (line 4) | class Input extends (HTMLElementSSR()!) {
method observedAttributes (line 5) | static get observedAttributes(): string[] {
method constructor (line 31) | constructor() {
method value (line 45) | get value(): string {
method value (line 52) | set value(value: string) {
method placeholder (line 65) | get placeholder(): string {
method placeholder (line 72) | set placeholder(value: string) {
method required (line 83) | get required(): string {
method required (line 90) | set required(value: string) {
method disabled (line 101) | get disabled(): string {
method disabled (line 108) | set disabled(value: string) {
method label (line 122) | get label(): string {
method label (line 128) | set label(value: string) {
method status (line 134) | get status(): string {
method status (line 140) | set status(value: string) {
method name (line 153) | get name(): string {
method name (line 160) | set name(value: string) {
method min (line 167) | get min(): string {
method min (line 174) | set min(value: string) {
method max (line 181) | get max(): string {
method max (line 188) | set max(value: string) {
method step (line 195) | get step(): string {
method step (line 202) | set step(value: string) {
method icon (line 209) | get icon(): string {
method icon (line 216) | set icon(value: string) {
method prefix (line 227) | get prefix(): string {
method prefix (line 234) | set prefix(value: string) {
method suffix (line 245) | get suffix(): string {
method suffix (line 252) | set suffix(value: string) {
method type (line 263) | get type(): string {
method type (line 270) | set type(value: string) {
method connectedCallback (line 437) | connectedCallback(): void {
method disconnectCallback (line 459) | disconnectCallback(): void {
method attributeChangedCallback (line 462) | attributeChangedCallback(name: string, oldValue: string, newValue: str...
function Custom (line 467) | function Custom() {
FILE: packages/ranui/shadowless/select/index.ts
type Option (line 9) | interface Option {
type PlacementDirection (line 14) | type PlacementDirection = Record<string, Record<string, string>>;
class Select (line 29) | class Select extends (HTMLElementSSR()!) {
method observedAttributes (line 46) | static get observedAttributes(): string[] {
method constructor (line 60) | constructor() {
method value (line 92) | get value(): string {
method value (line 95) | set value(value: string) {
method defaultValue (line 102) | get defaultValue(): string {
method defaultValue (line 105) | set defaultValue(value: string) {
method showSearch (line 108) | get showSearch(): string {
method showSearch (line 111) | set showSearch(value: string) {
method type (line 114) | get type(): string {
method type (line 117) | set type(value: string) {
method placement (line 120) | get placement(): string {
method placement (line 123) | set placement(value: string) {
method sheet (line 126) | get sheet(): string {
method sheet (line 129) | set sheet(value: string) {
method getPopupContainerId (line 132) | get getPopupContainerId(): string {
method getPopupContainerId (line 135) | set getPopupContainerId(value: string) {
method dropdownclass (line 138) | get dropdownclass(): string {
method dropdownclass (line 141) | set dropdownclass(value: string) {
method trigger (line 144) | get trigger(): string {
method trigger (line 147) | set trigger(value: string) {
method disabled (line 150) | get disabled(): boolean {
method disabled (line 153) | set disabled(value: boolean | string | undefined | null) {
method connectedCallback (line 448) | connectedCallback(): void {
method disconnectCallback (line 454) | disconnectCallback(): void {
method attributeChangedCallback (line 463) | attributeChangedCallback(name: string, _: string, newValue: string): v...
function Custom (line 476) | function Custom() {
FILE: packages/ranui/shadowless/select/option/index.ts
function Custom (line 3) | function Custom() {
FILE: packages/ranui/typings.d.ts
type Prompt (line 11) | interface Prompt {
type Hint (line 17) | type Hint = (options: Prompt | string | undefined | null) => void;
type Message (line 19) | interface Message {
type Ranui (line 28) | interface Ranui {
type HlsPlayer (line 32) | interface HlsPlayer {
type Hls (line 41) | interface Hls {
type HLS (line 49) | type HLS = Hls & (new () => HlsPlayer);
type Viewport (line 51) | interface Viewport {
type RenderContext (line 56) | interface RenderContext {
type PDFPageProxy (line 62) | interface PDFPageProxy {
type PDFDocumentProxy (line 68) | interface PDFDocumentProxy {
type HTMLElement (line 73) | interface HTMLElement {
type Document (line 80) | interface Document {
type MathJax (line 87) | interface MathJax {
type Window (line 94) | interface Window {
type ICON_NAME_AMP (line 112) | enum ICON_NAME_AMP {
type BaseIntrinsicElements (line 143) | interface BaseIntrinsicElements {
type IntrinsicElements (line 248) | interface IntrinsicElements extends BaseIntrinsicElements {}
type IntrinsicElements (line 253) | interface IntrinsicElements extends BaseIntrinsicElements {}
FILE: packages/ranui/utils/color.ts
constant HEX_COLOR_REGEX (line 144) | const HEX_COLOR_REGEX = /^#([\da-f]{6}|[\da-f]{3})$/i;
constant RGB_REGEX (line 146) | const RGB_REGEX = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/;
constant RGBA_REGEX (line 148) | const RGBA_REGEX = /^rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d{1,3}(\.\d+)...
FILE: packages/ranui/utils/image.ts
type ImgType (line 3) | type ImgType = HTMLImageElement | HTMLCanvasElement;
FILE: packages/ranui/utils/index.ts
type CustomErrorType (line 103) | interface CustomErrorType {
function createCustomError (line 107) | function createCustomError(msg: string = ''): CustomErrorType {
function getMimeTypeFromExtension (line 212) | function getMimeTypeFromExtension(fileName: string): string {
FILE: packages/ranui/utils/tween.ts
type SpeedType (line 11) | interface SpeedType {
FILE: packages/ranui/vite.config.ts
type chunkOptimization (line 18) | interface chunkOptimization {
FILE: packages/ranuts/assets/wasm/word/wasmjieba-web.d.ts
type TokenizeMode (line 51) | enum TokenizeMode {
type InitInput (line 56) | type InitInput = RequestInfo | URL | Response | BufferSource | WebAssemb...
type InitOutput (line 58) | interface InitOutput {
type SyncInitInput (line 74) | type SyncInitInput = BufferSource | WebAssembly.Module;
FILE: packages/ranuts/assets/wasm/word/wasmjieba-web.js
function getObject (line 7) | function getObject(idx) {
function dropObject (line 13) | function dropObject(idx) {
function takeObject (line 19) | function takeObject(idx) {
function getUint8Memory0 (line 40) | function getUint8Memory0() {
function getStringFromWasm0 (line 47) | function getStringFromWasm0(ptr, len) {
function addHeapObject (line 52) | function addHeapObject(obj) {
function debugString (line 61) | function debugString(val) {
constant WASM_VECTOR_LEN (line 126) | let WASM_VECTOR_LEN = 0;
function passStringToWasm0 (line 151) | function passStringToWasm0(arg, malloc, realloc) {
function getInt32Memory0 (line 192) | function getInt32Memory0() {
function getUint32Memory0 (line 201) | function getUint32Memory0() {
function getArrayJsValueFromWasm0 (line 208) | function getArrayJsValueFromWasm0(ptr, len) {
function cut (line 223) | function cut(text, hmm) {
function cutAll (line 243) | function cutAll(text) {
function cutForSearch (line 264) | function cutForSearch(text, hmm) {
function isLikeNone (line 280) | function isLikeNone(x) {
function tokenize (line 289) | function tokenize(text, mode, hmm) {
function tag (line 310) | function tag(sentence, hmm) {
function suggestFreq (line 330) | function suggestFreq(segment) {
function addWord (line 343) | function addWord(word, freq, tag) {
function loadDict (line 355) | function loadDict(dict) {
function __wbg_load (line 365) | async function __wbg_load(module, imports) {
function __wbg_get_imports (line 395) | function __wbg_get_imports() {
function __wbg_init_memory (line 464) | function __wbg_init_memory(imports, maybe_memory) {}
function __wbg_finalize_init (line 466) | function __wbg_finalize_init(instance, module) {
function initSync (line 476) | function initSync(module) {
function __wbg_init (line 492) | async function __wbg_init(input) {
FILE: packages/ranuts/examples/clone-deep-example.ts
class Person (line 152) | class Person {
method constructor (line 156) | constructor(name: string, age: number) {
method greet (line 161) | greet() {
FILE: packages/ranuts/plugins/vite-plugins-banner.ts
function vitePluginBanner (line 12) | function vitePluginBanner(): Plugin {
FILE: packages/ranuts/rollup.d.ts
type BaseNodeWithoutComments (line 20) | interface BaseNodeWithoutComments {
type BaseNode (line 29) | interface BaseNode extends BaseNodeWithoutComments {
type NodeMap (line 34) | interface NodeMap {
type Node (line 59) | type Node = NodeMap[keyof NodeMap];
type Comment (line 61) | interface Comment extends BaseNodeWithoutComments {
type SourceLocation (line 66) | interface SourceLocation {
type Position (line 72) | interface Position {
type Program (line 79) | interface Program extends BaseNode {
type Directive (line 86) | interface Directive extends BaseNode {
type BaseFunction (line 92) | interface BaseFunction extends BaseNode {
type Function (line 102) | type Function = FunctionDeclaration | FunctionExpression | ArrowFunction...
type Statement (line 104) | type Statement =
type BaseStatement (line 126) | interface BaseStatement extends BaseNode {}
type EmptyStatement (line 128) | interface EmptyStatement extends BaseStatement {
type BlockStatement (line 132) | interface BlockStatement extends BaseStatement {
type StaticBlock (line 138) | interface StaticBlock extends Omit<BlockStatement, 'type'> {
type ExpressionStatement (line 142) | interface ExpressionStatement extends BaseStatement {
type IfStatement (line 147) | interface IfStatement extends BaseStatement {
type LabeledStatement (line 154) | interface LabeledStatement extends BaseStatement {
type BreakStatement (line 160) | interface BreakStatement extends BaseStatement {
type ContinueStatement (line 165) | interface ContinueStatement extends BaseStatement {
type WithStatement (line 170) | interface WithStatement extends BaseStatement {
type SwitchStatement (line 176) | interface SwitchStatement extends BaseStatement {
type ReturnStatement (line 182) | interface ReturnStatement extends BaseStatement {
type ThrowStatement (line 187) | interface ThrowStatement extends BaseStatement {
type TryStatement (line 192) | interface TryStatement extends BaseStatement {
type WhileStatement (line 199) | interface WhileStatement extends BaseStatement {
type DoWhileStatement (line 205) | interface DoWhileStatement extends BaseStatement {
type ForStatement (line 211) | interface ForStatement extends BaseStatement {
type BaseForXStatement (line 219) | interface BaseForXStatement extends BaseStatement {
type ForInStatement (line 225) | interface ForInStatement extends BaseForXStatement {
type DebuggerStatement (line 229) | interface DebuggerStatement extends BaseStatement {
type Declaration (line 233) | type Declaration = FunctionDeclaration | VariableDeclaration | ClassDecl...
type BaseDeclaration (line 235) | interface BaseDeclaration extends BaseStatement {}
type MaybeNamedFunctionDeclaration (line 237) | interface MaybeNamedFunctionDeclaration extends BaseFunction, BaseDeclar...
type FunctionDeclaration (line 244) | interface FunctionDeclaration extends MaybeNamedFunctionDeclaration {
type VariableDeclaration (line 248) | interface VariableDeclaration extends BaseDeclaration {
type VariableDeclarator (line 254) | interface VariableDeclarator extends BaseNode {
type ExpressionMap (line 260) | interface ExpressionMap {
type Expression (line 288) | type Expression = ExpressionMap[keyof ExpressionMap];
type BaseExpression (line 290) | interface BaseExpression extends BaseNode {}
type ChainElement (line 292) | type ChainElement = SimpleCallExpression | MemberExpression;
type ChainExpression (line 294) | interface ChainExpression extends BaseExpression {
type ThisExpression (line 299) | interface ThisExpression extends BaseExpression {
type ArrayExpression (line 303) | interface ArrayExpression extends BaseExpression {
type ObjectExpression (line 308) | interface ObjectExpression extends BaseExpression {
type PrivateIdentifier (line 313) | interface PrivateIdentifier extends BaseNode {
type Property (line 318) | interface Property extends BaseNode {
type PropertyDefinition (line 328) | interface PropertyDefinition extends BaseNode {
type FunctionExpression (line 336) | interface FunctionExpression extends BaseFunction, BaseExpression {
type SequenceExpression (line 342) | interface SequenceExpression extends BaseExpression {
type UnaryExpression (line 347) | interface UnaryExpression extends BaseExpression {
type BinaryExpression (line 354) | interface BinaryExpression extends BaseExpression {
type AssignmentExpression (line 361) | interface AssignmentExpression extends BaseExpression {
type UpdateExpression (line 368) | interface UpdateExpression extends BaseExpression {
type LogicalExpression (line 375) | interface LogicalExpression extends BaseExpression {
type ConditionalExpression (line 382) | interface ConditionalExpression extends BaseExpression {
type BaseCallExpression (line 389) | interface BaseCallExpression extends BaseExpression {
type CallExpression (line 393) | type CallExpression = SimpleCallExpression | NewExpression;
type SimpleCallExpression (line 395) | interface SimpleCallExpression extends BaseCallExpression {
type NewExpression (line 400) | interface NewExpression extends BaseCallExpression {
type MemberExpression (line 404) | interface MemberExpression extends BaseExpression, BasePattern {
type Pattern (line 412) | type Pattern = Identifier | ObjectPattern | ArrayPattern | RestElement |...
type BasePattern (line 414) | interface BasePattern extends BaseNode {}
type SwitchCase (line 416) | interface SwitchCase extends BaseNode {
type CatchClause (line 422) | interface CatchClause extends BaseNode {
type Identifier (line 428) | interface Identifier extends BaseNode, BaseExpression, BasePattern {
type Literal (line 433) | type Literal = SimpleLiteral | RegExpLiteral | BigIntLiteral;
type SimpleLiteral (line 435) | interface SimpleLiteral extends BaseNode, BaseExpression {
type RegExpLiteral (line 441) | interface RegExpLiteral extends BaseNode, BaseExpression {
type BigIntLiteral (line 451) | interface BigIntLiteral extends BaseNode, BaseExpression {
type UnaryOperator (line 458) | type UnaryOperator = '-' | '+' | '!' | '~' | 'typeof' | 'void' | 'delete';
type BinaryOperator (line 460) | type BinaryOperator =
type LogicalOperator (line 484) | type LogicalOperator = '||' | '&&' | '??';
type AssignmentOperator (line 486) | type AssignmentOperator =
type UpdateOperator (line 504) | type UpdateOperator = '++' | '--';
type ForOfStatement (line 506) | interface ForOfStatement extends BaseForXStatement {
type Super (line 511) | interface Super extends BaseNode {
type SpreadElement (line 515) | interface SpreadElement extends BaseNode {
type ArrowFunctionExpression (line 520) | interface ArrowFunctionExpression extends BaseExpression, BaseFunction {
type YieldExpression (line 526) | interface YieldExpression extends BaseExpression {
type TemplateLiteral (line 532) | interface TemplateLiteral extends BaseExpression {
type TaggedTemplateExpression (line 538) | interface TaggedTemplateExpression extends BaseExpression {
type TemplateElement (line 544) | interface TemplateElement extends BaseNode {
type AssignmentProperty (line 554) | interface AssignmentProperty extends Property {
type ObjectPattern (line 560) | interface ObjectPattern extends BasePattern {
type ArrayPattern (line 565) | interface ArrayPattern extends BasePattern {
type RestElement (line 570) | interface RestElement extends BasePattern {
type AssignmentPattern (line 575) | interface AssignmentPattern extends BasePattern {
type Class (line 581) | type Class = ClassDeclaration | ClassExpression;
type BaseClass (line 582) | interface BaseClass extends BaseNode {
type ClassBody (line 587) | interface ClassBody extends BaseNode {
type MethodDefinition (line 592) | interface MethodDefinition extends BaseNode {
type MaybeNamedClassDeclaration (line 601) | interface MaybeNamedClassDeclaration extends BaseClass, BaseDeclaration {
type ClassDeclaration (line 607) | interface ClassDeclaration extends MaybeNamedClassDeclaration {
type ClassExpression (line 611) | interface ClassExpression extends BaseClass, BaseExpression {
type MetaProperty (line 616) | interface MetaProperty extends BaseExpression {
type ModuleDeclaration (line 622) | type ModuleDeclaration =
type BaseModuleDeclaration (line 627) | interface BaseModuleDeclaration extends BaseNode {}
type ModuleSpecifier (line 629) | type ModuleSpecifier = ImportSpecifier | ImportDefaultSpecifier | Import...
type BaseModuleSpecifier (line 630) | interface BaseModuleSpecifier extends BaseNode {
type ImportDeclaration (line 634) | interface ImportDeclaration extends BaseModuleDeclaration {
type ImportSpecifier (line 640) | interface ImportSpecifier extends BaseModuleSpecifier {
type ImportExpression (line 645) | interface ImportExpression extends BaseExpression {
type ImportDefaultSpecifier (line 650) | interface ImportDefaultSpecifier extends BaseModuleSpecifier {
type ImportNamespaceSpecifier (line 654) | interface ImportNamespaceSpecifier extends BaseModuleSpecifier {
type ExportNamedDeclaration (line 658) | interface ExportNamedDeclaration extends BaseModuleDeclaration {
type ExportSpecifier (line 665) | interface ExportSpecifier extends BaseModuleSpecifier {
type ExportDefaultDeclaration (line 670) | interface ExportDefaultDeclaration extends BaseModuleDeclaration {
type ExportAllDeclaration (line 675) | interface ExportAllDeclaration extends BaseModuleDeclaration {
type AwaitExpression (line 681) | interface AwaitExpression extends BaseExpression {
constant VERSION (line 686) | const VERSION: string;
type NullValue (line 689) | type NullValue = null | undefined | void;
type MaybeArray (line 690) | type MaybeArray<T> = T | T[];
type MaybePromise (line 691) | type MaybePromise<T> = T | Promise<T>;
type PartialNull (line 693) | type PartialNull<T> = {
type RollupError (line 697) | interface RollupError extends RollupLog {
type RollupLog (line 703) | interface RollupLog {
type LogLevel (line 728) | type LogLevel = 'warn' | 'info' | 'debug';
type LogLevelOption (line 729) | type LogLevelOption = LogLevel | 'silent';
type SourceMapSegment (line 731) | type SourceMapSegment = [number] | [number, number, number, number] | [n...
type ExistingDecodedSourceMap (line 733) | interface ExistingDecodedSourceMap {
type ExistingRawSourceMap (line 744) | interface ExistingRawSourceMap {
type DecodedSourceMapOrMissing (line 755) | type DecodedSourceMapOrMissing =
type SourceMap (line 762) | interface SourceMap {
type SourceMapInput (line 773) | type SourceMapInput = ExistingRawSourceMap | string | null | { mappings:...
type ModuleOptions (line 775) | interface ModuleOptions {
type SourceDescription (line 782) | interface SourceDescription extends Partial<PartialNull<ModuleOptions>> {
type TransformModuleJSON (line 788) | interface TransformModuleJSON {
type ModuleJSON (line 799) | interface ModuleJSON extends TransformModuleJSON, ModuleOptions {
type PluginCache (line 807) | interface PluginCache {
type LoggingFunction (line 814) | type LoggingFunction = (log: RollupLog | string | (() => RollupLog | str...
type MinimalPluginContext (line 816) | interface MinimalPluginContext {
type EmittedAsset (line 824) | interface EmittedAsset {
type EmittedChunk (line 832) | interface EmittedChunk {
type EmittedPrebuiltChunk (line 842) | interface EmittedPrebuiltChunk {
type EmittedFile (line 851) | type EmittedFile = EmittedAsset | EmittedChunk | EmittedPrebuiltChunk;
type EmitFile (line 853) | type EmitFile = (emittedFile: EmittedFile) => string;
type ModuleInfo (line 855) | interface ModuleInfo extends ModuleOptions {
type GetModuleInfo (line 875) | type GetModuleInfo = (moduleId: string) => ModuleInfo | null;
type CustomPluginOptions (line 877) | interface CustomPluginOptions {
type LoggingFunctionWithPosition (line 881) | type LoggingFunctionWithPosition = (
type ParseAst (line 886) | type ParseAst = (input: string, options?: { allowReturnOutsideFunction?:...
type AbortSignal (line 890) | interface AbortSignal {}
type ParseAstAsync (line 893) | type ParseAstAsync = (
type PluginContext (line 898) | interface PluginContext extends MinimalPluginContext {
type PluginContextMeta (line 927) | interface PluginContextMeta {
type ResolvedId (line 932) | interface ResolvedId extends ModuleOptions {
type ResolvedIdMap (line 938) | interface ResolvedIdMap {
type PartialResolvedId (line 942) | interface PartialResolvedId extends Partial<PartialNull<ModuleOptions>> {
type ResolveIdResult (line 948) | type ResolveIdResult = string | NullValue | false | PartialResolvedId;
type ResolveIdResultWithoutNullValue (line 950) | type ResolveIdResultWithoutNullValue = string | false | PartialResolvedId;
type ResolveIdHook (line 952) | type ResolveIdHook = (
type ShouldTransformCachedModuleHook (line 959) | type ShouldTransformCachedModuleHook = (
type IsExternal (line 972) | type IsExternal = (source: string, importer: string | undefined, isResol...
type HasModuleSideEffects (line 974) | type HasModuleSideEffects = (id: string, external: boolean) => boolean;
type LoadResult (line 976) | type LoadResult = SourceDescription | string | NullValue;
type LoadHook (line 978) | type LoadHook = (this: PluginContext, id: string) => LoadResult;
type TransformPluginContext (line 980) | interface TransformPluginContext extends PluginContext {
type TransformResult (line 988) | type TransformResult = string | NullValue | Partial<SourceDescription>;
type TransformHook (line 990) | type TransformHook = (this: TransformPluginContext, code: string, id: st...
type ModuleParsedHook (line 992) | type ModuleParsedHook = (this: PluginContext, info: ModuleInfo) => void;
type RenderChunkHook (line 994) | type RenderChunkHook = (
type ResolveDynamicImportHook (line 1002) | type ResolveDynamicImportHook = (
type ResolveImportMetaHook (line 1009) | type ResolveImportMetaHook = (
type ResolveFileUrlHook (line 1015) | type ResolveFileUrlHook = (
type AddonHookFunction (line 1027) | type AddonHookFunction = (this: PluginContext, chunk: RenderedChunk) => ...
type AddonHook (line 1028) | type AddonHook = string | AddonHookFunction;
type ChangeEvent (line 1030) | type ChangeEvent = 'create' | 'update' | 'delete';
type WatchChangeHook (line 1031) | type WatchChangeHook = (this: PluginContext, id: string, change: { event...
type PluginImpl (line 1044) | type PluginImpl<O extends object = object, A = any> = (options?: O) => P...
type OutputBundle (line 1046) | interface OutputBundle {
type FunctionPluginHooks (line 1050) | interface FunctionPluginHooks {
type OutputPluginHooks (line 1093) | type OutputPluginHooks =
type InputPluginHooks (line 1105) | type InputPluginHooks = Exclude<keyof FunctionPluginHooks, OutputPluginH...
type SyncPluginHooks (line 1107) | type SyncPluginHooks =
type AsyncPluginHooks (line 1115) | type AsyncPluginHooks = Exclude<keyof FunctionPluginHooks, SyncPluginHoo...
type FirstPluginHooks (line 1117) | type FirstPluginHooks =
type SequentialPluginHooks (line 1126) | type SequentialPluginHooks =
type ParallelPluginHooks (line 1135) | type ParallelPluginHooks = Exclude<
type AddonHooks (line 1140) | type AddonHooks = 'banner' | 'footer' | 'intro' | 'outro';
type MakeAsync (line 1142) | type MakeAsync<Function_> = Function_ extends (this: infer This, ...para...
type ObjectHook (line 1146) | type ObjectHook<T, O = {}> = T | ({ handler: T; order?: 'pre' | 'post' |...
type PluginHooks (line 1148) | type PluginHooks = {
type OutputPlugin (line 1155) | interface OutputPlugin
type Plugin (line 1163) | interface Plugin<A = any> extends OutputPlugin, Partial<PluginHooks> {
type TreeshakingPreset (line 1168) | type TreeshakingPreset = 'smallest' | 'safest' | 'recommended';
type NormalizedTreeshakingOptions (line 1170) | interface NormalizedTreeshakingOptions {
type TreeshakingOptions (line 1180) | interface TreeshakingOptions extends Partial<Omit<NormalizedTreeshakingO...
type ManualChunkMeta (line 1185) | interface ManualChunkMeta {
type GetManualChunk (line 1189) | type GetManualChunk = (id: string, meta: ManualChunkMeta) => string | Nu...
type ExternalOption (line 1191) | type ExternalOption =
type GlobalsOption (line 1197) | type GlobalsOption = { [name: string]: string } | ((name: string) => str...
type InputOption (line 1199) | type InputOption = string | string[] | { [entryAlias: string]: string };
type ManualChunksOption (line 1201) | type ManualChunksOption = { [chunkAlias: string]: string[] } | GetManual...
type LogHandlerWithDefault (line 1203) | type LogHandlerWithDefault = (level: LogLevel, log: RollupLog, defaultHa...
type LogOrStringHandler (line 1205) | type LogOrStringHandler = (level: LogLevel | 'error', log: RollupLog | s...
type LogHandler (line 1207) | type LogHandler = (level: LogLevel, log: RollupLog) => void;
type ModuleSideEffectsOption (line 1209) | type ModuleSideEffectsOption = boolean | 'no-external' | string[] | HasM...
type PreserveEntrySignaturesOption (line 1211) | type PreserveEntrySignaturesOption = false | 'strict' | 'allow-extension...
type SourcemapPathTransformOption (line 1213) | type SourcemapPathTransformOption = (relativeSourcePath: string, sourcem...
type SourcemapIgnoreListOption (line 1215) | type SourcemapIgnoreListOption = (relativeSourcePath: string, sourcemapP...
type InputPluginOption (line 1217) | type InputPluginOption = MaybePromise<Plugin | NullValue | false | Input...
type InputOptions (line 1219) | interface InputOptions {
type InputOptionsWithPlugins (line 1242) | interface InputOptionsWithPlugins extends InputOptions {
type NormalizedInputOptions (line 1246) | interface NormalizedInputOptions {
type InternalModuleFormat (line 1267) | type InternalModuleFormat = 'amd' | 'cjs' | 'es' | 'iife' | 'system' | '...
type ModuleFormat (line 1269) | type ModuleFormat = InternalModuleFormat | 'commonjs' | 'esm' | 'module'...
type GeneratedCodePreset (line 1271) | type GeneratedCodePreset = 'es5' | 'es2015';
type NormalizedGeneratedCodeOptions (line 1273) | interface NormalizedGeneratedCodeOptions {
type GeneratedCodeOptions (line 1281) | interface GeneratedCodeOptions extends Partial<NormalizedGeneratedCodeOp...
type OptionsPaths (line 1285) | type OptionsPaths = Record<string, string> | ((id: string) => string);
type InteropType (line 1287) | type InteropType = 'compat' | 'auto' | 'esModule' | 'default' | 'default...
type GetInterop (line 1289) | type GetInterop = (id: string | null) => InteropType;
type AmdOptions (line 1291) | type AmdOptions = (
type NormalizedAmdOptions (line 1310) | type NormalizedAmdOptions = (
type AddonFunction (line 1324) | type AddonFunction = (chunk: RenderedChunk) => string | Promise<string>;
type OutputPluginOption (line 1326) | type OutputPluginOption = MaybePromise<OutputPlugin | NullValue | false ...
type HashCharacters (line 1328) | type HashCharacters = 'base64' | 'base36' | 'hex';
type OutputOptions (line 1330) | interface OutputOptions {
type NormalizedOutputOptions (line 1383) | interface NormalizedOutputOptions {
type WarningHandlerWithDefault (line 1434) | type WarningHandlerWithDefault = (warning: RollupLog, defaultHandler: Lo...
type SerializedTimings (line 1436) | interface SerializedTimings {
type PreRenderedAsset (line 1440) | interface PreRenderedAsset {
type OutputAsset (line 1446) | interface OutputAsset extends PreRenderedAsset {
type RenderedModule (line 1451) | interface RenderedModule {
type PreRenderedChunk (line 1459) | interface PreRenderedChunk {
type RenderedChunk (line 1470) | interface RenderedChunk extends PreRenderedChunk {
type OutputChunk (line 1484) | interface OutputChunk extends RenderedChunk {
type SerializablePluginCache (line 1491) | interface SerializablePluginCache {
type RollupCache (line 1495) | interface RollupCache {
type RollupOutput (line 1500) | interface RollupOutput {
type RollupBuild (line 1504) | interface RollupBuild {
type RollupOptions (line 1514) | interface RollupOptions extends InputOptions {
type MergedRollupOptions (line 1519) | interface MergedRollupOptions extends InputOptionsWithPlugins {
type ChokidarOptions (line 1525) | interface ChokidarOptions {
type RollupWatchHooks (line 1548) | type RollupWatchHooks = 'onError' | 'onStart' | 'onBundleStart' | 'onBun...
type WatcherOptions (line 1550) | interface WatcherOptions {
type RollupWatchOptions (line 1559) | interface RollupWatchOptions extends InputOptions {
type AwaitedEventListener (line 1564) | type AwaitedEventListener<T extends { [event: string]: (...parameters: a...
type AwaitingEventEmitter (line 1568) | interface AwaitingEventEmitter<T extends { [event: string]: (...paramete...
type RollupWatcherEvent (line 1596) | type RollupWatcherEvent =
type RollupWatcher (line 1609) | type RollupWatcher = AwaitingEventEmitter<{
type AstNode (line 1618) | interface AstNode {
type ProgramNode (line 1624) | type ProgramNode = Program & AstNode;
type RollupOptionsFunction (line 1630) | type RollupOptionsFunction = (
FILE: packages/ranuts/src/arithmetic/index.ts
type ListNode (line 13) | interface ListNode {
type HeadNode (line 18) | interface HeadNode {
type TreeNode (line 24) | interface TreeNode {
class MinHeap (line 313) | class MinHeap {
method constructor (line 316) | constructor(arr: Array<number>) {
constant PENDING (line 427) | const PENDING = 'pending';
constant RESOLVED (line 428) | const RESOLVED = 'resolved';
constant REJECTED (line 429) | const REJECTED = 'rejected';
class CustomPromise (line 431) | class CustomPromise {
method constructor (line 437) | constructor(cb: unknown) {
FILE: packages/ranuts/src/ml/ocr.ts
type Options (line 10) | interface Options {
type OcrReturn (line 16) | interface OcrReturn extends BaseReturn {
FILE: packages/ranuts/src/node/body.ts
type ServerBody (line 8) | interface ServerBody {
FILE: packages/ranuts/src/node/color.ts
constant OPEN (line 4) | const OPEN = 0;
constant CLOSE (line 5) | const CLOSE = 1;
type Formatter (line 7) | type Formatter = (open: string, close: string, replace?: string) => (inp...
FILE: packages/ranuts/src/node/command.ts
type PromptOption (line 15) | interface PromptOption {
FILE: packages/ranuts/src/node/ctx2req.ts
type ConnectMiddleware (line 4) | type ConnectMiddleware = (req: IncomingMessage, res: ServerResponse, nex...
constant PARAM_LENGTH (line 8) | const PARAM_LENGTH = 3;
function noCallbackHandler (line 10) | function noCallbackHandler(ctx: Context, connectMiddleware: ConnectMiddl...
function withCallbackHandler (line 15) | function withCallbackHandler(ctx: Context, connectMiddleware: ConnectMid...
function connect (line 23) | function connect(connectMiddleware: ConnectMiddleware): MiddlewareFuncti...
FILE: packages/ranuts/src/node/fs.ts
type FilePromiseResult (line 4) | type FilePromiseResult = Promise<Ranuts.Identification> & {
type Error (line 8) | type Error = NodeJS.ErrnoException | null;
FILE: packages/ranuts/src/node/get.ts
type Request (line 3) | interface Request {
type Response (line 7) | interface Response {
FILE: packages/ranuts/src/node/paresUrl.ts
type ParseUrl (line 3) | interface ParseUrl {
type Req (line 11) | interface Req extends IncomingMessage {
FILE: packages/ranuts/src/node/readDir.ts
type Options (line 3) | interface Options {
FILE: packages/ranuts/src/node/router.ts
type Handler (line 25) | type Handler = (ctx: Context, next: Next) => void;
class Router (line 27) | class Router {
method constructor (line 32) | constructor() {
method get (line 37) | get(url: string, handler: Handler): void {
method post (line 40) | post(url: string, handler: Handler): void {
method put (line 43) | put(url: string, handler: Handler): void {
method patch (line 46) | patch(url: string, handler: Handler): void {
method del (line 49) | del(url: string, handler: Handler): void {
method head (line 52) | head(url: string, handler: Handler): void {
method options (line 55) | options(url: string, handler: Handler): void {
method addHandlerToMap (line 58) | private addHandlerToMap(method: string) {
method routes (line 70) | routes(): MiddlewareFunction {
method allowedMethods (line 79) | allowedMethods(): MiddlewareFunction {
FILE: packages/ranuts/src/node/send.ts
type Option (line 6) | interface Option {
FILE: packages/ranuts/src/node/server.ts
type Next (line 6) | type Next = () => Promise<never> | Promise<void>;
type MiddlewareFunction (line 8) | type MiddlewareFunction = (ctx: Context, next: Next) => void | Promise<v...
type Context (line 10) | interface Context {
function ipv4 (line 17) | function ipv4(): string | undefined {
class Server (line 32) | class Server {
method constructor (line 35) | constructor() {
method use (line 48) | use(handle: MiddlewareFunction): void {
method listen (line 54) | listen(...args: any): http.Server {
function onerror (line 65) | function onerror(err: Error) {
function compose (line 69) | function compose(middleware: Array<MiddlewareFunction>) {
FILE: packages/ranuts/src/node/stream.ts
type ReadOption (line 4) | interface ReadOption {
type WriteOption (line 12) | interface WriteOption {
FILE: packages/ranuts/src/node/traverse.ts
type Caller (line 9) | type Caller = (relPath: string, absPath: string, stats: Stats) => any;
function traverse (line 16) | async function traverse(dir: string, callback: Caller, pre = ''): Promis...
function traverseSync (line 35) | function traverseSync(dir: string, callback: Caller, pre = ''): void {
FILE: packages/ranuts/src/node/websocket.ts
type FrameMeta (line 6) | interface FrameMeta {
class Client (line 22) | class Client extends EventEmitter {
method constructor (line 25) | constructor(socket: internal.Duplex) {
method createFrame (line 30) | createFrame(content: string, options?: { opcode: number }): Buffer {
method send (line 54) | send(data: string, options?: { opcode: number }): void {
method ping (line 57) | ping(): void {
method pong (line 60) | pong(): void {
method close (line 63) | close(): void {
class WebSocket (line 70) | class WebSocket extends EventEmitter {
method constructor (line 73) | constructor({ port = 30104 }: { port: number }) {
method broadcast (line 84) | broadcast(data: string): void {
method create (line 92) | create(req: http.IncomingMessage, socket: internal.Duplex): void {
method addListenCloseClient (line 158) | addListenCloseClient(client: Client): void {
method parseFrameMeta (line 170) | parseFrameMeta(source: Buffer): FrameMeta {
method iMask (line 196) | iMask(data: Buffer, key: Buffer | null): Buffer {
FILE: packages/ranuts/src/node/writeFile.ts
type Error (line 3) | type Error = NodeJS.ErrnoException | null;
FILE: packages/ranuts/src/node/ws.ts
function createFrame (line 13) | function createFrame(content: string, options: { opcode: any }) {
function parseFrameMeta (line 48) | function parseFrameMeta(source: Buffer) {
function iMask (line 83) | function iMask(data: Uint8Array, key: Buffer | null) {
function Event (line 95) | function Event(this: any) {
type DateList (line 110) | interface DateList {
function WSS (line 119) | function WSS(this: any, server: http.Server): void {
FILE: packages/ranuts/src/optimize/index.ts
function customNew (line 37) | function customNew(...args: unknown[]): Record<string, unknown> {
function debounce (line 54) | function debounce<T extends (...args: any[]) => any>(
function throttle (line 76) | function throttle(fn: Function, wait: number = 3000): Function {
FILE: packages/ranuts/src/ran/index.ts
type InventedElementProps (line 12) | type InventedElementProps = any;
type FiberProps (line 14) | type FiberProps = any;
type AuthenticElement (line 16) | type AuthenticElement = any;
type InventedElement (line 18) | interface InventedElement {
type Fiber (line 23) | interface Fiber {
function createTextInventedElement (line 70) | function createTextInventedElement(text: string): InventedElement {
function createElement (line 86) | function createElement(type: string, config: InventedElementProps, child...
function fiberToAuthenticElement (line 103) | function fiberToAuthenticElement(fiber: Fiber): AuthenticElement {
function reconcile (line 124) | function reconcile(fiber: Fiber) {
function reconcileFiberNode (line 152) | function reconcileFiberNode(fiber: Fiber) {
function reconcileChildren (line 164) | function reconcileChildren(fiber: Fiber) {
function schedule (line 258) | function schedule(deadline: IdleDeadline) {
function commitFiber (line 276) | function commitFiber() {
function replacementHandler (line 282) | function replacementHandler(fiber: Fiber) {
function deletionHandler (line 288) | function deletionHandler(fiber: Fiber) {
function updateHandler (line 294) | function updateHandler(fiber: Fiber) {
function fiberHandler (line 327) | function fiberHandler(fiber: Fiber) {
function render (line 348) | function render(inventedElement: InventedElement, root: Element): void {
FILE: packages/ranuts/src/ran/min.ts
type Fiber (line 9) | interface Fiber {
class Concurrent (line 88) | class Concurrent {
method constructor (line 91) | constructor(element: Fiber, container: HTMLElement) {
method workLoop (line 101) | workLoop(deadline: IdleDeadline): void {
method performUnitOfWork (line 118) | performUnitOfWork(fiber: Fiber): Fiber | undefined {
method startWork (line 159) | startWork(): void {
method commitRoot (line 162) | commitRoot(): void {
method commitWork (line 166) | commitWork(fiber: Fiber | undefined): void {
FILE: packages/ranuts/src/sort/heap.ts
class Heap (line 1) | class Heap {
method constructor (line 4) | constructor(arr: Array<number> = []) {
FILE: packages/ranuts/src/utils/audioRecorder.ts
type Section (line 17) | interface Section {
class WebmBase (line 249) | class WebmBase<T> {
method constructor (line 253) | constructor(
method updateBySource (line 258) | updateBySource() {
method setSource (line 262) | setSource(source: Uint8Array) {
method updateByData (line 267) | updateByData() {
method setData (line 271) | setData(data: T) {
type ContainerData (line 277) | interface ContainerData {
function padHex (line 283) | function padHex(hex: string) {
class WebmUint (line 287) | class WebmUint extends WebmBase<string> {
method constructor (line 288) | constructor(name: string, type: string) {
method updateBySource (line 292) | updateBySource() {
method updateByData (line 301) | updateByData() {
method getValue (line 310) | getValue() {
method setValue (line 314) | setValue(value: number) {
class WebmFloat (line 319) | class WebmFloat extends WebmBase<number> {
method constructor (line 320) | constructor(name: string, type: string) {
method getFloatArrayType (line 324) | getFloatArrayType() {
method updateBySource (line 327) | updateBySource() {
method updateByData (line 333) | updateByData() {
method getValue (line 339) | getValue() {
method setValue (line 342) | setValue(value: number) {
class WebmContainer (line 347) | class WebmContainer extends WebmBase<ContainerData[]> {
method constructor (line 351) | constructor(name: string, type: string) {
method readByte (line 355) | readByte() {
method readUint (line 358) | readUint() {
method updateBySource (line 369) | updateBySource() {
method writeUint (line 400) | writeUint(x: number, draft = false) {
method writeSections (line 419) | writeSections(draft = false) {
method updateByData (line 435) | updateByData() {
method getSectionById (line 443) | getSectionById(id: number) {
class WebmFile (line 455) | class WebmFile extends WebmContainer {
method constructor (line 456) | constructor(source: Uint8Array) {
method fixDuration (line 461) | fixDuration(duration: number) {
method toBlob (line 503) | toBlob(type = 'video/webm') {
function getMimeType (line 536) | function getMimeType() {
class AudioRecorder (line 549) | class AudioRecorder {
method constructor (line 554) | constructor() {
method init (line 569) | private init(stream: MediaStream) {
method start (line 590) | start(): MediaRecorder | undefined {
method pause (line 596) | pause(): MediaRecorder | undefined {
method stop (line 602) | stop(): Blob | undefined {
FILE: packages/ranuts/src/utils/behavior.ts
function getHardwareInfo (line 49) | function getHardwareInfo(gl: WebGL2RenderingContext) {
type AudioCompressor (line 85) | enum AudioCompressor {
FILE: packages/ranuts/src/utils/bom.ts
type RequestUrlToArraybufferOption (line 41) | interface RequestUrlToArraybufferOption {
type requestUrlToArraybufferReturn (line 50) | interface requestUrlToArraybufferReturn extends BaseReturn {
type BaseReturn (line 54) | interface BaseReturn {
type Context (line 100) | interface Context {
function appendUrl (line 253) | function appendUrl(url: string, params: Record<string, string> = {}): st...
function getCookieByName (line 289) | function getCookieByName(name: string): string {
type ClientRatio (line 296) | interface ClientRatio {
constant ENCODE_CHARS_REGEXP (line 330) | const ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F...
constant UNMATCHED_SURROGATE_PAIR_REGEXP (line 337) | const UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uD...
constant UNMATCHED_SURROGATE_PAIR_REPLACE (line 344) | const UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2';
function encodeUrl (line 364) | function encodeUrl(url: string): string {
type Options (line 370) | interface Options {
type ReturnType (line 376) | interface ReturnType {
type MessageHandler (line 469) | interface MessageHandler<T = unknown, R = unknown> {
type MessageData (line 473) | interface MessageData<T = unknown> {
type PendingRequest (line 481) | interface PendingRequest<R = unknown> {
constant DEFAULT_TIMEOUT (line 486) | const DEFAULT_TIMEOUT = 120000;
class PostMessageBridge (line 494) | class PostMessageBridge {
method constructor (line 500) | constructor(targetWindow: Window = window, targetOrigin = '*') {
type BridgeManagerOptions (line 625) | interface BridgeManagerOptions {
class BridgeManager (line 631) | class BridgeManager {
method constructor (line 637) | private constructor() {}
method getInstance (line 639) | static getInstance(): BridgeManager {
type BroadcastPayload (line 709) | interface BroadcastPayload {
type CallToPayload (line 714) | interface CallToPayload<T = unknown> {
FILE: packages/ranuts/src/utils/color.ts
constant FMT (line 1) | const FMT: Record<string, Array<string>> = {
type ColorVal (line 31) | type ColorVal = (string | number)[];
class Rgb (line 33) | class Rgb {
method constructor (line 37) | constructor(col: Array<string | number>) {
method toString (line 43) | toString(): string {
class Rgba (line 48) | class Rgba extends Rgb {
method constructor (line 50) | constructor(col: Array<string | number>) {
method toString (line 55) | toString(): string {
class Hsl (line 60) | class Hsl {
method constructor (line 64) | constructor(col: Array<string | number>) {
method toString (line 70) | toString(): string {
class Hsla (line 75) | class Hsla extends Hsl {
method constructor (line 77) | constructor(col: Array<string | number>) {
method toString (line 82) | toString(): string {
class Color (line 87) | class Color {
method constructor (line 100) | constructor(
method setHue (line 136) | setHue(newHue: string | number): void {
method setSat (line 143) | setSat(newSat: string | number): void {
method setLum (line 150) | setLum(newLum: number): void {
method setAlpha (line 157) | setAlpha(newAlpha: string | number): void {
method updateFromHsl (line 163) | updateFromHsl(): void {
class ColorScheme (line 400) | class ColorScheme {
method constructor (line 402) | constructor(colorVal: (string | number)[], angleArray: number[]) {
method createFromColors (line 412) | createFromColors(colorVal: (string | number)[]): Color[] {
method createFromAngles (line 421) | createFromAngles(colorVal: string | number | (string | number)[], angl...
method Compl (line 432) | static Compl(colorVal: ColorVal): ColorScheme {
method Triad (line 436) | static Triad(colorVal: ColorVal): ColorScheme {
method Tetrad (line 440) | static Tetrad(colorVal: ColorVal): ColorScheme {
method Analog (line 444) | static Analog(colorVal: ColorVal): ColorScheme {
method Split (line 448) | static Split(colorVal: ColorVal): ColorScheme {
method Accent (line 452) | static Accent(colorVal: ColorVal): ColorScheme {
FILE: packages/ranuts/src/utils/compose.ts
type Next (line 1) | type Next = () => Promise<never> | Promise<void>;
type Middleware (line 3) | type Middleware<T> = (context: T, next: Next) => any;
type ComposedMiddleware (line 5) | type ComposedMiddleware<T> = (context: T, next?: Next) => Promise<void>;
function compose (line 11) | function compose<T>(middleware: Array<Middleware<T>>): ComposedMiddlewar...
FILE: packages/ranuts/src/utils/device.ts
type DEVICE (line 6) | enum DEVICE {
type CurrentDevice (line 12) | type CurrentDevice = 'ipad' | 'android' | 'iphone' | 'pc';
FILE: packages/ranuts/src/utils/dom.ts
function escapeHtml (line 41) | function escapeHtml(string?: string | number | null): string {
function setFontSize (line 100) | function setFontSize() {
constant SVG_NS (line 167) | const SVG_NS = 'http://www.w3.org/2000/svg';
constant SVG_TAG_NAMES (line 168) | const SVG_TAG_NAMES = [
class Chain (line 201) | class Chain {
method constructor (line 204) | constructor(tagName: string, options?: ElementCreationOptions) {
FILE: packages/ranuts/src/utils/img.ts
type convertImageToBase64Return (line 28) | interface convertImageToBase64Return extends BaseReturn {
FILE: packages/ranuts/src/utils/memoize.ts
type Func (line 1) | type Func = () => unknown;
FILE: packages/ranuts/src/utils/mimeType.ts
function getMime (line 828) | function getMime(ext: string): string | undefined {
FILE: packages/ranuts/src/utils/monitor.ts
type Payload (line 9) | interface Payload {
class Monitor (line 13) | class Monitor {
method constructor (line 14) | constructor() {
method reportPerformance (line 21) | reportPerformance(): void {
method log (line 36) | log(payload: Record<string, unknown>): void {
method reportClick (line 43) | reportClick(): void {
method reportXhr (line 59) | reportXhr(): void {
method reportFetch (line 82) | reportFetch(): void {
method reportError (line 105) | reportError(): void {
method reportConsole (line 118) | reportConsole(): void {
method initialize (line 135) | initialize(): void {
FILE: packages/ranuts/src/utils/network.ts
function createMessageToStatusCodeMap (line 106) | function createMessageToStatusCodeMap(codes: Map<number, string>) {
function createStatusCodeList (line 119) | function createStatusCodeList(codes: Map<number, string>) {
function getStatusCode (line 132) | function getStatusCode(message: string) {
function getStatusMessage (line 147) | function getStatusMessage(code: number) {
function getStatus (line 169) | function getStatus(code?: number | string): number | string | undefined {
FILE: packages/ranuts/src/utils/noop.ts
type Noop (line 3) | type Noop = () => void;
FILE: packages/ranuts/src/utils/number.ts
type ComputeNumberResult (line 2) | interface ComputeNumberResult {
class Mathjs (line 41) | class Mathjs {
function mathjs (line 85) | function mathjs(a: number, type: string, b: number): ComputeNumberResult {
FILE: packages/ranuts/src/utils/obj.ts
function querystring (line 7) | function querystring(data = {}): string {
type Obj (line 160) | type Obj = Record<string, any>;
function replaceOld (line 185) | function replaceOld(
function sameValueZero (line 257) | function sameValueZero(x: any, y: any): boolean {
function isObjectLike (line 275) | function isObjectLike(value: any): boolean {
function getTag (line 282) | function getTag(value: any): string {
function isArrayLike (line 289) | function isArrayLike(value: any): boolean {
function isEqual (line 305) | function isEqual(value: any, other: any, seen = new Map()): boolean {
FILE: packages/ranuts/src/utils/performance.ts
type BasicType (line 20) | interface BasicType {
function getPerformance (line 40) | function getPerformance(): BasicType | undefined {
FILE: packages/ranuts/src/utils/queue.ts
type QuestQueueOptions (line 2) | interface QuestQueueOptions {
type Fun (line 7) | type Fun = Function | Func;
class QuestQueue (line 8) | class QuestQueue {
method constructor (line 14) | constructor({ simultaneous, total }: QuestQueueOptions) {
FILE: packages/ranuts/src/utils/report.ts
type BeaconPayload (line 5) | interface BeaconPayload {
function createData (line 46) | function createData(params: Record<string, unknown> = {}): Record<string...
FILE: packages/ranuts/src/utils/request.ts
type Hooks (line 4) | type Hooks = (...args: unknown[]) => void;
type Options (line 6) | interface Options {
FILE: packages/ranuts/src/utils/str.ts
function randomString (line 61) | function randomString(len: number = 8): string {
function changeHumpToLowerCase (line 71) | function changeHumpToLowerCase(str: string): string {
type ClearStrOption (line 84) | interface ClearStrOption {
function getMatchingSentences (line 105) | function getMatchingSentences(text: string, searchValue: string): string...
type TransformText (line 193) | interface TransformText {
function rotateLeft (line 224) | function rotateLeft(lValue: number, iShiftBits: number): number {
function addUnsigned (line 228) | function addUnsigned(lX: number, lY: number): number {
function F (line 241) | function F(x: number, y: number, z: number): number {
function G (line 245) | function G(x: number, y: number, z: number): number {
function H (line 249) | function H(x: number, y: number, z: number): number {
function I (line 253) | function I(x: number, y: number, z: number): number {
function FF (line 257) | function FF(a: number, b: number, c: number, d: number, x: number, s: nu...
function GG (line 262) | function GG(a: number, b: number, c: number, d: number, x: number, s: nu...
function HH (line 267) | function HH(a: number, b: number, c: number, d: number, x: number, s: nu...
function II (line 272) | function II(a: number, b: number, c: number, d: number, x: number, s: nu...
function convertToWordArray (line 277) | function convertToWordArray(str: string): number[] {
function wordToHex (line 300) | function wordToHex(lValue: number): string {
function utf8Encode (line 313) | function utf8Encode(str: string): string {
type FileMetadata (line 431) | type FileMetadata = {
type BlobMetadata (line 440) | type BlobMetadata = {
type FileChunk (line 447) | type FileChunk = {
class MessageCodecError (line 458) | class MessageCodecError extends Error {
method constructor (line 459) | constructor(
method encode (line 481) | encode(data: any): string {
method decode (line 498) | decode<T = any>(encodedStr: string): T | null {
method encodeFile (line 520) | async encodeFile(file: File): Promise<string> {
method decodeFile (line 545) | decodeFile(encoded: string): File {
method encodeBlob (line 578) | async encodeBlob(blob: Blob): Promise<string> {
method decodeBlob (line 601) | decodeBlob(encoded: string): Blob {
method encodeDate (line 630) | encodeDate(date: Date): string {
method decodeDate (line 647) | decodeDate(encodedStr: string): Date {
method encodeRegExp (line 665) | encodeRegExp(regexp: RegExp): string {
method decodeRegExp (line 683) | decodeRegExp(encodedStr: string): RegExp {
method encodeMap (line 701) | encodeMap<K, V>(map: Map<K, V>): string {
method decodeMap (line 718) | decodeMap<K, V>(encodedStr: string): Map<K, V> {
method encodeSet (line 736) | encodeSet<T>(set: Set<T>): string {
method decodeSet (line 753) | decodeSet<T>(encodedStr: string): Set<T> {
method encodeError (line 771) | encodeError(error: Error): string {
method decodeError (line 790) | decodeError(encodedStr: string): Error {
method encodeArrayBuffer (line 811) | encodeArrayBuffer(buffer: ArrayBuffer): string {
method decodeArrayBuffer (line 828) | decodeArrayBuffer(encodedStr: string): ArrayBuffer {
method encodeTypedArray (line 846) | encodeTypedArray(typedArray: ArrayBufferView): string {
method decodeTypedArray (line 864) | decodeTypedArray(encodedStr: string): ArrayBufferView {
method encodeFileChunked (line 885) | async encodeFileChunked(
method decodeFileChunked (line 934) | async decodeFileChunked(chunks: FileChunk[]): Promise<File> {
FILE: packages/ranuts/src/utils/subscribe.ts
type Callback (line 1) | type Callback = Function;
type EventName (line 3) | type EventName = string | symbol;
type EventItem (line 5) | type EventItem = {
constant NEW_LISTENER (line 11) | const NEW_LISTENER = 'NEW_LISTENER';
class SyncHook (line 13) | class SyncHook {
FILE: packages/ranuts/src/utils/throttle.ts
type ThrottleFunc (line 1) | type ThrottleFunc<T extends (...args: any[]) => void> = (...args: Parame...
function throttle (line 9) | function throttle<T extends (...args: any[]) => any>(func: T, delay: num...
FILE: packages/ranuts/src/utils/time.ts
function formatDuration (line 1) | function formatDuration(time: number): string | number {
function timestampToTime (line 10) | function timestampToTime(timestamp?: number | string): Date & { format?:...
FILE: packages/ranuts/src/utils/totp/sha/common.ts
constant TWO_PWR_32 (line 13) | const TWO_PWR_32 = 4294967296;
function packedLEConcat (line 43) | function packedLEConcat(a: packedValue, b: packedValue): packedValue {
function getOutputOpts (line 80) | function getOutputOpts(options?: {
function parseInputOption (line 127) | function parseInputOption(
method constructor (line 201) | protected constructor(variant: any, inputFormat: any, options?: any) {
method update (line 230) | update(srcString: string | ArrayBuffer | Uint8Array): this {
method getHash (line 267) | getHash(format: any, options?: any): any {
method setHMACKey (line 322) | setHMACKey(key: any, inputFormat: any, options?: any): void {
method _setHMACKey (line 342) | protected _setHMACKey(key: packedValue): void {
method getHMAC (line 393) | getHMAC(format: any, options?: any): any {
method _getHMAC (line 403) | protected _getHMAC(): number[] {
FILE: packages/ranuts/src/utils/totp/sha/converters.ts
function str2packed (line 24) | function str2packed(
function hex2packed (line 115) | function hex2packed(
function bytes2packed (line 158) | function bytes2packed(
function b642packed (line 194) | function b642packed(
function uint8array2packed (line 257) | function uint8array2packed(
function arraybuffer2packed (line 291) | function arraybuffer2packed(
function getStrConverter (line 308) | function getStrConverter(
function packed2hex (line 415) | function packed2hex(
function packed2b64 (line 447) | function packed2b64(
function packed2bytes (line 489) | function packed2bytes(packed: number[], outputLength: number, bigEndianM...
function packed2arraybuffer (line 513) | function packed2arraybuffer(packed: number[], outputLength: number, bigE...
function packed2uint8array (line 535) | function packed2uint8array(packed: number[], outputLength: number, bigEn...
function getOutputConverter (line 577) | function getOutputConverter(format: any, outputBinLen: any, bigEndianMod...
FILE: packages/ranuts/src/utils/totp/sha/custom_types.ts
type EncodingType (line 2) | type EncodingType = 'UTF8' | 'UTF16BE' | 'UTF16LE';
type FormatNoTextType (line 3) | type FormatNoTextType = 'HEX' | 'B64' | 'BYTES' | 'ARRAYBUFFER' | 'UINT8...
type FormatType (line 4) | type FormatType = 'TEXT' | FormatNoTextType;
type GenericInputType (line 6) | type GenericInputType =
type FixedLengthOptionsNoEncodingType (line 25) | type FixedLengthOptionsNoEncodingType =
type FixedLengthOptionsEncodingType (line 33) | type FixedLengthOptionsEncodingType =
type packedValue (line 43) | interface packedValue {
type SHAKEOptionsNoEncodingType (line 48) | interface SHAKEOptionsNoEncodingType {
type SHAKEOptionsEncodingType (line 52) | interface SHAKEOptionsEncodingType extends SHAKEOptionsNoEncodingType {
type CSHAKEOptionsNoEncodingType (line 56) | interface CSHAKEOptionsNoEncodingType {
type CSHAKEOptionsEncodingType (line 61) | interface CSHAKEOptionsEncodingType extends CSHAKEOptionsNoEncodingType {
type KMACOptionsNoEncodingType (line 65) | interface KMACOptionsNoEncodingType {
type KMACOptionsEncodingType (line 70) | interface KMACOptionsEncodingType extends KMACOptionsNoEncodingType {
type ResolvedCSHAKEOptionsNoEncodingType (line 74) | interface ResolvedCSHAKEOptionsNoEncodingType {
type ResolvedKMACOptionsNoEncodingType (line 79) | interface ResolvedKMACOptionsNoEncodingType extends ResolvedCSHAKEOption...
FILE: packages/ranuts/src/utils/totp/sha/primitives_32.ts
function rotl_32 (line 17) | function rotl_32(x: number, n: number): number {
function rotr_32 (line 28) | function rotr_32(x: number, n: number): number {
function shr_32 (line 39) | function shr_32(x: number, n: number): number {
function parity_32 (line 51) | function parity_32(x: number, y: number, z: number): number {
function ch_32 (line 63) | function ch_32(x: number, y: number, z: number): number {
function maj_32 (line 75) | function maj_32(x: number, y: number, z: number): number {
function sigma0_32 (line 85) | function sigma0_32(x: number): number {
function safeAdd_32_2 (line 98) | function safeAdd_32_2(a: number, b: number): number {
function safeAdd_32_4 (line 116) | function safeAdd_32_4(a: number, b: number, c: number, d: number): number {
function safeAdd_32_5 (line 135) | function safeAdd_32_5(a: number, b: number, c: number, d: number, e: num...
function gamma1_32 (line 148) | function gamma1_32(x: number): number {
function gamma0_32 (line 158) | function gamma0_32(x: number): number {
function sigma1_32 (line 168) | function sigma1_32(x: number): number {
FILE: packages/ranuts/src/utils/totp/sha/primitives_64.ts
class Int_64 (line 13) | class Int_64 {
method constructor (line 20) | constructor(msint_32: number, lsint_32: number) {
function rotl_64 (line 35) | function rotl_64(x: Int_64, n: number): Int_64 {
function rotr_64 (line 57) | function rotr_64(x: Int_64, n: number): Int_64 {
function shr_64 (line 77) | function shr_64(x: Int_64, n: number): Int_64 {
function ch_64 (line 89) | function ch_64(x: Int_64, y: Int_64, z: Int_64): Int_64 {
function maj_64 (line 104) | function maj_64(x: Int_64, y: Int_64, z: Int_64): Int_64 {
function sigma0_64 (line 117) | function sigma0_64(x: Int_64): Int_64 {
function safeAdd_64_2 (line 135) | function safeAdd_64_2(x: Int_64, y: Int_64): Int_64 {
function safeAdd_64_4 (line 158) | function safeAdd_64_4(a: Int_64, b: Int_64, c: Int_64, d: Int_64): Int_64 {
function safeAdd_64_5 (line 183) | function safeAdd_64_5(a: Int_64, b: Int_64, c: Int_64, d: Int_64, e: Int...
function xor_64_2 (line 227) | function xor_64_2(a: Int_64, b: Int_64): Int_64 {
function xor_64_5 (line 241) | function xor_64_5(a: Int_64, b: Int_64, c: Int_64, d: Int_64, e: Int_64)...
function gamma1_64 (line 254) | function gamma1_64(x: Int_64): Int_64 {
function gamma0_64 (line 271) | function gamma0_64(x: Int_64): Int_64 {
function sigma1_64 (line 288) | function sigma1_64(x: Int_64): Int_64 {
FILE: packages/ranuts/src/utils/totp/sha/sha.ts
type FixedLengthVariantType (line 19) | type FixedLengthVariantType =
class jsSHA (line 30) | class jsSHA {
method constructor (line 62) | constructor(variant: any, inputFormat: any, options?: any) {
method update (line 93) | update(input: string | ArrayBuffer | Uint8Array): this {
method getHash (line 115) | getHash(format: any, options?: any): any {
method setHMACKey (line 133) | setHMACKey(key: any, inputFormat: any, options?: any): void {
method getHMAC (line 152) | getHMAC(format: any, options?: any): any {
FILE: packages/ranuts/src/utils/totp/sha/sha1.ts
function getNewState (line 17) | function getNewState(_variant: 'SHA-1'): number[] {
function roundSHA1 (line 28) | function roundSHA1(block: number[], H: number[]): number[] {
function finalizeSHA1 (line 80) | function finalizeSHA1(remainder: number[], remainderBinLen: number, proc...
class jsSHA (line 114) | class jsSHA extends jsSHABase<number[], 'SHA-1'> {
method constructor (line 132) | constructor(variant: any, inputFormat: any, options?: any) {
FILE: packages/ranuts/src/utils/totp/sha/sha256.ts
type VariantType (line 21) | type VariantType = 'SHA-224' | 'SHA-256';
function getNewState256 (line 29) | function getNewState256(variant: VariantType): number[] {
function roundSHA256 (line 48) | function roundSHA256(block: number[], H: number[]): number[] {
function finalizeSHA256 (line 102) | function finalizeSHA256(
class jsSHA (line 147) | class jsSHA extends jsSHABase<number[], VariantType> {
method constructor (line 165) | constructor(variant: any, inputFormat: any, options?: any) {
FILE: packages/ranuts/src/utils/totp/sha/sha3.ts
type FixedLengthVariantType (line 19) | type FixedLengthVariantType = 'SHA3-224' | 'SHA3-256' | 'SHA3-384' | 'SH...
type VariantType (line 21) | type VariantType = FixedLengthVariantType | 'SHAKE128' | 'SHAKE256' | 'C...
function getNewState (line 64) | function getNewState(_variant: VariantType): Int_64[][] {
function cloneSHA3State (line 81) | function cloneSHA3State(state: Int_64[][]): Int_64[][] {
function roundSHA3 (line 98) | function roundSHA3(block: number[] | null, state: Int_64[][]): Int_64[][] {
function finalizeSHA3 (line 168) | function finalizeSHA3(
function left_encode (line 231) | function left_encode(x: number): packedValue {
function right_encode (line 262) | function right_encode(x: number): packedValue {
function encode_string (line 293) | function encode_string(input: packedValue): packedValue {
function byte_pad (line 304) | function byte_pad(packed: packedValue, outputByteLen: number): number[] {
function resolveCSHAKEOptions (line 324) | function resolveCSHAKEOptions(options: CSHAKEOptionsNoEncodingType): Res...
function resolveKMACOptions (line 338) | function resolveKMACOptions(options: KMACOptionsNoEncodingType): Resolve...
class jsSHA (line 349) | class jsSHA extends jsSHABase<Int_64[][], VariantType> {
method constructor (line 383) | constructor(variant: any, inputFormat: any, options?: any) {
method _initializeCSHAKE (line 523) | protected _initializeCSHAKE(options?: CSHAKEOptionsNoEncodingType, fun...
method _initializeKMAC (line 555) | protected _initializeKMAC(options: KMACOptionsNoEncodingType): void {
method _getKMAC (line 577) | protected _getKMAC(options: { outputLen: number }): number[] {
FILE: packages/ranuts/src/utils/totp/sha/sha512.ts
type VariantType (line 22) | type VariantType = 'SHA-384' | 'SHA-512';
function getNewState512 (line 113) | function getNewState512(variant: VariantType): Int_64[] {
function roundSHA512 (line 147) | function roundSHA512(block: number[], H: Int_64[]): Int_64[] {
function finalizeSHA512 (line 202) | function finalizeSHA512(
class jsSHA (line 278) | class jsSHA extends jsSHABase<Int_64[], VariantType> {
method constructor (line 296) | constructor(variant: any, inputFormat: any, options?: any) {
FILE: packages/ranuts/src/utils/totp/totp.ts
type Options (line 8) | type Options = {
class TOTP (line 24) | class TOTP {
method generate (line 25) | static generate(key: string, options?: Options): { otp: string; expire...
method hex2dec (line 47) | private static hex2dec(hex: string) {
method dec2hex (line 51) | private static dec2hex(dec: number) {
method base32tohex (line 55) | private static base32tohex(base32: string) {
method leftpad (line 75) | private static leftpad(str: string, len: number, pad: string) {
FILE: packages/ranuts/src/utils/visual/application.ts
class Application (line 9) | class Application {
method constructor (line 16) | constructor(options: IApplicationOptions) {
method render (line 26) | public render(): void {
method start (line 30) | public start(): void {
method stop (line 38) | public stop(): void {
FILE: packages/ranuts/src/utils/visual/demo/sankey.ts
class Sankey (line 2) | class Sankey {}
FILE: packages/ranuts/src/utils/visual/enums.ts
type SHAPE_TYPE (line 2) | enum SHAPE_TYPE {
type LINE_CAP (line 10) | enum LINE_CAP {
type LINE_JOIN (line 16) | enum LINE_JOIN {
type RENDERER_TYPE (line 23) | enum RENDERER_TYPE {
constant MAX_VERTEX_COUNT (line 29) | const MAX_VERTEX_COUNT = 65536;
constant BYTES_PER_VERTEX (line 32) | const BYTES_PER_VERTEX = 12;
constant CONTAINER (line 34) | const CONTAINER = 'container';
constant GRAPHICS (line 36) | const GRAPHICS = 'graphics';
constant OBJECT (line 38) | const OBJECT = 'object';
FILE: packages/ranuts/src/utils/visual/event/boundary.ts
class EventBoundary (line 6) | class EventBoundary {
method constructor (line 14) | constructor(stage: Container) {
FILE: packages/ranuts/src/utils/visual/event/event.ts
class EventSystem (line 6) | class EventSystem {
method constructor (line 10) | constructor(canvasEle: HTMLCanvasElement, stage: Container) {
FILE: packages/ranuts/src/utils/visual/event/types.ts
type EventPhase (line 4) | enum EventPhase {
class FederatedMouseEvent (line 11) | class FederatedMouseEvent {
method stopPropagation (line 23) | public stopPropagation(): void {
type FederatedEventMap (line 28) | type FederatedEventMap = {
type Cursor (line 39) | type Cursor =
FILE: packages/ranuts/src/utils/visual/graphics/graphics.ts
class Graphics (line 22) | class Graphics extends Container {
method constructor (line 28) | constructor() {
method lineStyle (line 34) | public lineStyle(options: ILineStyleOptions | number, color: string = ...
FILE: packages/ranuts/src/utils/visual/graphics/graphicsData.ts
class GraphicsData (line 5) | class GraphicsData {
method constructor (line 13) | constructor(shape: Shape, fillStyle: Fill, lineStyle: Line) {
FILE: packages/ranuts/src/utils/visual/graphics/graphicsGeometry.ts
class GraphicsGeometry (line 10) | class GraphicsGeometry {
method drawShape (line 26) | public drawShape(shape: Shape, fillStyle: Fill, lineStyle: Line): void {
method containsPoint (line 34) | public containsPoint(p: Point): boolean {
method buildVerticesAndTriangulate (line 49) | public buildVerticesAndTriangulate(): void {
method clear (line 64) | public clear(): void {
FILE: packages/ranuts/src/utils/visual/math/enums.ts
constant DEG_TO_RAD (line 1) | const DEG_TO_RAD = Math.PI / 180;
constant RAD_TO_DEG (line 2) | const RAD_TO_DEG = 180 / Math.PI;
constant PI_2 (line 3) | const PI_2 = Math.PI * 2;
FILE: packages/ranuts/src/utils/visual/math/matrix.ts
type TransformableObject (line 4) | interface TransformableObject {
class Matrix (line 17) | class Matrix {
method constructor (line 25) | constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
FILE: packages/ranuts/src/utils/visual/math/transform.ts
class Transform (line 6) | class Transform {
method constructor (line 21) | constructor() {
method rotation (line 28) | get rotation(): number {
method rotation (line 32) | set rotation(r: number) {
method updateLocalTransform (line 63) | public updateLocalTransform(): void {
method updateTransform (line 100) | public updateTransform(parentTransform: Transform): void {
FILE: packages/ranuts/src/utils/visual/render/batchRenderer.ts
method constructor (line 47) | constructor(options: IApplicationOptions) {
method addBatch (line 58) | public addBatch(batch: Batch): void {
method startBuild (line 68) | protected startBuild(): void {
method buildEnd (line 75) | protected buildEnd(): void {
method resizeBufferIfNeeded (line 83) | protected resizeBufferIfNeeded(): void {
method packData (line 98) | protected packData(): void {
method updateChildrenTransform (line 132) | protected updateChildrenTransform(rootContainer: Container): void {
method render (line 155) | public render(rootContainer: Container): void {
FILE: packages/ranuts/src/utils/visual/render/canvasRenderer.ts
class CanvasRenderer (line 5) | class CanvasRenderer extends Renderer {
method constructor (line 9) | constructor(options: IApplicationOptions) {
method render (line 18) | public render(container: Container): void {
FILE: packages/ranuts/src/utils/visual/render/render.ts
method constructor (line 12) | constructor(options: IApplicationOptions) {
method resizeView (line 18) | public resizeView(width: number, height: number): void {
method init (line 23) | public async init(): Promise<any> {
FILE: packages/ranuts/src/utils/visual/render/utils/batch/index.ts
class BatchPart (line 82) | class BatchPart {
method constructor (line 88) | constructor(style: Fill) {
method start (line 91) | public start(vertexStart: number, indexStart: number): void {
method end (line 95) | public end(vertexCount: number, indexCount: number): void {
method reset (line 104) | reset(): void {
class GraphicsBatchPool (line 109) | class GraphicsBatchPool extends BatchPool {
method constructor (line 111) | constructor() {
method getOne (line 114) | public getOne(): GraphicsBatch {
class GraphicsBatch (line 122) | class GraphicsBatch extends Batch {
method packVertices (line 138) | packVertices(floatView: Float32Array, intView: Uint32Array): void {
method packIndices (line 163) | packIndices(int32: Uint32Array): void {
method updateVertices (line 173) | updateVertices(floatView: Float32Array): void {
class BatchPools (line 194) | class BatchPools {
method get (line 198) | public get(type: string) {
method reset (line 201) | public reset() {
FILE: packages/ranuts/src/utils/visual/render/utils/float.ts
class CustomFloatArray (line 3) | class CustomFloatArray {
method length (line 13) | get length(): number {
method concat (line 20) | public concat(arr: number[]): void {
method push (line 37) | public push(num: number): void {
method expandCapacity (line 49) | public expandCapacity(): void {
method data (line 60) | get data(): Float32Array {
method clear (line 71) | public clear(): void {
class CustomIntArray (line 77) | class CustomIntArray {
method length (line 87) | get length(): number {
method concat (line 94) | public concat(arr: number[]): void {
method concatUInt16 (line 110) | public concatUInt16(uint16: Uint32Array): void {
method expandCapacity (line 125) | public expandCapacity(): void {
method data (line 136) | get data(): Uint32Array {
method clear (line 148) | public clear(): void {
FILE: packages/ranuts/src/utils/visual/render/utils/webgl/batchPool.ts
type Batch (line 4) | interface Batch {
class BatchPool (line 10) | class BatchPool {
method constructor (line 31) | constructor(renderer: WebGLRenderer) {
method setBuffer (line 47) | private setBuffer(vertexCount: number, vertexIndexCount: number) {
method push (line 81) | public push(batch: Batch): void {
method draw (line 91) | private draw() {
method packData (line 96) | private packData() {
method flush (line 138) | public flush(): void {
FILE: packages/ranuts/src/utils/visual/render/webGPURenderer.ts
class WebGPURenderer (line 7) | class WebGPURenderer extends BatchRenderer {
method constructor (line 40) | constructor(options: IApplicationOptions) {
method init (line 53) | public async init(): Promise<void> {
method draw (line 66) | protected draw(): void {
method initUniformBindGroup (line 100) | private initUniformBindGroup() {
method initGpuBuffer (line 133) | private initGpuBuffer() {
method updateBuffer (line 149) | protected updateBuffer(): void {
method setRootTransform (line 179) | protected setRootTransform(a: number, b: number, c: number, d: number,...
method setProjectionMatrix (line 200) | protected setProjectionMatrix(): void {
method createPipeline (line 230) | private createPipeline() {
method initDevice (line 292) | private async initDevice() {
method initRenderPassDescriptor (line 311) | private initRenderPassDescriptor() {
FILE: packages/ranuts/src/utils/visual/render/webGlRenderer.ts
class WebGLRenderer (line 8) | class WebGLRenderer extends Renderer {
method constructor (line 16) | constructor(options: IApplicationOptions) {
method setProjectionMatrix (line 51) | private setProjectionMatrix() {
method setRootTransform (line 65) | private setRootTransform(a: number, b: number, c: number, d: number, t...
method render (line 73) | public render(rootContainer: Container): void {
FILE: packages/ranuts/src/utils/visual/shape/circle.ts
class Circle (line 5) | class Circle extends Shape {
method constructor (line 10) | constructor(x = 0, y = 0, radius = 0) {
method contains (line 16) | public contains(p: Point): boolean {
FILE: packages/ranuts/src/utils/visual/shape/ellipse.ts
class Ellipse (line 5) | class Ellipse extends Shape {
method constructor (line 11) | constructor(x = 0, y = 0, radiusX = 0, radiusY = 0) {
method contains (line 18) | public contains(p: Point): boolean {
FILE: packages/ranuts/src/utils/visual/shape/polygon.ts
class Polygon (line 6) | class Polygon extends Shape {
method constructor (line 10) | constructor(points: number[] = []) {
method isIntersect (line 15) | private isIntersect(px: number, py: number, p1x: number, p1y: number, ...
method contains (line 47) | public contains(p: Point): boolean {
FILE: packages/ranuts/src/utils/visual/shape/rectangle.ts
class Rectangle (line 6) | class Rectangle extends Shape {
method constructor (line 12) | constructor(x = 0, y = 0, width = 0, height = 0) {
method contains (line 19) | public contains(p: Point): boolean {
FILE: packages/ranuts/src/utils/visual/shape/roundedRectangle.ts
class RoundedRectangle (line 5) | class RoundedRectangle extends Shape {
method constructor (line 12) | constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
method contains (line 21) | public contains(p: Point): boolean {
FILE: packages/ranuts/src/utils/visual/style/fill.ts
class Fill (line 1) | class Fill {
method constructor (line 6) | constructor() {
method clone (line 10) | public clone(): Fill {
method reset (line 18) | public reset(): void {
FILE: packages/ranuts/src/utils/visual/style/line.ts
class Line (line 4) | class Line extends Fill {
method clone (line 10) | public clone(): Line {
method reset (line 22) | public reset(): void {
FILE: packages/ranuts/src/utils/visual/types.ts
type IApplicationOptions (line 3) | interface IApplicationOptions {
type IFillStyleOptions (line 10) | interface IFillStyleOptions {
type ILineStyleOptions (line 16) | interface ILineStyleOptions extends IFillStyleOptions {
FILE: packages/ranuts/src/utils/visual/vertex/container.ts
class Container (line 13) | class Container extends Vertex {
method constructor (line 32) | constructor() {
method renderCanvas (line 72) | protected renderCanvas(render: CanvasRenderer): void {
method renderWebGL (line 114) | protected renderWebGL(renderer: WebGLRenderer): void {
method renderWebGLRecursive (line 122) | public renderWebGLRecursive(renderer: WebGLRenderer): void {
method buildBatches (line 136) | public buildBatches(batchRenderer: BatchRenderer): void {
method updateBatches (line 144) | public updateBatches(floatView: Float32Array): void {
FILE: packages/ranuts/src/utils/visual/vertex/point.ts
class Point (line 2) | class Point {
method constructor (line 5) | constructor(x = 0, y = 0) {
method set (line 10) | public set(x = 0, y = x): void {
class ObservablePoint (line 19) | class ObservablePoint<T = never> {
method constructor (line 23) | constructor(cb: (...args: T[]) => void, x = 0, y = 0) {
method set (line 29) | set(x = 0, y = x): void {
method x (line 35) | get x(): number {
method x (line 39) | set x(value: number) {
method y (line 46) | get y(): number {
method y (line 50) | set y(value: number) {
FILE: packages/ranuts/src/utils/visual/vertex/vertex.ts
method zIndex (line 23) | get zIndex(): number {
method zIndex (line 27) | set zIndex(value: number) {
method position (line 34) | get position(): ObservablePoint {
method localTransform (line 38) | get localTransform(): Matrix {
method worldTransform (line 42) | get worldTransform(): Matrix {
method x (line 46) | get x(): number {
method x (line 50) | set x(value: number) {
method y (line 54) | get y(): number {
method y (line 58) | set y(value: number) {
method scale (line 62) | get scale(): ObservablePoint {
method pivot (line 66) | get pivot(): ObservablePoint {
method skew (line 70) | get skew(): ObservablePoint {
method rotation (line 74) | get rotation(): number {
method rotation (line 78) | set rotation(value: number) {
method angle (line 82) | get angle(): number {
method angle (line 86) | set angle(value: number) {
method updateTransform (line 90) | public updateTransform(): void {
FILE: packages/ranuts/src/vnode/chainDom.ts
class Chain (line 5) | class Chain {
method constructor (line 7) | constructor(tagName: string, options?: ElementCreationOptions) {
FILE: packages/ranuts/src/vnode/h.ts
function addNS (line 6) | function addNS(
function h (line 29) | function h(sel: string, b?: VNodeData | null | VNodeChildren, c?: VNodeC...
FILE: packages/ranuts/src/vnode/hooks.ts
type PreHook (line 3) | type PreHook = () => any;
type InitHook (line 4) | type InitHook = (vNode: VNode) => any;
type CreateHook (line 5) | type CreateHook = (emptyVNode: VNode, vNode: VNode) => any;
type InsertHook (line 6) | type InsertHook = (vNode: VNode) => any;
type PrePatchHook (line 7) | type PrePatchHook = (oldVNode: VNode, vNode: VNode) => any;
type UpdateHook (line 8) | type UpdateHook = (oldVNode: VNode, vNode: VNode) => any;
type PostPatchHook (line 9) | type PostPatchHook = (oldVNode: VNode, vNode: VNode) => any;
type DestroyHook (line 10) | type DestroyHook = (vNode: VNode) => any;
type RemoveHook (line 11) | type RemoveHook = (vNode: VNode, removeCallback: () => void) => any;
type PostHook (line 12) | type PostHook = () => any;
type Hooks (line 14) | interface Hooks {
FILE: packages/ranuts/src/vnode/htmlDomApi.ts
type Fragment (line 1) | interface Fragment extends DocumentFragment {
type DOMAPI (line 7) | interface DOMAPI {
function createElement (line 49) | function createElement(tagName: any, options?: ElementCreationOptions): ...
function createElementNS (line 53) | function createElementNS(namespaceURI: string, qualifiedName: string, op...
function createDocumentFragment (line 57) | function createDocumentFragment(): Fragment {
function createTextNode (line 61) | function createTextNode(text: string): Text {
function createComment (line 65) | function createComment(text: string): Comment {
function insertBefore (line 69) | function insertBefore(parentNode: Node, newNode: Node, referenceNode: No...
function removeChild (line 87) | function removeChild(node: Node, child: Node): void {
function appendChild (line 91) | function appendChild(node: Node, child: Node): void {
function parentNode (line 98) | function parentNode(node: Node): Node | null {
function nextSibling (line 109) | function nextSibling(node: Node): Node | null {
function tagName (line 123) | function tagName(elm: Element): string {
function setTextContent (line 127) | function setTextContent(node: Node, text: string | null): void {
function getTextContent (line 131) | function getTextContent(node: Node): string | null {
function isElement (line 135) | function isElement(node: Node): node is Element {
function isText (line 139) | function isText(node: Node): node is Text {
function isComment (line 143) | function isComment(node: Node): node is Comment {
function isDocumentFragment (line 147) | function isDocumentFragment(node: Node): node is DocumentFragment {
function parseFragment (line 151) | function parseFragment(fragmentNode: DocumentFragment, parentNode?: Node...
FILE: packages/ranuts/src/vnode/init.ts
type NonUndefined (line 13) | type NonUndefined<T> = T extends undefined ? never : T;
type KeyToIndexMap (line 15) | type KeyToIndexMap = Record<string, number>;
type Cbs (line 17) | interface Cbs {
function sameVnode (line 25) | function sameVnode(vnode1: VNode, vnode2: VNode): boolean {
function isVnode (line 30) | function isVnode(vnode: any): vnode is VNode {
function createKeyToOldIdx (line 35) | function createKeyToOldIdx(children: VNode[], beginIdx: number, endIdx: ...
function init (line 49) | function init(): (oldVnode: VNode | Element, vnode: VNode) => VNode {
FILE: packages/ranuts/src/vnode/is.ts
function primitive (line 10) | function primitive(s: unknown): s is string | number {
function isVnode (line 14) | function isVnode(s: any): s is VNode {
FILE: packages/ranuts/src/vnode/modules/attributes.ts
type Attrs (line 3) | type Attrs = Record<string, string | number | boolean>;
function updateAttrs (line 10) | function updateAttrs(oldVnode: VNode, vnode: VNode): void {
FILE: packages/ranuts/src/vnode/modules/class.ts
type Classes (line 3) | type Classes = Record<string, boolean>;
function updateClass (line 5) | function updateClass(oldVnode: VNode, vnode: VNode): void {
FILE: packages/ranuts/src/vnode/modules/index.ts
type ModuleHook (line 7) | type ModuleHook = any;
type Modules (line 9) | type Modules = Record<string, Record<string, ModuleHook>>;
FILE: packages/ranuts/src/vnode/modules/listeners.ts
type Listener (line 7) | type Listener<T> = (this: VNode, ev: T, vnode: VNode) => void;
type On (line 9) | type On = {
type SomeListener (line 13) | type SomeListener<N extends keyof HTMLElementEventMap> = Listener<HTMLEl...
function invokeHandler (line 15) | function invokeHandler<N extends keyof HTMLElementEventMap>(
function handleEvent (line 31) | function handleEvent(event: Event, vnode: VNode) {
function createListener (line 42) | function createListener() {
function updateEventListeners (line 48) | function updateEventListeners(oldVnode: VNode, vnode?: VNode): void {
FILE: packages/ranuts/src/vnode/modules/props.ts
type Props (line 3) | type Props = Record<string, any>;
function updateProps (line 5) | function updateProps(oldVnode: VNode, vnode: VNode): void {
FILE: packages/ranuts/src/vnode/modules/style.ts
type VNodeStyle (line 3) | type VNodeStyle = Record<string, any>;
function updateStyle (line 12) | function updateStyle(oldVnode: VNode, vnode: VNode): void {
function forceReflow (line 63) | function forceReflow(): void {
function applyDestroyStyle (line 67) | function applyDestroyStyle(vnode: VNode): void {
function applyRemoveStyle (line 78) | function applyRemoveStyle(vnode: VNode, rm: () => void): void {
FILE: packages/ranuts/src/vnode/vnode.ts
type VNodes (line 8) | type VNodes = VNode[];
type VNodeChildElement (line 9) | type VNodeChildElement = VNode | string | number;
type ArrayOrElement (line 10) | type ArrayOrElement<T> = T | T[];
type VNodeChildren (line 11) | type VNodeChildren = ArrayOrElement<VNodeChildElement>;
type Key (line 14) | type Key = string | number;
type VNode (line 17) | interface VNode {
type VNodeData (line 35) | interface VNodeData {
function vnode (line 53) | function vnode(
FILE: packages/ranuts/src/wasm/word.ts
type TokenWord (line 4) | interface TokenWord {
type Word (line 10) | interface Word {
FILE: packages/ranuts/src/wicket/index.ts
type ActionOption (line 30) | interface ActionOption {
type wicketMap (line 37) | interface wicketMap {
type WicketOption (line 44) | interface WicketOption {
class WebView (line 49) | class WebView {
method constructor (line 54) | constructor(options: WicketOption) {
method size (line 62) | get size(): number {
method size (line 66) | set size(size: number) {
FILE: packages/ranuts/test/cloneDeep.test.ts
class Person (line 185) | class Person {
method constructor (line 189) | constructor(name: string, age: number) {
method greet (line 194) | greet() {
FILE: packages/ranuts/test/server.test.ts
constant PORT (line 5) | const PORT = 30103;
FILE: packages/ranuts/test/utils/compose.test.ts
function wait (line 12) | function wait(ms: number) {
FILE: packages/ranuts/typings.d.ts
type Identification (line 2) | interface Identification {
type Window (line 10) | interface Window {
type global (line 22) | interface global {
type Process (line 25) | interface Process {
FILE: packages/ranuts/vite.config.ts
type chunkOptimization (line 52) | interface chunkOptimization {
FILE: packages/solidity/ignition/modules/Lock.ts
constant JAN_1ST_2030 (line 4) | const JAN_1ST_2030 = 1893456000;
constant ONE_GWEI (line 5) | const ONE_GWEI: bigint = parseEther('0.001');
FILE: packages/visual/components/bar/index.ts
class Bar (line 2) | class Bar {}
FILE: packages/visual/components/line/index.ts
class Line (line 1) | class Line {}
FILE: packages/visual/components/pie/index.ts
class Pie (line 2) | class Pie {}
FILE: packages/visual/components/sankey/index.ts
type ISankeyOptions (line 4) | interface ISankeyOptions {
type ISankeyNode (line 8) | interface ISankeyNode {
type ISankeyLink (line 21) | interface ISankeyLink {
type ISankeyData (line 27) | interface ISankeyData {
constant NODE_BASE_WIDTH (line 410) | const NODE_BASE_WIDTH = 10;
constant NODE_BASE_HEIGHT (line 411) | const NODE_BASE_HEIGHT = 120;
constant FONT_SIZE_DEFAULT (line 412) | const FONT_SIZE_DEFAULT = 12;
constant FONT_FAMILY (line 413) | const FONT_FAMILY = 'PingFang SC';
constant TEXT_MAX_WIDTH (line 415) | const TEXT_MAX_WIDTH = 120;
constant LAYER_BASE_SPACE (line 416) | const LAYER_BASE_SPACE = 80;
constant BASE_CROSS_SPACE (line 417) | const BASE_CROSS_SPACE = 2;
constant BASE_VERTICAL_SPACE (line 418) | const BASE_VERTICAL_SPACE = 4;
constant FONT_WEIGHT (line 419) | const FONT_WEIGHT = 'normal';
type TEXT_POSITION (line 421) | enum TEXT_POSITION {
class Sankey (line 635) | class Sankey {
method constructor (line 641) | constructor(options: ISankeyOptions) {
FILE: packages/visual/src/application.ts
class Application (line 8) | class Application {
method constructor (line 15) | constructor(options?: IApplicationOptions) {
method render (line 27) | public render(): void {
method start (line 31) | public start(): void {
method stop (line 39) | public stop(): void {
FILE: packages/visual/src/enums.ts
type RENDERER_TYPE (line 2) | enum RENDERER_TYPE {
constant CONTAINER (line 8) | const CONTAINER = 'container';
constant GRAPHICS (line 10) | const GRAPHICS = 'graphics';
FILE: packages/visual/src/event/boundry.ts
class EventBoundary (line 6) | class EventBoundary {
method constructor (line 14) | constructor(stage: Container) {
FILE: packages/visual/src/event/enums.ts
type EventPhase (line 1) | enum EventPhase {
FILE: packages/visual/src/event/event.ts
class EventSystem (line 7) | class EventSystem {
method constructor (line 11) | constructor(canvasEle: HTMLCanvasElement, stage: Container) {
FILE: packages/visual/src/event/types.ts
class FederatedMouseEvent (line 5) | class FederatedMouseEvent {
method stopPropagation (line 17) | public stopPropagation(): void {
type FederatedEventMap (line 22) | type FederatedEventMap = {
type Cursor (line 33) | type Cursor =
FILE: packages/visual/src/graphics/geometry.ts
class GraphicsGeometry (line 5) | class GraphicsGeometry {
method drawShape (line 7) | public drawShape(shape: Shape, fillStyle: Fill, lineStyle: Line): void {
method containsPoint (line 15) | public containsPoint(p: Point): boolean {
method clear (line 27) | public clear(): void {
FILE: packages/visual/src/graphics/graphics.ts
class Graphics (line 20) | class Graphics extends Container {
method constructor (line 26) | constructor() {
method lineStyle (line 32) | public lineStyle(options: ILineStyleOptions | number, color: string = ...
FILE: packages/visual/src/graphics/graphicsData.ts
class GraphicsData (line 3) | class GraphicsData {
method constructor (line 11) | constructor(shape: Shape, fillStyle: Fill, lineStyle: Line) {
FILE: packages/visual/src/render/canvasRender.ts
class CanvasRenderer (line 5) | class CanvasRenderer extends Renderer {
method constructor (line 10) | constructor(options: IApplicationOptions) {
method render (line 21) | public render(container: Container): void {
FILE: packages/visual/src/render/render.ts
method constructor (line 8) | constructor(options: IApplicationOptions) {
method resizeView (line 14) | public resizeView(width: number, height: number): void {
FILE: packages/visual/src/render/webGLRender.ts
class WebGLRenderer (line 4) | class WebGLRenderer extends Renderer {
method constructor (line 5) | constructor(options: IApplicationOptions) {
method render (line 9) | render(): void {
FILE: packages/visual/src/render/webGPURender.ts
class WebGPURenderer (line 4) | class WebGPURenderer extends Renderer {
method constructor (line 5) | constructor(options: IApplicationOptions) {
method render (line 9) | render(): void {
FILE: packages/visual/src/shape/circle.ts
class Circle (line 5) | class Circle extends Shape {
method constructor (line 10) | constructor(x = 0, y = 0, radius = 0) {
method contains (line 16) | public contains(p: Point): boolean {
FILE: packages/visual/src/shape/ellipse.ts
class Ellipse (line 6) | class Ellipse extends Shape {
method constructor (line 12) | constructor(x = 0, y = 0, radiusX = 0, radiusY = 0) {
method contains (line 19) | public contains(p: Point): boolean {
FILE: packages/visual/src/shape/enums.ts
type SHAPE_TYPE (line 2) | enum SHAPE_TYPE {
type LINE_CAP (line 10) | enum LINE_CAP {
type LINE_JOIN (line 16) | enum LINE_JOIN {
FILE: packages/visual/src/shape/fill.ts
class Fill (line 1) | class Fill {
method constructor (line 6) | constructor() {
method clone (line 10) | public clone(): Fill {
method reset (line 18) | public reset(): void {
FILE: packages/visual/src/shape/line.ts
class Line (line 4) | class Line extends Fill {
method clone (line 10) | public clone(): Line {
method reset (line 22) | public reset(): void {
FILE: packages/visual/src/shape/polygon.ts
class Polygon (line 6) | class Polygon extends Shape {
method constructor (line 10) | constructor(points: number[] = []) {
method isIntersect (line 15) | private isIntersect(px: number, py: number, p1x: number, p1y: number, ...
method contains (line 47) | public contains(p: Point): boolean {
FILE: packages/visual/src/shape/rectangle.ts
class Rectangle (line 6) | class Rectangle extends Shape {
method constructor (line 12) | constructor(x = 0, y = 0, width = 0, height = 0) {
method contains (line 19) | public contains(p: Point): boolean {
FILE: packages/visual/src/shape/roundedRectangle.ts
class RoundedRectangle (line 5) | class RoundedRectangle extends Shape {
method constructor (line 12) | constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
method contains (line 21) | public contains(p: Point): boolean {
FILE: packages/visual/src/shape/types.ts
type IFillStyleOptions (line 3) | interface IFillStyleOptions {
type ILineStyleOptions (line 9) | interface ILineStyleOptions extends IFillStyleOptions {
FILE: packages/visual/src/transform/enums.ts
constant PI_2 (line 2) | const PI_2 = Math.PI * 2;
constant DEG_TO_RAD (line 4) | const DEG_TO_RAD = Math.PI / 180;
constant RAD_TO_DEG (line 6) | const RAD_TO_DEG = 180 / Math.PI;
FILE: packages/visual/src/transform/matrix.ts
class Matrix (line 10) | class Matrix {
method constructor (line 18) | constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
FILE: packages/visual/src/transform/transform.ts
class Transform (line 5) | class Transform {
method constructor (line 20) | constructor() {
method rotation (line 27) | get rotation(): number {
method rotation (line 31) | set rotation(r: number) {
method updateLocalTransform (line 62) | public updateLocalTransform(): void {
method updateTransform (line 99) | public updateTransform(parentTransform: Transform): void {
FILE: packages/visual/src/transform/types.ts
type TransformableObject (line 3) | interface TransformableObject {
FILE: packages/visual/src/types.ts
type IApplicationOptions (line 3) | interface IApplicationOptions {
FILE: packages/visual/src/vertex/container.ts
class Container (line 9) | class Container extends Vertex {
method constructor (line 20) | constructor() {
method renderCanvas (line 60) | protected renderCanvas(render: CanvasRenderer): void {
FILE: packages/visual/src/vertex/point.ts
class Point (line 2) | class Point {
method constructor (line 5) | constructor(x = 0, y = 0) {
method set (line 10) | public set(x = 0, y = x): void {
class ObservablePoint (line 19) | class ObservablePoint<T = never> {
method constructor (line 23) | constructor(cb: (...args: T[]) => void, x = 0, y = 0) {
method set (line 29) | set(x = 0, y = x): void {
method x (line 35) | get x(): number {
method x (line 39) | set x(value: number) {
method y (line 46) | get y(): number {
method y (line 50) | set y(value: number) {
FILE: packages/visual/src/vertex/vertex.ts
method zIndex (line 22) | get zIndex(): number {
method zIndex (line 26) | set zIndex(value: number) {
method position (line 33) | get position(): ObservablePoint {
method localTransform (line 37) | get localTransform(): Matrix {
method worldTransform (line 41) | get worldTransform(): Matrix {
method x (line 45) | get x(): number {
method x (line 49) | set x(value: number) {
method y (line 53) | get y(): number {
method y (line 57) | set y(value: number) {
method scale (line 61) | get scale(): ObservablePoint {
method pivot (line 65) | get pivot(): ObservablePoint {
method skew (line 69) | get skew(): ObservablePoint {
method rotation (line 73) | get rotation(): number {
method rotation (line 77) | set rotation(value: number) {
method angle (line 81) | get angle(): number {
method angle (line 85) | set angle(value: number) {
method updateTransform (line 89) | public updateTransform(): void {
Copy disabled (too large)
Download .json
Condensed preview — 919 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (33,132K chars).
[
{
"path": ".editorconfig",
"chars": 146,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
},
{
"path": ".github/dependabot.yml",
"chars": 217,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"github-actions\"\n directory: \"/\"\n schedule:\n interval: weekly\n "
},
{
"path": ".github/workflows/ci.yml",
"chars": 1439,
"preview": "name: CI\non:\n pull_request:\n branches: [main]\n paths:\n - \"packages/**\"\n push:\n branches: [main]\n path"
},
{
"path": ".github/workflows/pages-build-site.yml",
"chars": 1407,
"preview": "name: pages-build-site\non:\n push:\n branches:\n - main\n\npermissions:\n contents: write\n pages: write\n id-token:"
},
{
"path": ".github/workflows/semantic-pull-request.yml",
"chars": 453,
"preview": "name: Semantic Pull Request\n\non:\n pull_request_target:\n types:\n - opened\n - edited\n - synchronize\n\npe"
},
{
"path": ".gitignore",
"chars": 280,
"preview": "# npm\nnode_modules\npackage-lock.json\nnpminstall-debug.log\n# common\n.temp\ncache\n# mac\n.DS_Store\n# eslint\n.eslintcache\n# v"
},
{
"path": ".jscpd.json",
"chars": 265,
"preview": "{\n \"threshold\": 10,\n \"reporters\": [\"html\", \"console\"],\n \"ignore\": [\n \"**/__snapshots__/**\",\n \"**.config.ts\",\n "
},
{
"path": ".prettierignore",
"chars": 72,
"preview": "dist/\nLICENSE.md\npnpm-lock.yaml\npnpm-workspace.yaml\nreport\npublic\nassets"
},
{
"path": ".prettierrc.json",
"chars": 353,
"preview": "{\n \"semi\": true,\n \"tabWidth\": 2,\n \"singleQuote\": true,\n \"printWidth\": 120,\n \"trailingComma\": \"all\",\n \"overrides\": "
},
{
"path": ".vscode/c_cpp_properties.json",
"chars": 915,
"preview": "{\n \"configurations\": [\n {\n \"name\": \"Mac\",\n \"includePath\": [\n \"${workspaceFolder}/**\",\n // 需要"
},
{
"path": ".vscode/launch.json",
"chars": 429,
"preview": "{\n // 使用 IntelliSense 了解相关属性。\n // 悬停以查看现有属性的描述。\n // 欲了解更多信息,请访问:https://go.microsoft.com/fwlink/?linkid=830387\n \"ver"
},
{
"path": ".vscode/markdown.code-snippets",
"chars": 1197,
"preview": "{\n // Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and\n"
},
{
"path": ".vscode/ranui-components.code-snippets",
"chars": 2729,
"preview": "{\n // Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and\n"
},
{
"path": ".vscode/settings.json",
"chars": 1796,
"preview": "{\n \"cSpell.words\": [\n \"abilitys\",\n \"Alloc\",\n \"allowclear\",\n \"ANALYSE\",\n \"analysed\",\n \"binarystring\",\n"
},
{
"path": ".vscode/ts.json.code-snippets",
"chars": 3611,
"preview": "{\n // Place your ran 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and\n"
},
{
"path": "LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2023 chaxus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "SECURITY.md",
"chars": 619,
"preview": "# Security Policy\n\n## Supported Versions\n\nUse this section to tell people about which versions of your project are\ncurre"
},
{
"path": "bin/build.sh",
"chars": 69,
"preview": "npx pnpm -F ranuts build && pnpm -F ranui build && pnpm -F docs build"
},
{
"path": "bin/clean.sh",
"chars": 270,
"preview": "\nrm -rf $(pnpm store path)\nrm -rf node_modules\nrm -rf packages/ranui/node_modules/\nrm -rf packages/ranuts/node_modules/\n"
},
{
"path": "bin/install.sh",
"chars": 205,
"preview": "# 子package安装\npnpm i [package] -r --filter smarty-ui-vite\n# 或者 直接在 ranui 目录下\npnpm i [package]\n# 安装 workspace 中\npnpm i [pa"
},
{
"path": "bin/lint.sh",
"chars": 373,
"preview": "\nbin=./node_modules/.bin\n$bin/prettier --check --cache .\n$bin/eslint --cache . && $bin/prettier --check --cache .\n# befo"
},
{
"path": "bin/nvm.sh",
"chars": 36,
"preview": "nvm alias default node\nnvm use node\n"
},
{
"path": "bin/preinstall.sh",
"chars": 75,
"preview": "# @tensorflow/tfjs-node in github actions\npython3 --version\nnode --version "
},
{
"path": "bin/test.sh",
"chars": 178,
"preview": "pnpm -F docs tsc\npnpm -F image-process tsc\npnpm -F ml tsc\npnpm -F ranui tsc\npnpm -F ranuts tsc\npnpm -F solidity tsc\npnpm"
},
{
"path": "eslint.config.js",
"chars": 6810,
"preview": "// @ts-check\nimport { builtinModules } from 'node:module';\nimport eslint from '@eslint/js';\nimport pluginN from 'eslint-"
},
{
"path": "index.html",
"chars": 7228,
"preview": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-w"
},
{
"path": "package.json",
"chars": 1402,
"preview": "{\n \"name\": \"@ran/monorepo\",\n \"version\": \"1.0.0\",\n \"description\": \"Monorepo\",\n \"type\": \"module\",\n \"engines\": {\n \""
},
{
"path": "packages/cpro/package.json",
"chars": 218,
"preview": "{\n \"name\": \"cpro\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \"echo \\\""
},
{
"path": "packages/cpro/readme.md",
"chars": 31574,
"preview": "# C++\n\n如果要为 macOS 进行 C++ 开发,建议安装 Clang 编译器。只需在“终端”窗口中运行以下命令即可安装命令行开发人员工具:\n\n```sh\nxcode-select --install\n```\n\n然后,要验证已安装 c"
},
{
"path": "packages/cpro/sum.cpp",
"chars": 236,
"preview": "#include <emscripten/bind.h>\n\nusing namespace emscripten;\n\n//接收两个浮点型参数,返回一个字符串\nstd::string sum(double a,double b) {\n "
},
{
"path": "packages/debug/koaStatic/index.ts",
"chars": 1132,
"preview": "import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport Koa from 'koa';\nimport serve from 'koa-st"
},
{
"path": "packages/debug/koaStatic/readme.md",
"chars": 81,
"preview": "# 静态服务\n\n用于排查一些本地启动没有问题,但是部署到线上环境就无法运行的问题\n\n有时候需要搭配 nginx 做反向代理域名映射,用于完整并彻底的模拟线上环境\n"
},
{
"path": "packages/debug/nginxconf/agency.conf",
"chars": 385,
"preview": "\nevents {\n worker_connections 1024;\n}\n\nhttp {\n server {\n listen 80;\n server_name trade-app.longbridge.xyz;\n\n "
},
{
"path": "packages/debug/nginxconf/readme.md",
"chars": 2213,
"preview": "1. 使用命令行参数指定配置文件路径\n\n```sh\nnginx -c /path/to/your/nginx.conf\n```\n\n请注意,当您使用 -c 参数时,Nginx 将仅加载您指定的配置文件,而不会加载任何其他通过 include "
},
{
"path": "packages/debug/package.json",
"chars": 503,
"preview": "{\n \"name\": \"debug\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \"echo \\"
},
{
"path": "packages/debug/tsconfig.json",
"chars": 632,
"preview": "{\n \"exclude\": [\"node_modules/**\", \"dist/**\", \"public\"],\n \"include\": [\"**/*.ts\", \"**/*.d.ts\", \"**/*.tsx\", \"tailwind.con"
},
{
"path": "packages/docs/.vitepress/common/index.ts",
"chars": 4783,
"preview": "import { SERVICE_WORK_VERSION } from '../../variable/SERVICE_WORK_VERSION';\n\nexport const GTAG = 'https://www.googletagm"
},
{
"path": "packages/docs/.vitepress/common/sw.ts",
"chars": 704,
"preview": "// 注册 Service worker\nconst registerServiceWorker = async () => {\n if ('serviceWorker' in window.navigator) {\n try {\n"
},
{
"path": "packages/docs/.vitepress/components/Layout.vue",
"chars": 852,
"preview": "<template>\n <DefaultTheme.Layout />\n</template>\n<script setup lang=\"ts\">\nimport DefaultTheme from 'vitepress/theme';\nim"
},
{
"path": "packages/docs/.vitepress/components/TOTP.vue",
"chars": 2053,
"preview": "<template>\n <div>\n <div class=\"text-slate-600 text-base mt-2\">{{ t('components_totp_6') }}</div>\n <div class=\"fle"
},
{
"path": "packages/docs/.vitepress/composition/useBasic.ts",
"chars": 243,
"preview": "import { inject } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport type { Env } from '../plugins/env';\n\nexport def"
},
{
"path": "packages/docs/.vitepress/config.ts",
"chars": 2871,
"preview": "import { defineConfig } from 'vitepress';\nimport { themeEnConfig } from './langs/en';\nimport { themeCnConfig } from './l"
},
{
"path": "packages/docs/.vitepress/lang/en.json",
"chars": 311,
"preview": "{\n \"lang\": \"English\",\n \"components_totp_1\": \"Generate\",\n \"components_totp_2\": \"Please enter the key of 2FA\",\n \"compo"
},
{
"path": "packages/docs/.vitepress/lang/index.ts",
"chars": 1282,
"preview": "import { createI18n } from 'vue-i18n';\nimport { $env } from '../plugins/env';\nimport { I18N_MODE, LANGS_DICT, LANG_MESSA"
},
{
"path": "packages/docs/.vitepress/lang/zh-CN.json",
"chars": 236,
"preview": "{\n \"lang\": \"简体中文\",\n \"components_totp_1\": \"生成结果\",\n \"components_totp_2\": \"请输入 2FA 的 key\",\n \"components_totp_3\": \"你还没有输"
},
{
"path": "packages/docs/.vitepress/langs/cn/index.ts",
"chars": 14872,
"preview": "import type { DefaultTheme } from 'vitepress';\nimport { GITHUB } from '../../common/index';\n\nconst themeCnConfig: Defaul"
},
{
"path": "packages/docs/.vitepress/langs/en/index.ts",
"chars": 15264,
"preview": "import type { DefaultTheme } from 'vitepress';\nimport { GITHUB } from '../../common/index';\n\nconst themeEnConfig: Defaul"
},
{
"path": "packages/docs/.vitepress/lib/constant.ts",
"chars": 600,
"preview": "export enum INPUT_STATUS {\n NORMAL = 'normal',\n ERROR = 'error',\n WARNING = 'warning',\n}\n// 支持语言包字典\nexport enum LANGS"
},
{
"path": "packages/docs/.vitepress/plugins/env.ts",
"chars": 881,
"preview": "import { currentDevice, isBangDevice, isMobile, isWeiXin } from 'ranuts/utils';\nimport type { App } from 'vue';\nimport t"
},
{
"path": "packages/docs/.vitepress/theme/index.ts",
"chars": 1708,
"preview": "import DefaultTheme from 'vitepress/theme';\nimport type { EnhanceAppContext } from 'vitepress';\nimport { localStorageGet"
},
{
"path": "packages/docs/.vitepress/theme/styles/index.less",
"chars": 744,
"preview": "#app .VPNavBar {\n border-bottom: 1px solid var(--vp-c-divider-light);\n}\n\n#app .VPHomeHero {\n margin-top: 20px;\n margi"
},
{
"path": "packages/docs/.vitepress/theme/styles/vars.less",
"chars": 2966,
"preview": "/**\n * Colors\n * -------------------------------------------------------------------------- */\n\n:root {\n --vp-c-brand: "
},
{
"path": "packages/docs/.vitepress/theme/theme.less",
"chars": 1606,
"preview": ":root {\n --bg-color: #f5f6f6;\n --front-bg-color-2: #fafafa;\n --front-bg-color-1: #ffffff;\n --front-bg-color1: #fffff"
},
{
"path": "packages/docs/bin/build.sh",
"chars": 1371,
"preview": "#!/bin/bash\n# 更新 service work的版本号\nversion=$(date +%s)\n# 将版本号写入 variable 目录下 SERVICE_WORK_VERSION.ts\nSERVICE_WORK_VERSION"
},
{
"path": "packages/docs/cn/index.md",
"chars": 528,
"preview": "---\nlayout: home\n\ntitle: Home\n\nhero:\n name: ran\n text: 风起于青萍之末\n tagline: A ship in harbor is safe, but that is not wh"
},
{
"path": "packages/docs/cn/src/article/ai/index.md",
"chars": 3168,
"preview": "# Prompt\n\n## System Prompt\n\n用来描述 AI 的角色,性格,背景知识,语气等,总之只要不是用户直接说出来的内容,都可以放到 System Prompt 里面。\n\n## User Prompt\n\n用户直接发送给 AI"
},
{
"path": "packages/docs/cn/src/article/ast_parse/tokenizer.md",
"chars": 11640,
"preview": "# Abstract Syntax Tree\n\n## 一.(`abstract syntax tree`)抽象语法树的作用\n\n源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同"
},
{
"path": "packages/docs/cn/src/article/babel.md",
"chars": 509,
"preview": "# Babel\n\nbabel 核心库主要是:\n\n- @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。\n- @babel/travers"
},
{
"path": "packages/docs/cn/src/article/bundle.md",
"chars": 158,
"preview": "# Bundle\n\nBundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下"
},
{
"path": "packages/docs/cn/src/article/design_mode.md",
"chars": 41609,
"preview": "# 23 种经典设计模式\n\n> 设计模式 `Design Pattern` 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。。\n\n在《设计模式:可复"
},
{
"path": "packages/docs/cn/src/article/doc_preview.md",
"chars": 19228,
"preview": "<h1> 最全的 docx,pptx,xlsx(excel),pdf 文件预览方案总结 </h1>\n\n最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下\n\n"
},
{
"path": "packages/docs/cn/src/article/functional_programming.md",
"chars": 11127,
"preview": "# 函数式编程\n\n- 概述:函数式编程 (`Functional Programming`)`FP`就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。\n- 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对"
},
{
"path": "packages/docs/cn/src/article/imagemin.md",
"chars": 20,
"preview": "# imagemin 图片压缩源码分析\n"
},
{
"path": "packages/docs/cn/src/article/javascript/dom_load.md",
"chars": 388,
"preview": "# 页面加载完成后事件\n\n## window.onload\n\n## DOMContentLoaded\n\n```js\ndocument.addEventListener('DOMContentLoaded', fun);\n```\n\n## `<"
},
{
"path": "packages/docs/cn/src/article/math/linear_algebra.md",
"chars": 5144,
"preview": "# 线性代数\n\n## 一:向量究竟是什么\n\n线性代数中最基础,最根源的组成部分就是向量。一般来说,有三种看待向量的观点:\n\n1. 从物理学家的视角来看:向量是空间中的箭头,决定一个向量是它的长度和它所指的方向。其中平面的向量是二维的,处在我"
},
{
"path": "packages/docs/cn/src/article/sort/bubble/index.md",
"chars": 724,
"preview": "# 冒泡排序(Bubble Sort)\n\n冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名"
},
{
"path": "packages/docs/cn/src/article/sort/bucket/index.md",
"chars": 1801,
"preview": "# 桶排序 (Bucket Sort)\n\n高效与否的关键在于这个分桶函数。将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。\n\n## 算法描述\n\n- 设置一个定量的数组当作空桶;\n- "
},
{
"path": "packages/docs/cn/src/article/sort/count/index.md",
"chars": 1293,
"preview": "# 计数排序( Count Sort )\n\n计数排序(counting sort)就是一种牺牲内存空间来换取低时间复杂度的排序算法,同时它也是一种不基于比较的算法。这里的不基于比较指的是数组元素之间不存在比较大小的排序算法,我们知道,用分治"
},
{
"path": "packages/docs/cn/src/article/sort/heap/index.md",
"chars": 1734,
"preview": "# 堆排序(Heap Sort)\n\n堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。\n\n## 算法描述\n\n- 将"
},
{
"path": "packages/docs/cn/src/article/sort/index.md",
"chars": 473,
"preview": "# 十大经典排序\n\n十种常见排序算法可以分为两大类:\n\n- **比较类排序**:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序。\n- **非比较类排序**:不通过比较来决定元素间的"
},
{
"path": "packages/docs/cn/src/article/sort/insert/index.md",
"chars": 818,
"preview": "# 插入排序(Insert Sort)\n\n表现稳定的排序算法,因为无论什么数据进去都是 O(n2) 的时间复杂度,所以用到它的时候,数据规模越小越好。优点是不占用额外的内存空间。工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后"
},
{
"path": "packages/docs/cn/src/article/sort/merge/index.md",
"chars": 1172,
"preview": "# 归并排序(Merge Sort)\n\n归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序"
},
{
"path": "packages/docs/cn/src/article/sort/quick/index.md",
"chars": 1754,
"preview": "# 快速排序(Quick Sort)\n\n快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。\n\n## 算法描述\n\n快速排序使用分"
},
{
"path": "packages/docs/cn/src/article/sort/radix/index.md",
"chars": 1458,
"preview": "# 基数排序(Radix Sort)\n\n基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的"
},
{
"path": "packages/docs/cn/src/article/sort/select/index.md",
"chars": 1068,
"preview": "# 选择排序(Selection Sort)\n\n选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素"
},
{
"path": "packages/docs/cn/src/article/sort/shell/index.md",
"chars": 1057,
"preview": "# 希尔排序(Shell Sort)\n\n1959 年 Shell 发明,第一个突破 O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。\n\n## 算法描述\n\n先将整"
},
{
"path": "packages/docs/cn/src/article/system_design.md",
"chars": 602,
"preview": "# 如何处理一个系统设计\n\n系统设计是一个开放式的对话。他们期望你去主导这个对话。\n\n你可以使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成系统设计的面试题和解答这个章节。\n\n## 第一步:描述使用场景,约束和假设\n\n把所有"
},
{
"path": "packages/docs/cn/src/article/typescript/calculate.md",
"chars": 5148,
"preview": "# 数组长度做计数\n\n类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。\n\n没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。\n\n这是类型体操的第四个套路:数组长度做计数。\n\nTypeScript 类型系统"
},
{
"path": "packages/docs/cn/src/article/typescript/index.md",
"chars": 14880,
"preview": "# TypeScript 的类型系统\n\n## 一.类型是什么\n\n类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:\n\n- **不"
},
{
"path": "packages/docs/cn/src/article/typescript/pattern.md",
"chars": 8878,
"preview": "# 模式匹配提取\n\n字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。\n\n```ts\n'abc'.replace(/a(b)c/, '$1,$1,$1');\n// 'b,b,b'\n```\n\nType"
},
{
"path": "packages/docs/cn/src/article/typescript/reconstruction.md",
"chars": 7280,
"preview": "# 重新构造做变换\n\n类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?\n\nTypeScript 类型系统支持 3 种可以声明任意类型的变量: type、infer、类型参数。\n\ntype 叫做类型别名,其实就是声明一个变量存"
},
{
"path": "packages/docs/cn/src/article/typescript/recursion.md",
"chars": 6942,
"preview": "# 递归复用\n\n递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。\n\nTypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的"
},
{
"path": "packages/docs/cn/src/article/typescript/union_type.md",
"chars": 4986,
"preview": "# 分布式条件类型\n\n当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。\n\n比如这样一个联合类型:\n\n```ts\nt"
},
{
"path": "packages/docs/cn/src/article/video.md",
"chars": 25335,
"preview": "<h1>实现自适应码率 Web 视频加密播放:前后端的挑战与解决方案</h1>\n\n最近又遇到了`web`视频化的场景,之前也有过调研:[H5 视频化调研浅析](https://juejin.cn/post/72387396628227359"
},
{
"path": "packages/docs/cn/src/article/visual.md",
"chars": 38798,
"preview": "# 可视化渲染引擎\n\n## 零:系统设计\n\n在系统设计的过程中,需要明确**使用场景**,**约束条件**,**边界情况**。描述出最主要实现的功能,将这些功能进行高层级的设计,分类,链接。\n\n有了具体要实现的功能模块后,我们就再根据功能模"
},
{
"path": "packages/docs/cn/src/blockchain/index.md",
"chars": 3298,
"preview": "# 区块链数据结构\n\n区块链作为 Web3 生态的核心基础设施,相当于一个分布式数据库,用于存储全球范围内的交易数据、智能合约、用户身份信息和各种类型的去中心化应用(dApps)数据。以太坊区块链从上往下可以依次分解为:区块链、区块、交易三"
},
{
"path": "packages/docs/cn/src/blockchain/web3.md",
"chars": 4455,
"preview": "# 如何参与 web3\n\nWeb3 作为下一代互联网,为人们提供了一个去中心化、由用户控制的网络环境。普通人可以通过创建数字钱包、购买和交易加密货币、及参与 NFT 市场等方式参与到 Web3 中。下面我将带领你,从零开始一步一步踏入 We"
},
{
"path": "packages/docs/cn/src/note/centos.md",
"chars": 1219,
"preview": "# CentOS\n\n查看当前系统的版本:\n\n```sh\ncat /etc/centos-release\n```\n\n## YUM\n\nYUM 是 Yellowdog Updater, Modified 的缩写,虽然不是 CentOS 开发的,但"
},
{
"path": "packages/docs/cn/src/note/docker.md",
"chars": 5902,
"preview": "# docker\n\n查询 `docker` 是否在运行:\n\n1. 输入以下命令来查找 `Docker` 守护进程的 `PID`(进程 `ID`):\n\n```sh\nps -ef | grep docker\n```\n\n如果命令返回了包含`/us"
},
{
"path": "packages/docs/cn/src/note/libreoffice2wasm.md",
"chars": 11485,
"preview": "## 项目地址:\n\n```sh\ngit clone https://git.libreoffice.org/core\n```\n\ngithub 地址:`https://github.com/LibreOffice/core/blob/mast"
},
{
"path": "packages/docs/cn/src/note/ubuntu.md",
"chars": 461,
"preview": "# ubuntu\n\n```sh\napt update\n\napt install openjdk-11-jdk wget curl junit4 ant libgstreamer1.0-dev libgstreamer-plugins-ba"
},
{
"path": "packages/docs/cn/src/ranui/button/index.md",
"chars": 3353,
"preview": "# Button 按钮\n\n按钮组件用于触发一个即时操作,支持多种样式和状态。\n\n## 快速开始\n\n### 基础用法\n\n<r-button>Button</r-button>\n\n```html\n<r-button>Button</r-butt"
},
{
"path": "packages/docs/cn/src/ranui/checkbox/index.md",
"chars": 804,
"preview": "# CheckBox 多选框\n\n## 代码演示\n\n<r-checkbox></r-checkbox>\n\n```xml\n <r-checkbox ></r-checkbox>\n```\n\n## 属性\n\n### `checked`\n\n<r-che"
},
{
"path": "packages/docs/cn/src/ranui/icon/index.md",
"chars": 3504,
"preview": "# Icon 图标\n\n语义化的矢量图形\n\n## 代码演示\n\n<div style='display:flex'>\n <r-icon name=\"lock\" size=\"50\" ></r-icon>\n <r-icon name"
},
{
"path": "packages/docs/cn/src/ranui/image/index.md",
"chars": 3416,
"preview": "# Image 图片\n\n## 代码演示\n\n```xml\n <r-img src=\"\" fallback=\"\"></r-img>\n```\n\n## 属性\n\n### 图片加载地址`src`\n\n图片的地址\n\n### 图片加载失败`fallback`"
},
{
"path": "packages/docs/cn/src/ranui/index.md",
"chars": 7888,
"preview": "# ranui\n\n基于 `Web Components`开发方案\n\n## 特点\n\n1. **跨框架兼容:** 与 React, Vue, Preact, SolidJS, Svelte 等兼容。可以和遵循 W3C 标准的任何 JavaScr"
},
{
"path": "packages/docs/cn/src/ranui/input/index.md",
"chars": 5953,
"preview": "# Select 下拉选择框\n\n下拉选择器组件,支持单选、搜索、自定义样式等功能。\n\n## 快速开始\n\n### 基础用法\n\n<r-select style=\"width: 120px; height: 40px\" defaultValue="
},
{
"path": "packages/docs/cn/src/ranui/loading/index.md",
"chars": 3758,
"preview": "<script setup>\nimport Loading from '../../../../vue/loading.vue'\n</script>\n\n# Loading 加载\n\n提供多种精美的加载动画效果,用于提升用户体验。\n\n## 快速"
},
{
"path": "packages/docs/cn/src/ranui/math/index.md",
"chars": 398,
"preview": "# math 数学公式\n\n在 `HTML` 页面中高质量展示 `LaTeX` 数学公式\n\n## 代码演示\n\n<r-math latex=\"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b "
},
{
"path": "packages/docs/cn/src/ranui/message/index.md",
"chars": 2290,
"preview": "# message 全局提示\n\n全局展示操作反馈信息。\n\n## 代码演示\n\n<div style=\"display:inline-block;margin-right: 8px;margin-bottom: 12px;\">\n <r-"
},
{
"path": "packages/docs/cn/src/ranui/modal/index.md",
"chars": 0,
"preview": ""
},
{
"path": "packages/docs/cn/src/ranui/player/index.md",
"chars": 3916,
"preview": "# r-player 视频播放器\n\n基于`hlsjs`和`web components`,让原生的标签`r-player`拥有统一的视频控件。\n不采用`new Player(options)`的方式挂载到指定`dom`,视图的归视图,逻辑的"
},
{
"path": "packages/docs/cn/src/ranui/popover/index.md",
"chars": 2630,
"preview": "# Popover 气泡卡片\n\n点击/鼠标移入元素,弹出气泡式的卡片浮层。\n\n## 代码演示\n\n<r-popover style=\"display: inline-block;\">\n <r-button>popover</r-butt"
},
{
"path": "packages/docs/cn/src/ranui/preview/index.md",
"chars": 2745,
"preview": "# preview 文件预览\n\n支持 `docx`、`pptx`、`pdf`、`xlsx` 文件的在线预览组件\n\n> ⚠️ **重要通知**: ranui 包在 0.1.10-alpha-27 版本之后将不再提供此组件,请迁移到独立的 [@"
},
{
"path": "packages/docs/cn/src/ranui/progress/index.md",
"chars": 2238,
"preview": "# progress 进度条\n\n可交互的进度条\n\n## 代码演示\n\n<r-progress type=\"drag\" ></r-progress>\n\n```xml\n<r-progress type=\"drag\" ></r-progress>\n"
},
{
"path": "packages/docs/cn/src/ranui/radar/index.md",
"chars": 5405,
"preview": "# Radar 雷达图\n\n以二维形式综合对比多组数据的差异,常用于比较 2 组或更多组数据集\n\n## 代码演示\n\n<r-radar style=\"width:300px;height:300px;display: block;\" abili"
},
{
"path": "packages/docs/cn/src/ranui/select/index.md",
"chars": 5953,
"preview": "# Select 下拉选择框\n\n下拉选择器组件,支持单选、搜索、自定义样式等功能。\n\n## 快速开始\n\n### 基础用法\n\n<r-select style=\"width: 120px; height: 40px\" defaultValue="
},
{
"path": "packages/docs/cn/src/ranui/skeleton/index.md",
"chars": 402,
"preview": "# skeleton 骨架屏\n\n在需要等待加载内容的位置提供一个占位图形组合。\n\n## 代码演示\n\n骨架长度跟随父级元素的长度\n\n<div style=\"width: 100px;margin-top:10px\">\n <r-skele"
},
{
"path": "packages/docs/cn/src/ranui/tab/index.md",
"chars": 4487,
"preview": "# Tab 图标\n\n标签页,其中`r-tab`需要和`r-tabs`搭配使用\n\n## 代码演示\n\n<div style=\"width:100%;\">\n <r-tabs >\n <r-tab label=\"tab1\">111"
},
{
"path": "packages/docs/cn/src/ranui/tabs/index.md",
"chars": 2358,
"preview": "# Tab\n\n## 代码展示\n\n<r-tabs>\n <r-tab label=\"tab1\">tab1</r-tab>\n <r-tab label=\"tab2\">tab2</r-tab>\n <r-tab label=\"tab"
},
{
"path": "packages/docs/cn/src/ranuts/binary_tree/index.md",
"chars": 1483,
"preview": "# 二叉树的定义\n\n在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[<sup>[1]</su"
},
{
"path": "packages/docs/cn/src/ranuts/bundler/index.md",
"chars": 318,
"preview": "# Bundler\n\n`Bundler`的使用:\n传入 options 参数\n\n```\nfunction build(options: Options):Promise<Build> {\n const bundle = new Bundl"
},
{
"path": "packages/docs/cn/src/ranuts/file/append_file.md",
"chars": 638,
"preview": "# AppendFile\n\n追加一些数据到文件内\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 | 说明 | 类型 | 描述 "
},
{
"path": "packages/docs/cn/src/ranuts/file/file_info.md",
"chars": 576,
"preview": "# QueryFileInfo\n\n查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 |"
},
{
"path": "packages/docs/cn/src/ranuts/file/read_dir.md",
"chars": 434,
"preview": "# ReadDir\n\n读一个目录下的所有文件\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 | 说明 | 类型 | 描述 |\n| ------ | -"
},
{
"path": "packages/docs/cn/src/ranuts/file/read_file.md",
"chars": 505,
"preview": "# ReadFile\n\n观察一个文件是否改变\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 | 说明 | 类型 | 描述 |\n| --"
},
{
"path": "packages/docs/cn/src/ranuts/file/watch_file.md",
"chars": 500,
"preview": "# WatchFile\n\n观察一个文件是否改变\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 | 说明 | 类型 | 描述 |\n|"
},
{
"path": "packages/docs/cn/src/ranuts/file/write_file.md",
"chars": 629,
"preview": "# WriteFile\n\n将内容写入文件\n\n## API\n\n### Return\n\n- Promise\n\n| 参数 | 说明 | 类型 | "
},
{
"path": "packages/docs/cn/src/ranuts/index.md",
"chars": 1274,
"preview": "# ranuts overview\n\n## 分类导航\n\n- [工具函数](./utils/index.md) - 函数式编程、字符串处理、对象处理、数字处理等\n- [文件操作](./file/write_file.md) - 文件读写、监听"
},
{
"path": "packages/docs/cn/src/ranuts/mime_type/mime_type.md",
"chars": 557,
"preview": "# getMime\n\n传入文件格式后缀,返回`mime type`\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | --------------- "
},
{
"path": "packages/docs/cn/src/ranuts/mode/subscribe.md",
"chars": 1120,
"preview": "# EventEmitter\n\n发布订阅的类\n\n## Class\n\n### Methods\n\n| 方法 | 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/add_class_to_element.md",
"chars": 1019,
"preview": "# addClassToElement\n\n给指定的 DOM 元素添加 CSS 类名。\n\n## API\n\n### addClassToElement\n\n#### Return\n\n无返回值(`void`)\n\n#### Parameters\n\n|"
},
{
"path": "packages/docs/cn/src/ranuts/utils/add_num_sym.md",
"chars": 1403,
"preview": "# addNumSym\n\n给数字添加正负号(+ 或 -)。\n\n## API\n\n### addNumSym\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | -"
},
{
"path": "packages/docs/cn/src/ranuts/utils/append_url.md",
"chars": 1652,
"preview": "# appendUrl\n\n将查询参数对象拼接到 URL 后面。\n\n## API\n\n### appendUrl\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | -"
},
{
"path": "packages/docs/cn/src/ranuts/utils/chain.md",
"chars": 2474,
"preview": "# Chain\n\n链式调用的 DOM 操作类,支持创建元素、设置属性、添加事件监听等操作。\n\n## API\n\n### Chain\n\n#### 构造函数\n\n```typescript\nnew Chain(tagName: string, op"
},
{
"path": "packages/docs/cn/src/ranuts/utils/change_hump_to_lower_case.md",
"chars": 1222,
"preview": "# changeHumpToLowerCase\n\n将驼峰命名转换为下划线命名(小写)。\n\n## API\n\n### changeHumpToLowerCase\n\n#### Return\n\n| 参数 | 说明 | 类"
},
{
"path": "packages/docs/cn/src/ranuts/utils/check_encoding.md",
"chars": 1241,
"preview": "# checkEncoding\n\n检测 Uint8Array 数据的字符编码。\n\n## API\n\n### checkEncoding\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| "
},
{
"path": "packages/docs/cn/src/ranuts/utils/clear_br.md",
"chars": 931,
"preview": "# clearBr\n\n清除字符串中的空格、HTML 标签和换行符。\n\n## API\n\n### clearBr\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | ---"
},
{
"path": "packages/docs/cn/src/ranuts/utils/clear_str.md",
"chars": 1449,
"preview": "# clearStr\n\n去除字符串首尾的空格、URL 编码和引号。\n\n## API\n\n### clearStr\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | --"
},
{
"path": "packages/docs/cn/src/ranuts/utils/clone_deep.md",
"chars": 1607,
"preview": "# cloneDeep\n\n深度克隆对象或数组,创建一个完全独立的副本,包括所有嵌套的对象和数组。\n\n## API\n\n### cloneDeep\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n|"
},
{
"path": "packages/docs/cn/src/ranuts/utils/compose.md",
"chars": 2548,
"preview": "# compose\n\n组合多个中间件函数,将异步函数转化为同步的方式进行执行。常用于构建中间件系统,如 Koa 风格的中间件。\n\n## API\n\n### compose\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/connection.md",
"chars": 1387,
"preview": "# connection\n\n获取当前网络连接信息(Network Information API)。\n\n## API\n\n### connection\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/convert_image_to_base64.md",
"chars": 2147,
"preview": "# convertImageToBase64\n\n将图片文件转换为 Base64 编码字符串。\n\n## API\n\n### convertImageToBase64\n\n#### Return\n\n| 参数 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/create.md",
"chars": 1301,
"preview": "# create\n\n创建 DOM 元素的辅助函数,支持 HTML 和 SVG 元素。\n\n## API\n\n### create\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/create_document_fragment.md",
"chars": 1560,
"preview": "# createDocumentFragment\n\n创建一个 DocumentFragment 并添加多个子元素。\n\n## API\n\n### createDocumentFragment\n\n#### Return\n\n| 参数 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/create_object_url.md",
"chars": 1782,
"preview": "# createObjectURL\n\n从 Blob、ArrayBuffer 或 Response 创建对象 URL。\n\n## API\n\n### createObjectURL\n\n#### Return\n\n| 参数 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/create_signal.md",
"chars": 1939,
"preview": "# createSignal\n\n创建响应式信号(Signal),支持值变化时通知订阅者。\n\n## API\n\n### createSignal\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/current_device.md",
"chars": 1191,
"preview": "# currentDevice\n\n获取当前设备类型。\n\n## API\n\n### currentDevice\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/debounce.md",
"chars": 1293,
"preview": "# debounce\n\n防抖函数,用于限制函数的执行频率。在指定的时间间隔内,如果函数被多次调用,只有最后一次调用会在延迟时间后执行。\n\n## API\n\n### debounce\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/duration_handler.md",
"chars": 1549,
"preview": "# durationHandler\n\n创建一个延迟执行函数,在指定时间后执行指定的函数。\n\n## API\n\n### durationHandler\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/encode_url.md",
"chars": 1366,
"preview": "# encodeUrl\n\n安全地编码 URL,排除已编码的序列,处理未匹配的代理对。\n\n## API\n\n### encodeUrl\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -----"
},
{
"path": "packages/docs/cn/src/ranuts/utils/escape_html.md",
"chars": 1498,
"preview": "# escapeHtml\n\n转义 HTML 特殊字符,防止 XSS 攻击。\n\n## API\n\n### escapeHtml\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/filter_obj.md",
"chars": 601,
"preview": "# filterObj\n\n过滤对象的属性,去除对象中在 list 数组里面有的属性,返回一个新对象,一般是用于去除空字符和 null\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/format_json.md",
"chars": 614,
"preview": "# formatJson\n\n传入一个 JSON 或者 JSON 的字符串,添加空格和换行进行返回一个格式化的 JSON 字符串\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 |\n"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_all_query_string.md",
"chars": 1553,
"preview": "# getAllQueryString\n\n从 URL 中提取所有查询参数并转换为对象。\n\n## API\n\n### getAllQueryString\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_cookie.md",
"chars": 506,
"preview": "# getCookie\n\n传入字符串,获取指定名字的 cookie 的值\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 |\n| ------- "
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_cookie_by_name.md",
"chars": 1245,
"preview": "# getCookieByName\n\n通过正则表达式获取指定名称的 Cookie 值。\n\n## API\n\n### getCookieByName\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_extensions.md",
"chars": 1175,
"preview": "# getExtensions\n\n根据 MIME 类型获取对应的文件扩展名数组。\n\n## API\n\n### getExtensions\n\n#### Return\n\n| 参数 | 说明 | 类"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_frame.md",
"chars": 1420,
"preview": "# getFrame\n\n计算每毫秒的帧率(FPS),每秒的帧率需要乘以 1000。\n\n## API\n\n### getFrame\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_host.md",
"chars": 1394,
"preview": "# getHost\n\n根据环境配置获取主机地址。\n\n## API\n\n### getHost\n\n#### Return\n\n| 参数 | 说明 | 类型 |"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_matching_sentences.md",
"chars": 1451,
"preview": "# getMatchingSentences\n\n从文本中提取包含搜索关键词的完整句子,对于重复的句子只保留最长的一个。\n\n## API\n\n### getMatchingSentences\n\n#### Return\n\n| 参数 | 说明"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_performance.md",
"chars": 3072,
"preview": "# getPerformance\n\n获取页面性能指标数据,包括 DNS 解析、TCP 连接、资源加载等各项性能指标。\n\n## API\n\n### getPerformance\n\n#### Return\n\n| 参数 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_pixel_ratio.md",
"chars": 1565,
"preview": "# getPixelRatio\n\n获取 Canvas 上下文的分辨率比例,用于处理高 DPI 屏幕。\n\n## API\n\n### getPixelRatio\n\n#### Return\n\n| 参数 | 说明 | 类型 |"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_query.md",
"chars": 1283,
"preview": "# getQuery\n\n从 URL 中提取查询参数并转换为对象(与 getAllQueryString 功能相同)。\n\n## API\n\n### getQuery\n\n#### Return\n\n| 参数 | 说明 | 类"
},
{
"path": "packages/docs/cn/src/ranuts/utils/get_window.md",
"chars": 1384,
"preview": "# getWindow\n\n跨浏览器获取可视窗口大小。\n\n## API\n\n### getWindow\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -----------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/handle_console.md",
"chars": 1423,
"preview": "# handleConsole\n\n拦截并处理 console 方法调用,可以在控制台输出前后执行自定义逻辑。\n\n## API\n\n### handleConsole\n\n#### Return\n\n无返回值(`void`)\n\n#### Param"
},
{
"path": "packages/docs/cn/src/ranuts/utils/handle_error.md",
"chars": 1576,
"preview": "# handleError\n\n全局错误处理,捕获未处理的 Promise 拒绝和运行时错误。\n\n## API\n\n### handleError\n\n#### Return\n\n无返回值(`void`)\n\n#### Parameters\n\n| 参"
},
{
"path": "packages/docs/cn/src/ranuts/utils/handle_fetch_hook.md",
"chars": 1983,
"preview": "# handleFetchHook\n\n拦截并处理 `fetch` 请求,可以在请求前后执行自定义逻辑。\n\n## API\n\n### handleFetchHook\n\n#### Return\n\n无返回值(`void`)\n\n#### Parame"
},
{
"path": "packages/docs/cn/src/ranuts/utils/hex_to_rgb.md",
"chars": 1399,
"preview": "# hexToRgb\n\n将十六进制颜色值转换为 RGB 数组。\n\n## API\n\n### hexToRgb\n\n#### Return\n\n| 参数 | 说明 |"
},
{
"path": "packages/docs/cn/src/ranuts/utils/image_request.md",
"chars": 1354,
"preview": "# imageRequest\n\n通过图片请求测试网络延迟(ping 值)。\n\n## API\n\n### imageRequest\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/index.md",
"chars": 10191,
"preview": "# 工具函数\n\n## 函数式编程\n\n| 方法 | 说明 | 详细内容 |\n| -------- | -------------- | ----------------------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_bang_device.md",
"chars": 1123,
"preview": "# isBangDevice\n\n判断当前设备是否为 iPhone 刘海屏机型。\n\n## API\n\n### isBangDevice\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n|"
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_client.md",
"chars": 968,
"preview": "# isClient\n\n判断当前环境是否为客户端(浏览器)环境。\n\n## API\n\n### isClient\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| --------- "
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_equal.md",
"chars": 1634,
"preview": "# isEqual\n\n深度比较两个值是否相等,支持对象、数组、日期等复杂类型的比较。\n\n## API\n\n### isEqual\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| ---"
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_image_size.md",
"chars": 1854,
"preview": "# isImageSize\n\n校验图片文件的尺寸是否符合指定要求。\n\n## API\n\n### isImageSize\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_mobile.md",
"chars": 923,
"preview": "# isMobile\n\n判断当前设备是否为移动端设备。\n\n## API\n\n### isMobile\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| --------- | -------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_safari.md",
"chars": 1104,
"preview": "# isSafari\n\n判断当前浏览器是否为 Safari。\n\n## API\n\n### isSafari\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_string.md",
"chars": 1144,
"preview": "# isString\n\n判断一个值是否为字符串类型。\n\n## API\n\n### isString\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| --------- | --------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/is_weixin.md",
"chars": 858,
"preview": "# isWeiXin\n\n判断当前环境是否为微信浏览器。\n\n## API\n\n### isWeiXin\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| --------- | ---"
},
{
"path": "packages/docs/cn/src/ranuts/utils/local_storage.md",
"chars": 1819,
"preview": "# localStorageGetItem / localStorageSetItem\n\n安全地操作 localStorage,支持服务端渲染环境。\n\n## API\n\n### localStorageSetItem\n\n设置 localSto"
},
{
"path": "packages/docs/cn/src/ranuts/utils/mathjs.md",
"chars": 1715,
"preview": "# mathjs\n\n精确的数字运算函数,解决 JavaScript 浮点数精度问题,支持链式调用。\n\n## API\n\n### mathjs\n\n#### Return\n\n| 参数 | 说明 |"
},
{
"path": "packages/docs/cn/src/ranuts/utils/md5.md",
"chars": 1151,
"preview": "# md5\n\nMD5 哈希函数,用于将字符串转换为 MD5 哈希值(十六进制字符串)。\n\n## API\n\n### md5\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/memoize.md",
"chars": 1395,
"preview": "# memoize\n\n记忆化函数,用于缓存函数执行结果。函数执行一次后,后续调用会直接返回缓存的结果,无需重新执行。\n\n## API\n\n### memoize\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/merge.md",
"chars": 1354,
"preview": "# merge\n\n合并对象,将第二个对象的属性合并到第一个对象中。\n\n## API\n\n### merge\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| "
},
{
"path": "packages/docs/cn/src/ranuts/utils/network_speed.md",
"chars": 1861,
"preview": "# networkSpeed\n\n通过多次请求测试当前网络的 ping 值和抖动(jitter)。\n\n## API\n\n### networkSpeed\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/noop.md",
"chars": 1091,
"preview": "# noop\n\n空函数,不执行任何操作。常用于作为默认回调函数或占位符。\n\n## API\n\n### noop\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| ------ | -------- | ----"
},
{
"path": "packages/docs/cn/src/ranuts/utils/ocr.md",
"chars": 6604,
"preview": "# OCR\n\n传入图片和对应的语言类型,返回图片中的文本。\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 |\n| --------- | ------------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/per_to_num.md",
"chars": 1145,
"preview": "# perToNum\n\n将百分比字符串转换为数字。\n\n## API\n\n### perToNum\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | ------------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/performance_time.md",
"chars": 1220,
"preview": "# performanceTime\n\n获取高精度时间戳,支持浏览器和 Node.js 环境。\n\n## API\n\n### performanceTime\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/querystring.md",
"chars": 1551,
"preview": "# querystring\n\n将对象转换为 URL 查询字符串。\n\n## API\n\n### querystring\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | "
},
{
"path": "packages/docs/cn/src/ranuts/utils/random_color.md",
"chars": 1289,
"preview": "# randomColor\n\n生成随机颜色对象。\n\n## API\n\n### randomColor\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| ------- | ------------ "
},
{
"path": "packages/docs/cn/src/ranuts/utils/random_string.md",
"chars": 1259,
"preview": "# randomString\n\n生成随机字符串,包含时间戳前缀,确保唯一性。\n\n## API\n\n### randomString\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/range.md",
"chars": 1172,
"preview": "# range\n\n限制数字在指定的最小值和最大值范围内。\n\n## API\n\n### range\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | ------------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/remove_class_to_element.md",
"chars": 1027,
"preview": "# removeClassToElement\n\n从指定的 DOM 元素移除 CSS 类名。\n\n## API\n\n### removeClassToElement\n\n#### Return\n\n无返回值(`void`)\n\n#### Paramet"
},
{
"path": "packages/docs/cn/src/ranuts/utils/remove_ghosting.md",
"chars": 1186,
"preview": "# removeGhosting\n\n移除拖拽事件的阴影(ghost image),创建透明的拖拽图标。\n\n## API\n\n### removeGhosting\n\n#### Return\n\n无返回值(`void`)\n\n#### Paramet"
},
{
"path": "packages/docs/cn/src/ranuts/utils/retain.md",
"chars": 950,
"preview": "# retain\n\n覆盖浏览器的后退事件,用于拦截和处理浏览器返回操作。\n\n## API\n\n### retain\n\n#### Return\n\n无返回值(`void`)\n\n#### Parameters\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/rgb_to_hex.md",
"chars": 1489,
"preview": "# rgbToHex\n\n将 RGB 值转换为十六进制颜色值。\n\n## API\n\n### rgbToHex\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | -----"
},
{
"path": "packages/docs/cn/src/ranuts/utils/script_on_load.md",
"chars": 1576,
"preview": "# scriptOnLoad\n\n动态插入 script 或 link 标签,并等待所有资源加载完成。\n\n## API\n\n### scriptOnLoad\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/set_attribute_by_global.md",
"chars": 1034,
"preview": "# setAttributeByGlobal\n\n给全局对象(`window` 或 `global`)添加属性。\n\n## API\n\n### setAttributeByGlobal\n\n#### Return\n\n无返回值(`void`)\n\n##"
},
{
"path": "packages/docs/cn/src/ranuts/utils/set_mime.md",
"chars": 1218,
"preview": "# setMime\n\n设置或更新 MIME 类型映射。\n\n## API\n\n### setMime\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/str2xml.md",
"chars": 1707,
"preview": "# str2Xml\n\n传入字符串,转成`xml`\n\n## API\n\n### Return\n\n| 参数 | 说明 | 类型 |\n| ------------- | ----"
},
{
"path": "packages/docs/cn/src/ranuts/utils/str_parse.md",
"chars": 1454,
"preview": "# strParse\n\n将字符串解析为对象,支持自定义分隔符和等号。\n\n## API\n\n### strParse\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n"
},
{
"path": "packages/docs/cn/src/ranuts/utils/sync_hook.md",
"chars": 1851,
"preview": "# SyncHook\n\n同步事件钩子类,用于实现发布-订阅模式。\n\n## API\n\n### SyncHook\n\n#### 主要方法\n\n| 方法 | 说明 | 返回值 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/task.md",
"chars": 2069,
"preview": "# 统计执行时间\n\n有的时候,我们需要统计一个函数的执行时间,用于分析性能。因此封装了`startTask`和`taskEnd`函数。同时介绍其他三种统计方法\n\n1. `new Date().getTime()`,\n2. `console."
},
{
"path": "packages/docs/cn/src/ranuts/utils/throttle.md",
"chars": 1792,
"preview": "# throttle\n\n节流函数,用于限制函数的执行频率。在指定的时间间隔内,函数最多执行一次。\n\n## API\n\n### throttle\n\n#### Return\n\n| 参数 | 说明 | 类型 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/time_format.md",
"chars": 1230,
"preview": "# timeFormat\n\n将时间秒数转换为 `HH:MM:SS` 或 `MM:SS` 格式的字符串。\n\n## API\n\n### timeFormat\n\n#### Return\n\n| 参数 | 说明 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/timestamp_to_time.md",
"chars": 1881,
"preview": "# timestampToTime\n\n将时间戳转换为 Date 对象,并添加 `format` 方法用于格式化日期。\n\n## API\n\n### timestampToTime\n\n#### Return\n\n| 参数 "
},
{
"path": "packages/docs/cn/src/ranuts/utils/to_string.md",
"chars": 763,
"preview": "# toString\n\n将值转换为字符串类型。\n\n## API\n\n### toString\n\n#### Return\n\n| 参数 | 说明 | 类型 |\n| -------- | ------------"
},
{
"path": "packages/docs/cn/src/ranuts/utils/totp.md",
"chars": 3444,
"preview": "# TOTP\n\n基于时间的一次性密码(Time-based One-Time Password)生成器,实现了 RFC 6238 标准。用于生成动态验证码,常用于双因素认证(2FA)场景。\n\n## API\n\n### TOTP.generat"
},
{
"path": "packages/docs/cn/src/ranuts/utils/transform_number.md",
"chars": 1588,
"preview": "# transformNumber\n\n将数字转换为带单位的格式化字符串,支持中英文单位。\n\n## API\n\n### transformNumber\n\n#### Return\n\n| 参数 | 说明 | 类型 "
}
]
// ... and 719 more files (download for full content)
About this extraction
This page contains the full source code of the chaxus/ran GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 919 files (53.0 MB), approximately 6.5M tokens, and a symbol index with 2452 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.