@@ -242,57 +242,56 @@ pub const Element = struct {
242242 };
243243
244244 // Parse the fragment.
245+ // Should return error.Syntax on fail?
245246 const fragment = try parser .documentParseFragmentFromStr (doc , input );
246247 const fragment_node = parser .documentFragmentToNode (fragment );
247248
248249 // We always get it wrapped like so:
249250 // <html><head></head><body>{ ... }</body></html>
250- const html = parser . nodeFirstChild ( fragment_node ) orelse return ;
251- const head = parser .nodeFirstChild (html ) orelse return ;
252- const body = parser .nodeNextSibling ( head ) orelse return ;
251+ // None of the following can be null.
252+ const html = parser .nodeFirstChild (fragment_node ) .? ;
253+ const body = parser .nodeLastChild ( html ) .? ;
253254
254255 const children = try parser .nodeGetChildNodes (body );
255- const len = parser .nodeListLength (children );
256256
257- if (std .mem .eql (u8 , position , "beforeend" )) {
258- for (0.. len ) | _ | {
259- const child = parser .nodeListItem (children , 0 ) orelse continue ;
260- _ = try parser .nodeInsertBefore (self_node , child , null );
257+ // * `target_node` is `*Node` (where we actually insert),
258+ // * `prev_node` is `?*Node`.
259+ const target_node , const prev_node = blk : {
260+ // Prefer case-sensitive match.
261+ // "beforeend" was the most common case in my tests; we might adjust the order
262+ // depending on which ones websites prefer most.
263+ if (std .mem .eql (u8 , position , "beforeend" )) {
264+ break :blk .{ self_node , null };
261265 }
262- } else if (std .mem .eql (u8 , position , "afterbegin" )) {
263- const target = parser .nodeFirstChild (self_node ) orelse self_node ;
264- for (0.. len ) | _ | {
265- const child = parser .nodeListItem (children , 0 ) orelse continue ;
266- _ = try parser .nodeInsertBefore (target , child , null );
267- }
268- } else if (std .mem .eql (u8 , position , "beforebegin" )) {
269- const parent = parser .nodeParentNode (self_node ) orelse {
270- return error .NoModificationAllowed ;
271- };
272266
273- // Make sure parent is not Document.
274- // Should also check for document_fragment and document_type?
275- if ( parser . nodeType ( parent ) == .document ) {
276- return error . NoModificationAllowed ;
267+ if ( std . mem . eql ( u8 , position , "afterbegin" )) {
268+ // Get the first child; null indicates there are no children.
269+ const first_child = parser . nodeFirstChild ( self_node );
270+ break : blk .{ self_node , first_child } ;
277271 }
278272
279- for (0.. len ) | _ | {
280- const child = parser .nodeListItem (children , 0 ) orelse continue ;
281- _ = try parser .nodeInsertBefore (parent , child , self_node );
273+ if (std .mem .eql (u8 , position , "beforebegin" )) {
274+ // The node must have a parent node in order to use this variant.
275+ const parent = parser .nodeParentNode (self_node ) orelse return error .NoModificationAllowed ;
276+ break :blk .{ parent , self_node };
282277 }
283- } else if (std .mem .eql (u8 , position , "afterend" )) {
284- const parent = parser .nodeParentNode (self_node ) orelse {
285- return error .NoModificationAllowed ;
286- };
287278
288- if (parser .nodeType (parent ) == .document ) {
289- return error .NoModificationAllowed ;
279+ if (std .mem .eql (u8 , position , "afterend" )) {
280+ // The node must have a parent node in order to use this variant.
281+ const parent = parser .nodeParentNode (self_node ) orelse return error .NoModificationAllowed ;
282+ // Get the next sibling or null; null indicates our node is the only one.
283+ const sibling = parser .nodeNextSibling (self_node );
284+ break :blk .{ parent , sibling };
290285 }
291286
292- for (0.. len ) | _ | {
293- const child = parser .nodeListItem (children , 0 ) orelse continue ;
294- _ = try parser .nodeInsertBefore (parent , child , null );
295- }
287+ // Thrown if:
288+ // * position is not one of the four listed values.
289+ // * The input is XML that is not well-formed.
290+ return error .Syntax ;
291+ };
292+
293+ while (parser .nodeListItem (children , 0 )) | child | {
294+ _ = try parser .nodeInsertBefore (target_node , child , prev_node );
296295 }
297296 }
298297
0 commit comments