@@ -6,14 +6,44 @@ var codeInput = {
66 usedTemplates : {
77 } ,
88 defaultTemplate : undefined ,
9+ plugins : { // Import a plugin from the plugins folder and it will be saved here.
10+ } ,
11+ Plugin : class {
12+ /* Runs before code is highlighted; Params: codeInput element) */
13+ beforeHighlight ( codeInput ) { }
14+ /* Runs after code is highlighted; Params: codeInput element) */
15+ afterHighlight ( codeInput ) { }
16+ /* Runs before elements are added into a `code-input`; Params: codeInput element) */
17+ beforeElementsAdded ( codeInput ) { }
18+ /* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
19+ afterElementsAdded ( codeInput ) { }
20+ /* Runs when an attribute of a `code-input` is changed (you must add the attribute name to observedAttributes); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
21+ attributeChanged ( codeInput , name , oldValue , newValue ) { }
22+ observedAttributes = [ ]
23+ } ,
924 CodeInput : class extends HTMLElement { // Create code input element
1025 constructor ( ) {
1126 super ( ) ; // Element
1227 }
1328
29+
30+ /* Run this event in all plugins with a optional list of arguments */
31+ plugin_evt ( id , args ) {
32+ // Run the event `id` in each plugin
33+ for ( let i in this . template . plugins ) {
34+ let plugin = this . template . plugins [ i ] ;
35+ if ( id in plugin ) {
36+ if ( args === undefined ) {
37+ plugin [ id ] ( this ) ;
38+ } else {
39+ plugin [ id ] ( this , ...args ) ;
40+ }
41+ }
42+ }
43+ }
44+
1445 /* Syntax-highlighting functions */
1546 update ( text ) {
16-
1747 if ( this . value != text ) this . value = text ; // Change value attribute if necessary.
1848 if ( this . querySelector ( "textarea" ) . value != text ) this . querySelector ( "textarea" ) . value = text ;
1949
@@ -26,13 +56,17 @@ var codeInput = {
2656 }
2757 // Update code
2858 result_element . innerHTML = this . escape_html ( text ) ;
59+ this . plugin_evt ( "beforeHighlight" ) ;
60+
2961 if ( this . autodetect ) { // Autodetection
3062 result_element . className = "" ; // CODE
3163 result_element . parentElement . className = "" ; // PRE
3264 }
3365 // Syntax Highlight
3466 if ( this . template . includeCodeInputInHighlightFunc ) this . template . highlight ( result_element , this ) ;
3567 else this . template . highlight ( result_element ) ;
68+
69+ this . plugin_evt ( "afterHighlight" ) ;
3670 }
3771
3872 sync_scroll ( ) {
@@ -175,6 +209,8 @@ var codeInput = {
175209 this . template = codeInput . usedTemplates [ this . getAttribute ( "template" ) || codeInput . defaultTemplate ] ;
176210 if ( this . template . preElementStyled ) this . classList . add ( "code-input_pre-element-styled" ) ;
177211
212+ this . plugin_evt ( "beforeElementsAdded" ) ;
213+
178214 /* Defaults */
179215 let lang = this . getAttribute ( "lang" ) ;
180216 let placeholder = this . getAttribute ( "placeholder" ) || this . getAttribute ( "lang" ) || "" ;
@@ -196,9 +232,8 @@ var codeInput = {
196232 textarea . setAttribute ( "oninput" , "this.parentElement.update(this.value); this.parentElement.sync_scroll();" ) ;
197233 textarea . setAttribute ( "onscroll" , "this.parentElement.sync_scroll();" ) ;
198234 textarea . setAttribute ( "onkeydown" , "this.parentElement.check_tab(event); this.parentElement.check_enter(event);" ) ;
199-
200235 this . append ( textarea ) ;
201-
236+
202237 /* Create pre code */
203238 let code = document . createElement ( "code" ) ;
204239 let pre = document . createElement ( "pre" ) ;
@@ -210,14 +245,21 @@ var codeInput = {
210245 if ( lang != undefined && lang != "" ) {
211246 code . classList . add ( "language-" + lang ) ;
212247 }
213- else this . autodetect = true // No lang attribute
214248 }
215249
250+ this . plugin_evt ( "afterElementsAdded" ) ;
251+
216252 /* Add code from value attribute - useful for loading from backend */
217253 this . update ( value , this ) ;
218254 }
219- static get observedAttributes ( ) {
220- return [ "value" , "placeholder" , "lang" , "template" ] ; // Attributes to monitor
255+ get observedAttributes ( ) {
256+ let attrs = [ "value" , "placeholder" , "lang" , "template" ] ; // Attributes to monitor
257+
258+ /* Add from plugins */
259+ for ( let plugin in this . template . plugins ) {
260+ attrs = attrs . concat ( plugin . observedAttributes ) ;
261+ }
262+ return attrs ;
221263 }
222264 attributeChangedCallback ( name , oldValue , newValue ) {
223265 if ( this . isConnected ) {
@@ -260,14 +302,14 @@ var codeInput = {
260302 if ( newValue != undefined && newValue != "" ) {
261303 code . classList . add ( "language-" + newValue ) ;
262304 console . log ( "ADD" , "language-" + newValue ) ;
263- } else {
264- // Autodetect - works with HLJS
265- this . autodetect = true ;
266305 }
267306
268307 if ( textarea . placeholder == oldValue ) textarea . placeholder = newValue ;
269308
270309 this . update ( this . value ) ;
310+
311+ default :
312+ this . plugin_evt ( "attributeChanged" , [ name , oldValue , newValue ] ) ; // Plugin event
271313 }
272314 }
273315
@@ -294,28 +336,30 @@ var codeInput = {
294336 codeInput . defaultTemplate = template_name ;
295337 } ,
296338 templates : {
297- custom ( highlight = function ( ) { } , preElementStyled = true , isCode = true , includeCodeInputInHighlightFunc = false ) {
339+ custom ( highlight = function ( ) { } , preElementStyled = true , isCode = true , includeCodeInputInHighlightFunc = false , plugins = [ ] ) {
298340 return {
299341 highlight : highlight ,
300342 includeCodeInputInHighlightFunc : includeCodeInputInHighlightFunc ,
301343 preElementStyled : preElementStyled ,
302344 isCode : isCode ,
303345 } ;
304346 } ,
305- prism ( prism ) { // Dependency: Prism.js (https://prismjs.com/)
347+ prism ( prism , plugins = [ ] ) { // Dependency: Prism.js (https://prismjs.com/)
306348 return {
307349 includeCodeInputInHighlightFunc : false ,
308350 highlight : prism . highlightElement ,
309351 preElementStyled : true ,
310- isCode : true
352+ isCode : true ,
353+ plugins : plugins ,
311354 } ;
312355 } ,
313- hljs ( hljs ) { // Dependency: Highlight.js (https://highlightjs.org/)
356+ hljs ( hljs , plugins = [ ] ) { // Dependency: Highlight.js (https://highlightjs.org/)
314357 return {
315358 includeCodeInputInHighlightFunc : false ,
316359 highlight : hljs . highlightElement ,
317360 preElementStyled : false ,
318- isCode : true
361+ isCode : true ,
362+ plugins : plugins ,
319363 } ;
320364 } ,
321365 characterLimit ( ) {
0 commit comments