Full Code of CarterLi/vue3-ace-editor for AI

master 68e4aef2e31b cached
9 files
18.2 KB
4.9k tokens
38 symbols
1 requests
Download .txt
Repository: CarterLi/vue3-ace-editor
Branch: master
Commit: 68e4aef2e31b
Files: 9
Total size: 18.2 KB

Directory structure:
gitextract_hmq5fgcx/

├── .gitignore
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── types.d.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
/node_modules
/*.log
/demo-source


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Carter Li

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: README.md
================================================
vue3-ace-editor
====================


[![npm](https://img.shields.io/npm/v/vue3-ace-editor.svg)](https://www.npmjs.com/package/vue3-ace-editor)


A packaging of [ace](https://ace.c9.io/). Inspired by [vue2-ace-editor](https://github.com/chairuosen/vue2-ace-editor), but supports [Vue 3](https://github.com/vuejs/vue-next)

## Install

`ace-builds` must be installed alongside `vue3-ace-editor` using your favorite package manager.

* npm i vue3-ace-editor ace-builds
* yarn add vue3-ace-editor ace-builds
* pnpm i vue3-ace-editor ace-builds

## Usage

```vue
<script setup>
    import { ref } from 'vue';
    import { VAceEditor } from 'vue3-ace-editor';
    import 'ace-builds/src-noconflict/mode-json'; // Load the language definition file used below
    import 'ace-builds/src-noconflict/theme-chrome'; // Load the theme definition file used below

    const content = ref(JSON.stringify({ message: 'Hello Ace' }));
</script>
<template>
    <v-ace-editor
        v-model:value="content"
        lang="json"
        theme="chrome"
        style="height: 300px" />
</template>
```

Property `v-model:value` is required. `<v-ace-editor>` has no height by default. Its height must be specified manually, or set both `min-lines` and `max-lines` to make the editor's height auto-grow.

Property `lang`, `theme` is same as [ace-editor's doc](https://github.com/ajaxorg/ace)


## Load modes and themes (**REQUIRED**)

Using of `ace-builds/webpack-resolver` is removed due to bug https://github.com/CarterLi/vue3-ace-editor/issues/3. You **MUST** import `theme` and `mode` yourself. eg.

```js
// You MUST make sure that `ace-builds` or `vue3-ace-editor` (which imports `ace-builds` internally) is loaded before importing `mode` and `theme`
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-chrome';
```

To use dynamic loading to avoid first-load overhead

```js
import ace from 'ace-builds';

import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url';
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl);

import themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url';
ace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl);
```

Note that to make search box (`Ctrl+F` or `Command+F`) work, `ext-searchbox` must also be loaded.

```js
import extSearchboxUrl from 'ace-builds/src-noconflict/ext-searchbox?url';
ace.config.setModuleUrl('ace/ext/searchbox', extSearchboxUrl);
```

Find all supported themes and modes in `node_modules/ace-builds/src-noconflict`

## Deferences with [vue2-ace-editor](https://github.com/chairuosen/vue2-ace-editor)

1. This component uses [ace-builds](https://www.npmjs.com/package/ace-builds) directly, instead of the outdated wrapper [brace](https://www.npmjs.com/package/brace)
1. DOM size changes are detected automatically using [ResizeObserver](resize-observer-polyfill), thus no `width` / `height` props needed.
1. For easier usage, more props / events added / emitted.
    1. Prop `readonly`: This Boolean attribute indicates that the user cannot modify the value of the control.
    1. Prop `placeholder`: A hint to the user of what can be entered in the control.
    1. Prop `wrap`: Indicates whether the control wraps text.
    1. Prop `printMargin`: A short hand of `showPrintMargin` and `printMarginColumn`.
    1. Prop `minLines` and `maxLines`: Specifiy the minimum and maximum number of lines.
    1. All ace events emitted. Docs can be found here: <https://ace.c9.io/#api=editor&nav=api>
    1. Some commonly used methods `focus`, `blur`, `selectAll` provided as shortcuts.

## Get raw ace instance

Use `getAceInstance`

```vue
<script setup>
    import { ref, onMounted } from 'vue';

    const aceRef = ref(null);

    onMounted(() => {
        console.log(aceRef.value.getAceInstance());
    })
</script>
<template>
    <v-ace-editor ref="aceRef" v-bind="..." />
</template>
```

`@init` is provided for `vue2-ace-editor` compatibility only but is not recommanded to use.

## Enable syntax checking

To enable syntax checking, module `ace/mode/lang_worker` must be registered, and option `useWorker: true` must be set.

Take JSON for example:

```ts
import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'; // For vite

import workerJsonUrl from 'file-loader?esModule=false!ace-builds/src-noconflict/worker-json.js'; // For webpack / vue-cli

ace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl);
```

```html
<v-ace-editor v-model:value="json" lang="json" :options="{ useWorker: true }" />
```

See also https://github.com/CarterLi/vue3-ace-editor/issues/3#issuecomment-768190528 to load the worker file from CDN

## Minimal example using vite

* Preview: <https://carterli.github.io/vue3-ace-editor/>
* Source: <https://github.com/CarterLi/vue3-ace-editor/tree/gh-pages/demo-source>

## Use it with Nuxt

Since ace doesn't support SSR, using it with Nuxt can be tricky. You must make sure that `ace` related things are loaded only at client side.

```vue
<script setup>
import { markRaw, onMounted, ref } from 'vue';

const VAceEditor = ref('div'); // Stores dynamic loaded component. Before `vue3-ace-editor` is loaded, a `div` is used as a placeholder
const content = ref(JSON.stringify({ platform: 'Nuxt', env: 'SSR' }, null, 2));

onMounted(async () => { // onMounted is a client-only lifecycle hook
  await import('ace-builds'); // To importing things in a function, dynamic import must be used
  await import('ace-builds/src-noconflict/mode-json');
  await import('ace-builds/src-noconflict/theme-chrome');
  VAceEditor.value = markRaw((await import('vue3-ace-editor')).VAceEditor);
});
</script>
<template>
  <div>
    <component :is="VAceEditor" v-model:value="content" lang="json" theme="chrome" style="height: 400px" />
    <textarea :value="content" style="width: 100%; margin-top: 10px" rows="5" />
  </div>
</template>
```

Full example: <https://stackblitz.com/edit/github-oeoxgm?file=app.vue>

## LICENSE

MIT


================================================
FILE: index.d.ts
================================================
import { type Ace } from 'ace-builds';
import type { VAceEditorInstance } from './types';
export declare const VAceEditor: import("vue").DefineComponent<{
    value: {
        type: StringConstructor;
        required: true;
    };
    lang: {
        type: StringConstructor;
        default: string;
    };
    theme: {
        type: StringConstructor;
        default: string;
    };
    options: ObjectConstructor;
    placeholder: StringConstructor;
    readonly: BooleanConstructor;
    wrap: BooleanConstructor;
    printMargin: {
        type: (BooleanConstructor | NumberConstructor)[];
        default: boolean;
    };
    minLines: NumberConstructor;
    maxLines: NumberConstructor;
}, unknown, unknown, {}, {
    focus(this: VAceEditorInstance): void;
    blur(this: VAceEditorInstance): void;
    selectAll(this: VAceEditorInstance): void;
    getAceInstance(this: VAceEditorInstance): Ace.Editor;
}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, string[], string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
    value: {
        type: StringConstructor;
        required: true;
    };
    lang: {
        type: StringConstructor;
        default: string;
    };
    theme: {
        type: StringConstructor;
        default: string;
    };
    options: ObjectConstructor;
    placeholder: StringConstructor;
    readonly: BooleanConstructor;
    wrap: BooleanConstructor;
    printMargin: {
        type: (BooleanConstructor | NumberConstructor)[];
        default: boolean;
    };
    minLines: NumberConstructor;
    maxLines: NumberConstructor;
}>> & {
    [x: `on${Capitalize<string>}`]: ((...args: any[]) => any) | undefined;
}, {
    lang: string;
    theme: string;
    readonly: boolean;
    wrap: boolean;
    printMargin: number | boolean;
}, {}>;


================================================
FILE: index.js
================================================
import ace from 'ace-builds';
import { capitalize, defineComponent, markRaw, h } from 'vue';
import ResizeObserver from 'resize-observer-polyfill';
const Events = [
    'blur',
    'input',
    'change',
    'changeSelection',
    'changeSelectionStyle',
    'changeSession',
    'copy',
    'focus',
    'paste',
];
export const VAceEditor = defineComponent({
    name: 'VAceEditor',
    props: {
        value: {
            type: String,
            required: true,
        },
        lang: {
            type: String,
            default: 'text',
        },
        theme: {
            type: String,
            default: 'chrome',
        },
        options: Object,
        placeholder: String,
        readonly: Boolean,
        wrap: Boolean,
        printMargin: {
            type: [Boolean, Number],
            default: true,
        },
        minLines: Number,
        maxLines: Number,
    },
    emits: ['update:value', 'init', ...Events],
    render() {
        return h('div');
    },
    mounted() {
        const editor = this._editor = markRaw(ace.edit(this.$el, {
            placeholder: this.placeholder,
            readOnly: this.readonly,
            value: this.value,
            mode: 'ace/mode/' + this.lang,
            theme: 'ace/theme/' + this.theme,
            wrap: this.wrap,
            printMargin: this.printMargin,
            useWorker: false,
            minLines: this.minLines,
            maxLines: this.maxLines,
            ...this.options,
        }));
        this._contentBackup = this.value;
        this._isSettingContent = false;
        editor.on('change', () => {
            // ref: https://github.com/CarterLi/vue3-ace-editor/issues/11
            if (this._isSettingContent)
                return;
            const content = editor.getValue();
            this._contentBackup = content;
            this.$emit('update:value', content);
        });
        Events.forEach(x => {
            const eventName = 'on' + capitalize(x);
            if (typeof this.$.vnode.props[eventName] === 'function') {
                editor.on(x, this.$emit.bind(this, x));
            }
        });
        this._ro = new ResizeObserver(() => editor.resize());
        this._ro.observe(this.$el);
        this.$emit('init', editor);
    },
    beforeUnmount() {
        var _a, _b;
        (_a = this._ro) === null || _a === void 0 ? void 0 : _a.disconnect();
        (_b = this._editor) === null || _b === void 0 ? void 0 : _b.destroy();
    },
    methods: {
        focus() {
            this._editor.focus();
        },
        blur() {
            this._editor.blur();
        },
        selectAll() {
            this._editor.selectAll();
        },
        getAceInstance() {
            return this._editor;
        },
    },
    watch: {
        value(val) {
            if (this._contentBackup !== val) {
                try {
                    this._isSettingContent = true;
                    this._editor.setValue(val, 1);
                }
                finally {
                    this._isSettingContent = false;
                }
                this._contentBackup = val;
            }
        },
        theme(val) {
            this._editor.setTheme('ace/theme/' + val);
        },
        options(val) {
            this._editor.setOptions(val);
        },
        readonly(val) {
            this._editor.setReadOnly(val);
        },
        placeholder(val) {
            this._editor.setOption('placeholder', val);
        },
        wrap(val) {
            this._editor.setWrapBehavioursEnabled(val);
        },
        printMargin(val) {
            this._editor.setOption('printMargin', val);
        },
        lang(val) {
            this._editor.setOption('mode', 'ace/mode/' + val);
        },
        minLines(val) {
            this._editor.setOption('minLines', val);
        },
        maxLines(val) {
            this._editor.setOption('maxLines', val);
        },
    }
});
//# sourceMappingURL=index.js.map

================================================
FILE: index.ts
================================================
import ace, { type Ace } from 'ace-builds';
import { capitalize, defineComponent, markRaw, h } from 'vue';
import ResizeObserver from 'resize-observer-polyfill';

import type { VAceEditorInstance } from './types';

const Events = [
  'blur',
  'input',
  'change',
  'changeSelection',
  'changeSelectionStyle',
  'changeSession',
  'copy',
  'focus',
  'paste',
];

export const VAceEditor = defineComponent({
  name: 'VAceEditor',
  props: {
    value: {
      type: String,
      required: true,
    },
    lang: {
      type: String,
      default: 'text',
    },
    theme: {
      type: String,
      default: 'chrome',
    },
    options: Object,
    placeholder: String,
    readonly: Boolean,
    wrap: Boolean,
    printMargin: {
      type: [Boolean, Number],
      default: true,
    },
    minLines: Number,
    maxLines: Number,
  },
  emits: ['update:value', 'init', ...Events],
  render(this: VAceEditorInstance) {
    return h('div');
  },
  mounted(this: VAceEditorInstance) {
    const editor = this._editor = markRaw(ace.edit(this.$el, {
      placeholder: this.placeholder,
      readOnly: this.readonly,
      value: this.value,
      mode: 'ace/mode/' + this.lang,
      theme: 'ace/theme/' + this.theme,
      wrap: this.wrap,
      printMargin: this.printMargin,
      useWorker: false,
      minLines: this.minLines,
      maxLines: this.maxLines,
      ...this.options,
    }));
    this._contentBackup = this.value;
    this._isSettingContent = false;
    editor.on('change', () => {
      // ref: https://github.com/CarterLi/vue3-ace-editor/issues/11
      if (this._isSettingContent) return;
      const content = editor.getValue();
      this._contentBackup = content;
      this.$emit('update:value', content);
    });
    Events.forEach(x => {
      const eventName = 'on' + capitalize(x);
      if (typeof this.$.vnode.props![eventName] === 'function') {
        editor.on(x as any, this.$emit.bind(this, x));
      }
    });
    this._ro = new ResizeObserver(() => editor.resize());
    this._ro.observe(this.$el);
    this.$emit('init', editor);
  },
  beforeUnmount(this: VAceEditorInstance) {
    this._ro?.disconnect();
    this._editor?.destroy();
  },
  methods: {
    focus(this: VAceEditorInstance) {
      this._editor.focus();
    },
    blur(this: VAceEditorInstance) {
      this._editor.blur();
    },
    selectAll(this: VAceEditorInstance) {
      this._editor.selectAll();
    },
    getAceInstance(this: VAceEditorInstance) {
      return this._editor;
    },
  },
  watch: {
    value(this: VAceEditorInstance, val: string) {
      if (this._contentBackup !== val) {
        try {
          this._isSettingContent = true;
          this._editor.setValue(val, 1);
        } finally {
          this._isSettingContent = false;
        }
        this._contentBackup = val;
      }
    },
    theme(this: VAceEditorInstance, val: string) {
      this._editor.setTheme('ace/theme/' + val);
    },
    options(this: VAceEditorInstance, val: Partial<Ace.EditorOptions>) {
      this._editor.setOptions(val);
    },
    readonly(this: VAceEditorInstance, val: boolean) {
      this._editor.setReadOnly(val);
    },
    placeholder(this: VAceEditorInstance, val: string) {
      this._editor.setOption('placeholder', val);
    },
    wrap(this: VAceEditorInstance, val: boolean) {
      this._editor.setWrapBehavioursEnabled(val);
    },
    printMargin(this: VAceEditorInstance, val: boolean | number) {
      this._editor.setOption('printMargin', val);
    },
    lang(this: VAceEditorInstance, val: string) {
      this._editor.setOption('mode', 'ace/mode/' + val);
    },
    minLines(this: VAceEditorInstance, val: number) {
      this._editor.setOption('minLines', val);
    },
    maxLines(this: VAceEditorInstance, val: number) {
      this._editor.setOption('maxLines', val);
    },
  }
});


================================================
FILE: package.json
================================================
{
  "name": "vue3-ace-editor",
  "version": "2.2.4",
  "description": "Like vue2-ace-editor but more functional and supports Vue 3",
  "main": "index.js",
  "module": "index.js",
  "type": "module",
  "types": "index.d.ts",
  "repository": "git@github.com:CarterLi/vue3-ace-editor.git",
  "author": "李通洲 <zhangsongcui@live.cn>",
  "license": "MIT",
  "scripts": {
    "build": "tsc -p ."
  },
  "dependencies": {
    "resize-observer-polyfill": "^1.5.1"
  },
  "peerDependencies": {
    "ace-builds": "*",
    "vue": "^3"
  },
  "devDependencies": {
    "typescript": "^5.2.2"
  }
}


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es2019",
    "module": "esnext",
    "strict": true,
    "importHelpers": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "declaration": true,
    "baseUrl": "./",
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ]
  },
  "exclude": [
    "node_modules"
  ]
}


================================================
FILE: types.d.ts
================================================
import { ComponentPublicInstance } from 'vue';
import type { Ace } from 'ace-builds';

export interface VAceEditorPrivate {
  _editor: Ace.Editor;
  _contentBackup: string;
  _isSettingContent: boolean;
  _ro: ResizeObserver;
}

export interface VAceEditorProps {
  readonly value: string;
  readonly lang: string;
  readonly theme: string;
  readonly options: Partial<Ace.EditorOptions>;
  readonly placeholder: string;
  readonly readonly: boolean;
  readonly wrap: boolean;
  readonly printMargin: boolean | number;
  readonly minLines: number;
  readonly maxLines: number;
}

export interface VAceEditorMethods {
  focus(): void;
  blur(): void;
  selectAll(): void;
  getAceInstance(): Ace.Editor;
}

export interface VAceEditorInstance extends
  ComponentPublicInstance,
  VAceEditorPrivate,
  VAceEditorProps,
  VAceEditorMethods {}
Download .txt
gitextract_hmq5fgcx/

├── .gitignore
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── types.d.ts
Download .txt
SYMBOL INDEX (38 symbols across 3 files)

FILE: index.js
  method render (line 42) | render() {
  method mounted (line 45) | mounted() {
  method beforeUnmount (line 79) | beforeUnmount() {
  method focus (line 85) | focus() {
  method blur (line 88) | blur() {
  method selectAll (line 91) | selectAll() {
  method getAceInstance (line 94) | getAceInstance() {
  method value (line 99) | value(val) {
  method theme (line 111) | theme(val) {
  method options (line 114) | options(val) {
  method readonly (line 117) | readonly(val) {
  method placeholder (line 120) | placeholder(val) {
  method wrap (line 123) | wrap(val) {
  method printMargin (line 126) | printMargin(val) {
  method lang (line 129) | lang(val) {
  method minLines (line 132) | minLines(val) {
  method maxLines (line 135) | maxLines(val) {

FILE: index.ts
  method render (line 46) | render(this: VAceEditorInstance) {
  method mounted (line 49) | mounted(this: VAceEditorInstance) {
  method beforeUnmount (line 82) | beforeUnmount(this: VAceEditorInstance) {
  method focus (line 87) | focus(this: VAceEditorInstance) {
  method blur (line 90) | blur(this: VAceEditorInstance) {
  method selectAll (line 93) | selectAll(this: VAceEditorInstance) {
  method getAceInstance (line 96) | getAceInstance(this: VAceEditorInstance) {
  method value (line 101) | value(this: VAceEditorInstance, val: string) {
  method theme (line 112) | theme(this: VAceEditorInstance, val: string) {
  method options (line 115) | options(this: VAceEditorInstance, val: Partial<Ace.EditorOptions>) {
  method readonly (line 118) | readonly(this: VAceEditorInstance, val: boolean) {
  method placeholder (line 121) | placeholder(this: VAceEditorInstance, val: string) {
  method wrap (line 124) | wrap(this: VAceEditorInstance, val: boolean) {
  method printMargin (line 127) | printMargin(this: VAceEditorInstance, val: boolean | number) {
  method lang (line 130) | lang(this: VAceEditorInstance, val: string) {
  method minLines (line 133) | minLines(this: VAceEditorInstance, val: number) {
  method maxLines (line 136) | maxLines(this: VAceEditorInstance, val: number) {

FILE: types.d.ts
  type VAceEditorPrivate (line 4) | interface VAceEditorPrivate {
  type VAceEditorProps (line 11) | interface VAceEditorProps {
  type VAceEditorMethods (line 24) | interface VAceEditorMethods {
  type VAceEditorInstance (line 31) | interface VAceEditorInstance extends
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (20K chars).
[
  {
    "path": ".gitignore",
    "chars": 34,
    "preview": "/node_modules\n/*.log\n/demo-source\n"
  },
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2020 Carter Li\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 5958,
    "preview": "vue3-ace-editor\n====================\n\n\n[![npm](https://img.shields.io/npm/v/vue3-ace-editor.svg)](https://www.npmjs.com/"
  },
  {
    "path": "index.d.ts",
    "chars": 1900,
    "preview": "import { type Ace } from 'ace-builds';\nimport type { VAceEditorInstance } from './types';\nexport declare const VAceEdito"
  },
  {
    "path": "index.js",
    "chars": 3997,
    "preview": "import ace from 'ace-builds';\nimport { capitalize, defineComponent, markRaw, h } from 'vue';\nimport ResizeObserver from "
  },
  {
    "path": "index.ts",
    "chars": 3844,
    "preview": "import ace, { type Ace } from 'ace-builds';\nimport { capitalize, defineComponent, markRaw, h } from 'vue';\nimport Resize"
  },
  {
    "path": "package.json",
    "chars": 583,
    "preview": "{\n  \"name\": \"vue3-ace-editor\",\n  \"version\": \"2.2.4\",\n  \"description\": \"Like vue2-ace-editor but more functional and supp"
  },
  {
    "path": "tsconfig.json",
    "chars": 463,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es2019\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"importHelpers\": true,\n"
  },
  {
    "path": "types.d.ts",
    "chars": 840,
    "preview": "import { ComponentPublicInstance } from 'vue';\nimport type { Ace } from 'ace-builds';\n\nexport interface VAceEditorPrivat"
  }
]

About this extraction

This page contains the full source code of the CarterLi/vue3-ace-editor GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (18.2 KB), approximately 4.9k tokens, and a symbol index with 38 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.

Copied to clipboard!