8 /** |
8 /** |
9 * Class WP_Block_Parser_Block |
9 * Class WP_Block_Parser_Block |
10 * |
10 * |
11 * Holds the block structure in memory |
11 * Holds the block structure in memory |
12 * |
12 * |
13 * @since 3.8.0 |
13 * @since 5.0.0 |
14 */ |
14 */ |
15 class WP_Block_Parser_Block { |
15 class WP_Block_Parser_Block { |
16 /** |
16 /** |
17 * Name of block |
17 * Name of block |
18 * |
18 * |
19 * @example "core/paragraph" |
19 * @example "core/paragraph" |
20 * |
20 * |
21 * @since 3.8.0 |
21 * @since 5.0.0 |
22 * @var string |
22 * @var string |
23 */ |
23 */ |
24 public $blockName; |
24 public $blockName; |
25 |
25 |
26 /** |
26 /** |
27 * Optional set of attributes from block comment delimiters |
27 * Optional set of attributes from block comment delimiters |
28 * |
28 * |
29 * @example null |
29 * @example null |
30 * @example array( 'columns' => 3 ) |
30 * @example array( 'columns' => 3 ) |
31 * |
31 * |
32 * @since 3.8.0 |
32 * @since 5.0.0 |
33 * @var array|null |
33 * @var array|null |
34 */ |
34 */ |
35 public $attrs; |
35 public $attrs; |
36 |
36 |
37 /** |
37 /** |
38 * List of inner blocks (of this same class) |
38 * List of inner blocks (of this same class) |
39 * |
39 * |
40 * @since 3.8.0 |
40 * @since 5.0.0 |
41 * @var WP_Block_Parser_Block[] |
41 * @var WP_Block_Parser_Block[] |
42 */ |
42 */ |
43 public $innerBlocks; |
43 public $innerBlocks; |
44 |
44 |
45 /** |
45 /** |
46 * Resultant HTML from inside block comment delimiters |
46 * Resultant HTML from inside block comment delimiters |
47 * after removing inner blocks |
47 * after removing inner blocks |
48 * |
48 * |
49 * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..." |
49 * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..." |
50 * |
50 * |
51 * @since 3.8.0 |
51 * @since 5.0.0 |
52 * @var string |
52 * @var string |
53 */ |
53 */ |
54 public $innerHTML; |
54 public $innerHTML; |
55 |
55 |
56 /** |
56 /** |
70 /** |
70 /** |
71 * Constructor. |
71 * Constructor. |
72 * |
72 * |
73 * Will populate object properties from the provided arguments. |
73 * Will populate object properties from the provided arguments. |
74 * |
74 * |
75 * @since 3.8.0 |
75 * @since 5.0.0 |
76 * |
76 * |
77 * @param string $name Name of block. |
77 * @param string $name Name of block. |
78 * @param array $attrs Optional set of attributes from block comment delimiters. |
78 * @param array $attrs Optional set of attributes from block comment delimiters. |
79 * @param array $innerBlocks List of inner blocks (of this same class). |
79 * @param array $innerBlocks List of inner blocks (of this same class). |
80 * @param string $innerHTML Resultant HTML from inside block comment delimiters after removing inner blocks. |
80 * @param string $innerHTML Resultant HTML from inside block comment delimiters after removing inner blocks. |
93 * Class WP_Block_Parser_Frame |
93 * Class WP_Block_Parser_Frame |
94 * |
94 * |
95 * Holds partial blocks in memory while parsing |
95 * Holds partial blocks in memory while parsing |
96 * |
96 * |
97 * @internal |
97 * @internal |
98 * @since 3.8.0 |
98 * @since 5.0.0 |
99 */ |
99 */ |
100 class WP_Block_Parser_Frame { |
100 class WP_Block_Parser_Frame { |
101 /** |
101 /** |
102 * Full or partial block |
102 * Full or partial block |
103 * |
103 * |
104 * @since 3.8.0 |
104 * @since 5.0.0 |
105 * @var WP_Block_Parser_Block |
105 * @var WP_Block_Parser_Block |
106 */ |
106 */ |
107 public $block; |
107 public $block; |
108 |
108 |
109 /** |
109 /** |
110 * Byte offset into document for start of parse token |
110 * Byte offset into document for start of parse token |
111 * |
111 * |
112 * @since 3.8.0 |
112 * @since 5.0.0 |
113 * @var int |
113 * @var int |
114 */ |
114 */ |
115 public $token_start; |
115 public $token_start; |
116 |
116 |
117 /** |
117 /** |
118 * Byte length of entire parse token string |
118 * Byte length of entire parse token string |
119 * |
119 * |
120 * @since 3.8.0 |
120 * @since 5.0.0 |
121 * @var int |
121 * @var int |
122 */ |
122 */ |
123 public $token_length; |
123 public $token_length; |
124 |
124 |
125 /** |
125 /** |
126 * Byte offset into document for after parse token ends |
126 * Byte offset into document for after parse token ends |
127 * (used during reconstruction of stack into parse production) |
127 * (used during reconstruction of stack into parse production) |
128 * |
128 * |
129 * @since 3.8.0 |
129 * @since 5.0.0 |
130 * @var int |
130 * @var int |
131 */ |
131 */ |
132 public $prev_offset; |
132 public $prev_offset; |
133 |
133 |
134 /** |
134 /** |
135 * Byte offset into document where leading HTML before token starts |
135 * Byte offset into document where leading HTML before token starts |
136 * |
136 * |
137 * @since 3.8.0 |
137 * @since 5.0.0 |
138 * @var int |
138 * @var int |
139 */ |
139 */ |
140 public $leading_html_start; |
140 public $leading_html_start; |
141 |
141 |
142 /** |
142 /** |
143 * Constructor |
143 * Constructor |
144 * |
144 * |
145 * Will populate object properties from the provided arguments. |
145 * Will populate object properties from the provided arguments. |
146 * |
146 * |
147 * @since 3.8.0 |
147 * @since 5.0.0 |
148 * |
148 * |
149 * @param WP_Block_Parser_Block $block Full or partial block. |
149 * @param WP_Block_Parser_Block $block Full or partial block. |
150 * @param int $token_start Byte offset into document for start of parse token. |
150 * @param int $token_start Byte offset into document for start of parse token. |
151 * @param int $token_length Byte length of entire parse token string. |
151 * @param int $token_length Byte length of entire parse token string. |
152 * @param int $prev_offset Byte offset into document for after parse token ends. |
152 * @param int $prev_offset Byte offset into document for after parse token ends. |
164 /** |
164 /** |
165 * Class WP_Block_Parser |
165 * Class WP_Block_Parser |
166 * |
166 * |
167 * Parses a document and constructs a list of parsed block objects |
167 * Parses a document and constructs a list of parsed block objects |
168 * |
168 * |
169 * @since 3.8.0 |
169 * @since 5.0.0 |
170 * @since 4.0.0 returns arrays not objects, all attributes are arrays |
170 * @since 4.0.0 returns arrays not objects, all attributes are arrays |
171 */ |
171 */ |
172 class WP_Block_Parser { |
172 class WP_Block_Parser { |
173 /** |
173 /** |
174 * Input document being parsed |
174 * Input document being parsed |
175 * |
175 * |
176 * @example "Pre-text\n<!-- wp:paragraph -->This is inside a block!<!-- /wp:paragraph -->" |
176 * @example "Pre-text\n<!-- wp:paragraph -->This is inside a block!<!-- /wp:paragraph -->" |
177 * |
177 * |
178 * @since 3.8.0 |
178 * @since 5.0.0 |
179 * @var string |
179 * @var string |
180 */ |
180 */ |
181 public $document; |
181 public $document; |
182 |
182 |
183 /** |
183 /** |
184 * Tracks parsing progress through document |
184 * Tracks parsing progress through document |
185 * |
185 * |
186 * @since 3.8.0 |
186 * @since 5.0.0 |
187 * @var int |
187 * @var int |
188 */ |
188 */ |
189 public $offset; |
189 public $offset; |
190 |
190 |
191 /** |
191 /** |
192 * List of parsed blocks |
192 * List of parsed blocks |
193 * |
193 * |
194 * @since 3.8.0 |
194 * @since 5.0.0 |
195 * @var WP_Block_Parser_Block[] |
195 * @var WP_Block_Parser_Block[] |
196 */ |
196 */ |
197 public $output; |
197 public $output; |
198 |
198 |
199 /** |
199 /** |
200 * Stack of partially-parsed structures in memory during parse |
200 * Stack of partially-parsed structures in memory during parse |
201 * |
201 * |
202 * @since 3.8.0 |
202 * @since 5.0.0 |
203 * @var WP_Block_Parser_Frame[] |
203 * @var WP_Block_Parser_Frame[] |
204 */ |
204 */ |
205 public $stack; |
205 public $stack; |
206 |
206 |
207 /** |
207 /** |
217 * |
217 * |
218 * When encountering an invalid parse will return a best-effort |
218 * When encountering an invalid parse will return a best-effort |
219 * parse. In contrast to the specification parser this does not |
219 * parse. In contrast to the specification parser this does not |
220 * return an error on invalid inputs. |
220 * return an error on invalid inputs. |
221 * |
221 * |
222 * @since 3.8.0 |
222 * @since 5.0.0 |
223 * |
223 * |
224 * @param string $document Input document being parsed. |
224 * @param string $document Input document being parsed. |
225 * @return WP_Block_Parser_Block[] |
225 * @return WP_Block_Parser_Block[] |
226 */ |
226 */ |
227 function parse( $document ) { |
227 function parse( $document ) { |
247 * with that token before descending deeper into a |
247 * with that token before descending deeper into a |
248 * nested block tree or continuing along the document |
248 * nested block tree or continuing along the document |
249 * or breaking out of a level of nesting. |
249 * or breaking out of a level of nesting. |
250 * |
250 * |
251 * @internal |
251 * @internal |
252 * @since 3.8.0 |
252 * @since 5.0.0 |
253 * @return bool |
253 * @return bool |
254 */ |
254 */ |
255 function proceed() { |
255 function proceed() { |
256 $next_token = $this->next_token(); |
256 $next_token = $this->next_token(); |
257 list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token; |
257 list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token; |
298 * easy case is if we stumbled upon a void block |
298 * easy case is if we stumbled upon a void block |
299 * in the top-level of the document |
299 * in the top-level of the document |
300 */ |
300 */ |
301 if ( 0 === $stack_depth ) { |
301 if ( 0 === $stack_depth ) { |
302 if ( isset( $leading_html_start ) ) { |
302 if ( isset( $leading_html_start ) ) { |
303 $this->output[] = (array) self::freeform( |
303 $this->output[] = (array) $this->freeform( |
304 substr( |
304 substr( |
305 $this->document, |
305 $this->document, |
306 $leading_html_start, |
306 $leading_html_start, |
307 $start_offset - $leading_html_start |
307 $start_offset - $leading_html_start |
308 ) |
308 ) |
392 * and finds the next valid token to parse if it exists |
392 * and finds the next valid token to parse if it exists |
393 * |
393 * |
394 * Returns the type of the find: kind of find, block information, attributes |
394 * Returns the type of the find: kind of find, block information, attributes |
395 * |
395 * |
396 * @internal |
396 * @internal |
397 * @since 3.8.0 |
397 * @since 5.0.0 |
398 * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments |
398 * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments |
399 * @return array |
399 * @return array |
400 */ |
400 */ |
401 function next_token() { |
401 function next_token() { |
402 $matches = null; |
402 $matches = null; |
480 /** |
480 /** |
481 * Pushes a length of text from the input document |
481 * Pushes a length of text from the input document |
482 * to the output list as a freeform block. |
482 * to the output list as a freeform block. |
483 * |
483 * |
484 * @internal |
484 * @internal |
485 * @since 3.8.0 |
485 * @since 5.0.0 |
486 * @param null $length how many bytes of document text to output. |
486 * @param null $length how many bytes of document text to output. |
487 */ |
487 */ |
488 function add_freeform( $length = null ) { |
488 function add_freeform( $length = null ) { |
489 $length = $length ? $length : strlen( $this->document ) - $this->offset; |
489 $length = $length ? $length : strlen( $this->document ) - $this->offset; |
490 |
490 |
491 if ( 0 === $length ) { |
491 if ( 0 === $length ) { |
492 return; |
492 return; |
493 } |
493 } |
494 |
494 |
495 $this->output[] = (array) self::freeform( substr( $this->document, $this->offset, $length ) ); |
495 $this->output[] = (array) $this->freeform( substr( $this->document, $this->offset, $length ) ); |
496 } |
496 } |
497 |
497 |
498 /** |
498 /** |
499 * Given a block structure from memory pushes |
499 * Given a block structure from memory pushes |
500 * a new block to the output list. |
500 * a new block to the output list. |
501 * |
501 * |
502 * @internal |
502 * @internal |
503 * @since 3.8.0 |
503 * @since 5.0.0 |
504 * @param WP_Block_Parser_Block $block The block to add to the output. |
504 * @param WP_Block_Parser_Block $block The block to add to the output. |
505 * @param int $token_start Byte offset into the document where the first token for the block starts. |
505 * @param int $token_start Byte offset into the document where the first token for the block starts. |
506 * @param int $token_length Byte length of entire block from start of opening token to end of closing token. |
506 * @param int $token_length Byte length of entire block from start of opening token to end of closing token. |
507 * @param int|null $last_offset Last byte offset into document if continuing form earlier output. |
507 * @param int|null $last_offset Last byte offset into document if continuing form earlier output. |
508 */ |
508 */ |
522 |
522 |
523 /** |
523 /** |
524 * Pushes the top block from the parsing stack to the output list. |
524 * Pushes the top block from the parsing stack to the output list. |
525 * |
525 * |
526 * @internal |
526 * @internal |
527 * @since 3.8.0 |
527 * @since 5.0.0 |
528 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. |
528 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. |
529 */ |
529 */ |
530 function add_block_from_stack( $end_offset = null ) { |
530 function add_block_from_stack( $end_offset = null ) { |
531 $stack_top = array_pop( $this->stack ); |
531 $stack_top = array_pop( $this->stack ); |
532 $prev_offset = $stack_top->prev_offset; |
532 $prev_offset = $stack_top->prev_offset; |
539 $stack_top->block->innerHTML .= $html; |
539 $stack_top->block->innerHTML .= $html; |
540 $stack_top->block->innerContent[] = $html; |
540 $stack_top->block->innerContent[] = $html; |
541 } |
541 } |
542 |
542 |
543 if ( isset( $stack_top->leading_html_start ) ) { |
543 if ( isset( $stack_top->leading_html_start ) ) { |
544 $this->output[] = (array) self::freeform( |
544 $this->output[] = (array) $this->freeform( |
545 substr( |
545 substr( |
546 $this->document, |
546 $this->document, |
547 $stack_top->leading_html_start, |
547 $stack_top->leading_html_start, |
548 $stack_top->token_start - $stack_top->leading_html_start |
548 $stack_top->token_start - $stack_top->leading_html_start |
549 ) |
549 ) |