@@ -14,14 +14,26 @@ class HTMLCodeBlockElement extends HTMLElement {
1414 throw new TypeError ( 'The syntax highlighting engine is not set to `HTMLCodeBlockElement.highlight`.' ) ;
1515 return { markup : '' } ;
1616 } ;
17+ /** Observer to monitor the editing of the content of this element. */
18+ #observer = new MutationObserver ( ( ) => {
19+ this . #observer. disconnect ( ) ;
20+ // Remove elements other than element with `code` as `slot` attribute value.
21+ // The content of the `[slot="code"]` element will be passed to next rendering.
22+ const slots = this . querySelectorAll ( '[slot]:not([slot="code"])' ) ;
23+ for ( const slot of slots ) {
24+ slot . remove ( ) ;
25+ }
26+ this . #value = ( this . textContent || this . getAttribute ( 'value' ) || '' ) . replace ( / ^ \n / , '' ) . replace ( / \n $ / , '' ) ;
27+ this . #render( ) ;
28+ } ) ;
1729 /** Slot elements for Shadow DOM content */
1830 #slots = ( ( ) => {
1931 /**
2032 * @param name - The value of name attribute for the slot element
2133 * @param id - The value of id attribute for the slot element
2234 * @return - The slot element
2335 */
24- const mkslot = ( name , id ) => {
36+ const mkslot = ( name , id = '' ) => {
2537 const slot = document . createElement ( 'slot' ) ;
2638 slot . name = name ;
2739 if ( id ) {
@@ -35,6 +47,22 @@ class HTMLCodeBlockElement extends HTMLElement {
3547 code : mkslot ( 'code' ) ,
3648 } ;
3749 } ) ( ) ;
50+ /**
51+ * True when rendered at least once.
52+ * The purpose of this flag is to available the operation the following usage.
53+ *
54+ * Specifically, this is the case where an element is rendered
55+ * on the screen without ever using the value property.
56+ *
57+ * ```js
58+ * const cb = document.createElement('code-block');
59+ *
60+ * cb.language = 'json';
61+ * cb.textContent = '{"a": 100}';
62+ * document.body.prepend(cb);
63+ * ```
64+ */
65+ #rendered = false ;
3866 /** Pure DOM content */
3967 #a11yName;
4068 /** Pure DOM content */
@@ -93,6 +121,7 @@ class HTMLCodeBlockElement extends HTMLElement {
93121 if ( ! this . parentNode ) {
94122 return ;
95123 }
124+ this . #observer. disconnect ( ) ;
96125 const src = ( ( ) => {
97126 if ( / [ ^ \n ] \n $ / . test ( this . #value) ) {
98127 return `${ this . #value} \n` ;
@@ -113,6 +142,9 @@ class HTMLCodeBlockElement extends HTMLElement {
113142 this . append ( this . #a11yName) ;
114143 this . append ( this . #copyButton) ;
115144 this . append ( this . #codeWrap) ;
145+ this . #observer. observe ( this , {
146+ childList : true ,
147+ } ) ;
116148 } ;
117149 /** @return - Syntax Highlighted Source Code */
118150 get value ( ) {
@@ -123,13 +155,19 @@ class HTMLCodeBlockElement extends HTMLElement {
123155 this . #render( ) ;
124156 }
125157 /**
126- * The name of code block
158+ * The accessible name of code block
127159 * @return - The value of the label attribute
128160 */
129161 get label ( ) {
130162 return this . #label;
131163 }
132164 set label ( value ) {
165+ if ( this . #label === value ||
166+ ( this . #label === '' &&
167+ this . getAttribute ( 'label' ) === null &&
168+ value === null ) ) {
169+ return ;
170+ }
133171 if ( value === null ) {
134172 this . #label = '' ;
135173 this . removeAttribute ( 'label' ) ;
@@ -141,13 +179,19 @@ class HTMLCodeBlockElement extends HTMLElement {
141179 this . #render( ) ;
142180 }
143181 /**
144- * Language Mode
182+ * Language name
145183 * @return - The value of the language attribute
146184 */
147185 get language ( ) {
148186 return this . #language;
149187 }
150188 set language ( value ) {
189+ if ( this . #language === value ||
190+ ( this . #language === '' &&
191+ this . getAttribute ( 'language' ) === null &&
192+ value === null ) ) {
193+ return ;
194+ }
151195 if ( value === null ) {
152196 this . #language = '' ;
153197 this . removeAttribute ( 'language' ) ;
@@ -159,13 +203,16 @@ class HTMLCodeBlockElement extends HTMLElement {
159203 this . #render( ) ;
160204 }
161205 /**
162- * Flag to display the UI
206+ * The flag to display the UI
163207 * @return - With or without controls attribute
164208 * */
165209 get controls ( ) {
166210 return this . #controls;
167211 }
168212 set controls ( value ) {
213+ if ( this . #controls === value ) {
214+ return ;
215+ }
169216 this . #controls = value ;
170217 if ( this . #controls) {
171218 this . setAttribute ( 'controls' , '' ) ;
@@ -200,6 +247,11 @@ class HTMLCodeBlockElement extends HTMLElement {
200247 }
201248 }
202249 connectedCallback ( ) {
250+ if ( this . #rendered === false &&
251+ this . #value === '' ) {
252+ this . #value = this . textContent || '' ;
253+ }
254+ this . #rendered = true ;
203255 this . #render( ) ;
204256 }
205257 constructor ( ) {
0 commit comments