Skip to content

Commit af067e6

Browse files
authored
Merge pull request #57 from WebCoder49/typescript-declarations
Typescript declarations, and major changes to make closer to `<textarea>`
2 parents 179584e + 2913a19 commit af067e6

12 files changed

+649
-109
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.vscode
2-
debug.html
2+
debug.html
3+
debug/

README.md

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
# code-input
2+
23
![Click to Switch](https://img.shields.io/static/v1?label=&message=Click%20to%20Switch:%20&color=grey&style=for-the-badge)[![GitHub](https://img.shields.io/static/v1?label=&message=GitHub&color=navy&style=for-the-badge&logo=github)](https://github.com/WebCoder49/code-input)[![NPM](https://img.shields.io/static/v1?label=&message=NPM&color=red&style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@webcoder49/code-input)
34

45
[![View License](https://img.shields.io/github/license/webcoder49/code-input?style=for-the-badge)](LICENSE) [![View Releases](https://img.Shields.io/github/v/release/webcoder49/code-input?style=for-the-badge)](https://github.com/WebCoder49/code-input/releases) [![View the demo on CodePen](https://img.shields.io/static/v1?label=Demo&message=on%20CodePen&color=orange&logo=codepen&style=for-the-badge)](https://codepen.io/WebCoder49/details/jOypJOx)
56

6-
> ___Fully customisable syntax-highlighted textareas.___ [[🚀 View the Demo](https://codepen.io/WebCoder49/details/jOypJOx)]
7+
> ___Fully customisable, editable syntax-highlighted textareas that can be placed in any HTML form.___ [[🚀 View the Demo](https://codepen.io/WebCoder49/details/jOypJOx)]
78
89
![Using code-input with many different themes](https://user-images.githubusercontent.com/69071853/133924472-05edde5c-23e7-4350-a41b-5a74d2dc1a9a.gif)
9-
*This demonstration uses themes from [Prism.js](https://prismjs.com/) and [highlight.js](https://highlightjs.org/), two syntax-highlighting programs which work well and have compatibility built-in with code-input.*
10+
*This demonstration uses themes from [Prism.js](https://prismjs.com/) and [highlight.js](https://highlightjs.org/), two syntax-highlighting programs which work well with and have compatibility built-in with code-input.*
11+
12+
*A frontend JavaScript library, with:*<br/>
13+
[![TypeScript Bindings - Click to Use](https://img.shields.io/static/v1?label=TypeScript%20Bindings&message=Click%20to%20Use&style=for-the-badge&color=blue&logo=typescript&logoColor=white)](https://github.com/WebCoder49/code-input-for-typescript)
14+
15+
---
1016

1117
## What does it do?
1218
**`code-input`** lets you **turn any ordinary JavaScript syntax-highlighting theme and program into customisable syntax-highlighted textareas** using an HTML custom element. It uses vanilla CSS to superimpose a `textarea` on a `pre code` block, then handles indentations, scrolling and fixes any resulting bugs with JavaScript. To see how it works in more detail, please see [this CSS-Tricks article](https://css-tricks.com/creating-an-editable-textarea-that-supports-syntax-highlighted-code/ "Creating an Editable Textarea That Supports Syntax-Highlighted Code") I wrote.
1319

1420
## What are the advantages of using code-input, and what can it be used for?
1521
Unlike other front-end code-editor projects, the simplicity of how `code-input` works means it is **highly customisable**. As it is not a full-featured editor, you can **choose what features you want it to include, and use your favourite syntax-highlighting algorithms and themes**.
1622

17-
The `<code-input>` element works like a `<textarea>` and therefore **works in HTML5 forms and supports using the `value` and `placeholder` attributes, as well as the `onchange` event.**
23+
The `<code-input>` element works like a `<textarea>` and therefore **works in HTML5 forms and supports using the `name`, `value` and `placeholder` attributes, events like `onchange`, form resets, to name a few...** [(Demo)](https://codepen.io/WebCoder49/details/JjmqjZv)
24+
25+
`code-input` has also accumulated many **features in optional [plugins](./plugins/README.md)** from open-source contributions, allowing you to choose any features you want. If a feature you want is not present, [please open an issue / contribute it!](#contributing)
1826

1927
## 🚀 Getting Started With `code-input` (in 4 simple steps)
2028

29+
## [`code-input` also supports TypeScript (click)](https://github.com/WebCoder49/code-input-for-typescript)
30+
2131
`code-input` is designed to be **both easy to use and customisable**. Here's how to use it to create syntax-highlighted textareas:
2232

2333
### 1. Import `code-input`
@@ -42,8 +52,8 @@ From JSDelivr CDN (click)
4252

4353
```html
4454
<!--In the <head>-->
45-
<script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@1.3/code-input.min.js"></script>
46-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@1.3/code-input.min.css">
55+
<script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.0/code-input.min.js"></script>
56+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.0/code-input.min.css">
4757
```
4858
</details>
4959

@@ -62,7 +72,7 @@ The next step is to set up a `template` to link `code-input` to your syntax-high
6272

6373
- *Custom:*
6474
```js
65-
codeInput.registerTemplate("syntax-highlighted", codeInput.templates.custom(
75+
codeInput.registerTemplate("syntax-highlighted", new codeInput.Template(
6676
function(result_element) { /* Highlight function - with `pre code` code element */
6777
/* Highlight code in result_element - code is already escaped so it doesn't become HTML */
6878
},
@@ -105,8 +115,14 @@ Now that you have registered a template, you can use the custom `<code-input>` e
105115
```
106116
*or*
107117
```HTML
108-
<code-input lang="HTML" placeholder="Type code here" value="<a href='https://github.com/WebCoder49/code-input'>code-input</a>" template="syntax-highlighted" onchange="console.log('Your code is', this.value)"></code-input>
118+
<code-input lang="HTML" placeholder="Type code here" template="syntax-highlighted" onchange="console.log('Your code is', this.value)">&lt; href='https://github.com/WebCoder49/code-input'>code-input&lt;/a></code-input>
109119
```
110120

111121
## Contributing
112122
If you have any features you would like to add to `code-input`, or have found any bugs, please [open an issue](https://github.com/WebCoder49/code-input/issues) or [fork and submit a pull request](https://github.com/WebCoder49/code-input/fork)! All contributions to this open-source project would be greatly appreciated.
123+
124+
125+
|[![Contributors](https://contrib.rocks/image?repo=WebCoder49%2Fcode-input)](https://github.com/WebCoder49/code-input/graphs/contributors)|
126+
|---|
127+
|...have contributed pull requests so far.|
128+
|(source: [contrib.rocks](https://contrib.rocks))|

code-input.css

+14
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, co
3333
width: calc(100% - var(--padding, 16px) * 2);
3434
height: calc(100% - var(--padding, 16px) * 2);
3535
}
36+
37+
code-input:not(.code-input_loaded) {
38+
margin: 0px!important;
39+
margin-bottom: calc(-1 * var(--padding, 16px))!important;
40+
padding: var(--padding, 16px)!important;
41+
border: 0;
42+
}
43+
3644
code-input:not(.code-input_pre-element-styled) pre, code-input.code-input_pre-element-styled pre code {
3745
/* Remove all margin and padding from others */
3846
margin: 0px!important;
@@ -67,6 +75,12 @@ code-input pre {
6775
z-index: 0;
6876
}
6977

78+
code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) textarea {
79+
opacity: 0;
80+
}
81+
code-input:not(.code-input_loaded)::after {
82+
color: #ccc;
83+
}
7084

7185
/* Make textarea almost completely transparent */
7286

code-input.d.ts

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
export as namespace codeInput;
2+
3+
/**
4+
* Plugins are imported from the plugins folder. They will then
5+
* provide custom extra functionality to code-input elements.
6+
*/
7+
export abstract class Plugin {
8+
/**
9+
* Create a Plugin
10+
*
11+
* @param {Array<string>} observedAttributes - The HTML attributes to watch for this plugin, and report any
12+
* modifications to the `codeInput.Plugin.attributeChanged` method.
13+
*/
14+
constructor(observedAttributes: Array<string>)
15+
/**
16+
* Runs before code is highlighted.
17+
* @param {codeInput.CodeInput} codeInput - The codeInput element
18+
*/
19+
beforeHighlight(codeInput: CodeInput): void
20+
/**
21+
* Runs after code is highlighted.
22+
* @param {codeInput.CodeInput} codeInput - The codeInput element
23+
*/
24+
afterHighlight(codeInput: CodeInput): void
25+
/**
26+
* Runs before elements are added into a code-input element.
27+
* @param {codeInput.CodeInput} codeInput - The codeInput element
28+
*/
29+
beforeElementsAdded(codeInput: CodeInput): void
30+
/**
31+
* Runs after elements are added into a code-input element (useful for adding events to the textarea).
32+
* @param {codeInput.CodeInput} codeInput - The codeInput element
33+
*/
34+
afterElementsAdded(codeInput: CodeInput): void
35+
/**
36+
* Runs when an attribute of a code-input element is changed (you must add the attribute name to `codeInput.Plugin.observedAttributes` first).
37+
* @param {codeInput.CodeInput} codeInput - The codeInput element
38+
* @param {string} name - The name of the attribute
39+
* @param {string} oldValue - The value of the attribute before it was changed
40+
* @param {string} newValue - The value of the attribute after it is changed
41+
*/
42+
attributeChanged(codeInput: CodeInput, name: string, oldValue: string, newValue: string): void
43+
/**
44+
* The HTML attributes to watch for this plugin, and report any
45+
* modifications to the `codeInput.Plugin.attributeChanged` method.
46+
*/
47+
observedAttributes: Array<string>
48+
}
49+
50+
/**
51+
* Before using any plugin in this namespace, please ensure you import its JavaScript
52+
* files (in the plugins folder), or continue to get a more detailed error in the developer
53+
* console.
54+
*
55+
* Where plugins are stored, after they are imported. The plugin
56+
* file assigns them a space in this object.
57+
* For adding completely new syntax-highlighting algorithms, please see `codeInput.templates`.
58+
*
59+
* Key - plugin name
60+
*
61+
* Value - plugin object
62+
* @type {Object}
63+
*/
64+
export namespace plugins {
65+
/**
66+
* JavaScript example of a plugin, which brings extra,
67+
* non-central optional functionality to code-input.
68+
* Instances of plugins can be passed in in an array
69+
* to the `plugins` argument when registering a template,
70+
* for example like this:
71+
* ```javascript
72+
* codeInput.registerTemplate("syntax-highlighted", codeInput.templates.hljs(hljs, [new codeInput.plugins.Test()]));
73+
* ```
74+
*/
75+
class Test extends Plugin {
76+
constructor();
77+
}
78+
79+
/**
80+
* Display a popup under the caret using the text in the code-input element. This works well with autocomplete suggestions.
81+
* Files: autocomplete.js / autocomplete.css
82+
*/
83+
class Autocomplete extends Plugin {
84+
/**
85+
* Pass in a function to display the popup that takes in (popup element, textarea, textarea.selectionEnd).
86+
* @param {function} updatePopupCallback a function to display the popup that takes in (popup element, textarea, textarea.selectionEnd).
87+
*/
88+
constructor(updatePopupCallback: (popupElem: HTMLElement, textarea: HTMLTextAreaElement, selectionEnd: number) => void);
89+
}
90+
91+
/**
92+
* Autodetect the language live and change the `lang` attribute using the syntax highlighter's
93+
* autodetect capabilities. Works with highlight.js only.
94+
* Files: autodetect.js
95+
*/
96+
class Autodetect extends Plugin {
97+
constructor();
98+
}
99+
100+
/**
101+
* Debounce the update and highlighting function
102+
* https://medium.com/@jamischarles/what-is-debouncing-2505c0648ff1
103+
* Files: debounce-update.js
104+
*/
105+
class DebounceUpdate extends Plugin {
106+
/**
107+
* Create a debounced update plugin to pass into a template.
108+
* @param {Number} delayMs Delay, in ms, to wait until updating the syntax highlighting
109+
*/
110+
constructor(delayMs: number);
111+
}
112+
113+
/**
114+
* Adds indentation using the `Tab` key, and auto-indents after a newline, as well as making it
115+
* possible to indent/unindent multiple lines using Tab/Shift+Tab
116+
* Files: indent.js
117+
*/
118+
class Indent extends Plugin {
119+
constructor();
120+
}
121+
122+
/**
123+
* Render special characters and control characters as a symbol with their hex code.
124+
* Files: special-chars.js, special-chars.css
125+
*/
126+
class SpecialChars extends Plugin {
127+
/**
128+
* Create a special characters plugin instance.
129+
* Default = covers many non-renderable ASCII characters.
130+
* @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code
131+
* @param {Boolean} inheritTextColor If `colorInSpecialChars` is false, forces the color of the hex code to inherit from syntax highlighting. Otherwise, the base color of the `pre code` element is used to give contrast to the small characters.
132+
* @param {RegExp} specialCharRegExp The regular expression which matches special characters
133+
*/
134+
constructor(colorInSpecialChars?: boolean, inheritTextColor?: boolean, specialCharRegExp?: RegExp);
135+
}
136+
}
137+
138+
/**
139+
* Register a plugin class under `codeInput.plugins`.
140+
* @param {string} pluginName The identifier of the plugin: if it is `"foo"`, `new codeInput.plugins.foo(`...`)` will instantiate it, etc.
141+
* @param {Object} pluginClass The class of the plugin, created with `class extends codeInput.plugin {`...`}`
142+
*/
143+
export function registerPluginClass(pluginName: string, pluginClass: Object): void;
144+
145+
/**
146+
* Please see `codeInput.templates.prism` or `codeInput.templates.hljs`.
147+
* Templates are used in `<code-input>` elements and once registered with
148+
* `codeInput.registerTemplate` will be in charge of the highlighting
149+
* algorithm and settings for all code-inputs with a `template` attribute
150+
* matching the registered name.
151+
*/
152+
export class Template {
153+
/**
154+
* **When `includeCodeInputInHighlightFunc` is `false`, `highlight` takes only the `<pre><code>` element as a parameter.**
155+
*
156+
* Constructor to create a custom template instance. Pass this into `codeInput.registerTemplate` to use it.
157+
* I would strongly recommend using the built-in simpler template `codeInput.templates.prism` or `codeInput.templates.hljs`.
158+
* @param {Function} highlight - a callback to highlight the code, that takes an HTML `<code>` element inside a `<pre>` element as a parameter
159+
* @param {boolean} preElementStyled - is the `<pre>` element CSS-styled as well as the `<code>` element? If true, `<pre>` element's scrolling is synchronised; if false, `<code>` element's scrolling is synchronised.
160+
* @param {boolean} isCode - is this for writing code? If true, the code-input's lang HTML attribute can be used, and the `<code>` element will be given the class name 'language-[lang attribute's value]'.
161+
* @param {false} includeCodeInputInHighlightFunc - Setting this to true passes the `<code-input>` element as a second argument to the highlight function.
162+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.Plugin`
163+
* @returns template object
164+
*/
165+
constructor(highlight?: (code: HTMLElement) => void, preElementStyled?: boolean, isCode?: boolean, includeCodeInputInHighlightFunc?: false, plugins?: Plugin[])
166+
/**
167+
* **When `includeCodeInputInHighlightFunc` is `true`, `highlight` takes two parameters: the `<pre><code>` element, and the `<code-input>` element.**
168+
*
169+
* Constructor to create a custom template instance. Pass this into `codeInput.registerTemplate` to use it.
170+
* I would strongly recommend using the built-in simpler template `codeInput.templates.prism` or `codeInput.templates.hljs`.
171+
* @param {Function} highlight - a callback to highlight the code, that takes an HTML `<code>` element inside a `<pre>` element as a parameter
172+
* @param {boolean} preElementStyled - is the `<pre>` element CSS-styled as well as the `<code>` element? If true, `<pre>` element's scrolling is synchronised; if false, `<code>` element's scrolling is synchronised.
173+
* @param {boolean} isCode - is this for writing code? If true, the code-input's lang HTML attribute can be used, and the `<code>` element will be given the class name 'language-[lang attribute's value]'.
174+
* @param {true} includeCodeInputInHighlightFunc - Setting this to true passes the `<code-input>` element as a second argument to the highlight function.
175+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.Plugin`
176+
* @returns template object
177+
*/
178+
constructor(highlight?: (code: HTMLElement, codeInput: CodeInput) => void, preElementStyled?: boolean, isCode?: boolean, includeCodeInputInHighlightFunc?: true, plugins?: Plugin[])
179+
highlight: Function
180+
preElementStyled: boolean
181+
isCode: boolean
182+
includeCodeInputInHighlightFunc: boolean
183+
plugins: Plugin[]
184+
}
185+
186+
/**
187+
* Shortcut functions for creating templates.
188+
* Each code-input element has a template attribute that
189+
* tells it which template to use.
190+
* Each template contains functions and preferences that
191+
* run the syntax-highlighting and let code-input control
192+
* the highlighting.
193+
*
194+
* For creating a custom template from scratch, please
195+
* use `new codeInput.Template(...)`.
196+
*
197+
* For adding small pieces of functionality, please see `codeInput.plugins`.
198+
*/
199+
export namespace templates {
200+
/**
201+
* Constructor to create a template that uses Prism.js syntax highlighting (https://prismjs.com/)
202+
* @param {Object} prism Import Prism.js, then after that import pass the `Prism` object as this parameter.
203+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
204+
* @returns template object
205+
*/
206+
function prism(prism: Object, plugins?: Plugin[]): Template
207+
/**
208+
* Constructor to create a template that uses highlight.js syntax highlighting (https://highlightjs.org/)
209+
* @param {Object} hljs Import highlight.js, then after that import pass the `hljs` object as this parameter.
210+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
211+
* @returns template object
212+
*/
213+
function hljs(hljs: Object, plugins?: Plugin[]): Template
214+
/**
215+
* Constructor to create a proof-of-concept template that gives a message if too many characters are typed.
216+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
217+
* @returns template object
218+
*/
219+
function characterLimit(plugins?: Plugin[]): Template
220+
/**
221+
* Constructor to create a proof-of-concept template that shows text in a repeating series of colors.
222+
* @param {string[]} rainbowColors - An array of CSS colors, in the order each color will be shown
223+
* @param {string} delimiter - The character used to split up parts of text where each part is a different colour (e.g. "" = characters, " " = words)
224+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
225+
* @returns template object
226+
*/
227+
function rainbowText(rainbowColors?: string[], delimiter?: string, plugins?: Plugin[]): Template
228+
}
229+
230+
/**
231+
* A `<code-input>` element, an instance of an `HTMLElement`, and the result
232+
* of `document.createElement("code-input")`.
233+
*/
234+
export class CodeInput extends HTMLElement { }
235+
236+
/**
237+
* Register a template so code-input elements with a template attribute that equals the templateName will use the template.
238+
* See `codeInput.templates` for constructors to create templates.
239+
* @param {string} templateName - the name to register the template under
240+
* @param {Object} template - a Template object instance - see `codeInput.templates`
241+
*/
242+
export function registerTemplate(templateName: string, template: Template): void;

0 commit comments

Comments
 (0)