docs: function processHTML() {
              /**
               * Genetrate an iterator of the index where non whitespace appear
               * @param {string} text The text to set
               * @returns {number} The index
               */
              function* genWordStartIndices(text) {
                  if (!text.trim()) {
                      return
                  }
                  const re = /\s/u
                  let preIsWhitespace = true
                  let i = 0
                  for (const c of text) {
                      const isWhitespace = re.test(c)
                      if (preIsWhitespace && !isWhitespace) {
                          yield i
                      }
                      preIsWhitespace = isWhitespace
                      i++
                  }
              }
  
              /**
               * Check whether the given token is a dummy element.
               * @param {Token} node The token to check.
               * @returns {boolean} `true` if the token is a dummy element.
               */
              function isDummyElement(node) {
                  return (
                      !node.startTag &&
                      (node.name === "body" ||
                          node.name === "head" ||
                          node.name === "html")
                  )
              }
  
              /**
               * Get the start token of Element
               * @param  {Node} elementNode The element node
               * @returns {Token} The start token
               */
              function getStartToken(elementNode) {
                  if (!elementNode) {
                      return null
                  }
                  if (elementNode.type !== "HTMLElement") {
                      return null
                  }
                  if (isDummyElement(elementNode)) {
                      return null
                  }
                  return elementNode.startTag || elementNode
              }
  
              microTemplateService.traverseDocumentNodes({
                  HTMLElement(node) {
                      if (isDummyElement(node)) {
                          return
                      }
                      const elementNode =
                          microTemplateService.getBranchProcessedHtmlNode(
                              node,
                              sourceCode
                          ) || node
                      const startToken = getStartToken(elementNode)
                      const parentStartToken = getStartToken(elementNode.parent)
                      if (parentStartToken) {
                          // self indent
                          setOffsetToToken(
                              startToken,
                              1,
                              parentStartToken.loc.start.line
                          )
                      } else {
                          setOffsetRootToIndex(startToken.range[0])
                      }
                      if (
                          IGNORE_INDENT_ELEMENT_NAMES.find(
                              name => name === elementNode.name
                          )
                      ) {
                          ignoreRanges.push([
                              elementNode.startTag
                                  ? elementNode.startTag.range[1]
                                  : elementNode.range[0],
                              elementNode.endTag
                                  ? elementNode.endTag.range[0]
                                  : elementNode.range[1],
                          ])
                      }
                  },
                  HTMLStartTag(node) {
                      const attrs = node.attributes.concat(node.ignoredAttributes)
                      setOffsetToToken(
                          attrs,
                          options.attribute,
                          node.loc.start.line
                      )
                      const start = node.tagOpen
                          ? node.tagOpen.range[1]
                          : node.range[0]
                      const end = node.tagClose
                          ? node.tagClose.range[0]
                          : node.range[1]
                      const attrTemplateTokens = microTemplateService
                          .getMicroTemplateTokens()
                          .filter(token => {
                              if (
                                  token.range[0] < start ||
                                  end < token.range[1]
                              ) {
                                  return false
                              }
                              return !attrs.some(
                                  n =>
                                      token.range[0] < n.range[1] &&
                                      n.range[0] < token.range[1]
                              )
                          })
                      setOffsetToToken(
                          attrTemplateTokens,
                          options.attribute,
                          node.loc.start.line
                      )
  
                      if (node.tagClose) {
                          setOffsetToToken(
                              node.tagClose,
                              options.closeBracket,
                              node.loc.start.line
                          )
                      }
                  },
                  HTMLEndTag(node) {
                      const endTag =
                          microTemplateService.getBranchProcessedHtmlNode(
                              node,
                              sourceCode
                          ) || node
                      const startToken = getStartToken(endTag.parent)
                      if (startToken) {
                          // self indent
                          setOffsetToToken(endTag, 0, startToken.loc.start.line)
                      }
  
                      if (endTag.tagClose) {
                          setOffsetToToken(
                              endTag.tagClose,
                              options.closeBracket,
                              endTag.loc.start.line
                          )
                      }
                  },
                  HTMLText(node) {
                      const textNode =
                          microTemplateService.getBranchProcessedHtmlNode(
                              node,
                              sourceCode
                          ) || node
  
                      const textHTML = sourceCode.text.slice(
                          textNode.range[0],
                          textNode.range[1]
                      )
                      const startToken = getStartToken(textNode.parent)
                      if (startToken) {
                          // self indent
                          for (const i of genWordStartIndices(textHTML)) {
                              setOffsetToIndex(
                                  textNode.range[0] + i,
                                  1,
                                  startToken.loc.start.line
                              )
                          }
                      } else {
                          for (const i of genWordStartIndices(textHTML)) {
                              setOffsetRootToIndex(textNode.range[0] + i)
                          }
                      }
                  },
                  HTMLComment(node) {
                      const commentNode =
                          microTemplateService.getBranchProcessedHtmlNode(
                              node,
                              sourceCode
                          ) || node
                      const startToken = getStartToken(commentNode.parent)
                      if (startToken) {
                          // self indent
                          setOffsetToToken(
                              commentNode,
                              1,
                              startToken.loc.start.line
                          )
                      } else {
                          setOffsetRootToIndex(commentNode.range[0])
                      }
  
                      const commentStart = commentNode.range[0] + 4
                      const commentEnd = commentNode.range[1] - 3
                      const comment = sourceCode.text.slice(
                          commentStart,
                          commentEnd
                      )
  
                      for (const i of genWordStartIndices(comment)) {
                          setOffsetToIndex(
                              commentStart + i,
                              1,
                              commentNode.loc.start.line
                          )
                      }
                      setOffsetToIndex(commentEnd, 0, commentNode.loc.start.line)
                  },
              })
          }