docs: @SuppressWarnings({"checkstyle:npathcomplexity", "checkstyle:cyclomaticcomplexity"})
  	protected String updateOutline(String content) {
  		final Pattern sectionPattern = Pattern.compile(
  				isAutoSectionNumbering() ? SECTION_PATTERN_AUTONUMBERING : SECTION_PATTERN_NO_AUTONUMBERING,
  						Pattern.MULTILINE);
  		final Matcher matcher = sectionPattern.matcher(content);
  
  		final Set<String> identifiers = new TreeSet<>();
  		final StringBuilder outline = new StringBuilder();
  		outline.append("\n"); //$NON-NLS-1$
  		final String outlineStyleId = getOutlineStyleId();
  		final boolean styledOutline = !Strings.isEmpty(outlineStyleId);
  		if (styledOutline) {
  			outline.append("<ul class=\"").append(Strings.convertToJavaString(outlineStyleId)); //$NON-NLS-1$
  			outline.append("\" id=\"").append(Strings.convertToJavaString(outlineStyleId)); //$NON-NLS-1$
  			outline.append("\">\n\n"); //$NON-NLS-1$
  		}
  		final IntegerRange outlineDepthRange = getOutlineDepthRange();
  
  		final StringBuffer output;
  		final SectionNumber sections;
  		final int titleGroupId;
  		if (isAutoSectionNumbering()) {
  			output = new StringBuffer();
  			sections = new SectionNumber();
  			titleGroupId = 3;
  		} else {
  			output = null;
  			sections = null;
  			titleGroupId = 2;
  		}
  
  		int prevLevel = 0;
  		int nbOpened = 0;
  
  		while (matcher.find()) {
  			final String prefix = matcher.group(1);
  			final int clevel = prefix.length();
  			if (outlineDepthRange.contains(clevel)) {
  				final int relLevel = clevel - outlineDepthRange.getStart();
  				final String title = matcher.group(titleGroupId);
  				String sectionId = matcher.group(titleGroupId + 1);
  
  				if (output != null) {
  					assert sections != null;
  
  					String sectionNumber = matcher.group(2);
  					if (!Strings.isEmpty(sectionNumber)) {
  						sections.setFromString(sectionNumber, relLevel + 1);
  					} else {
  						sections.increment(relLevel + 1);
  					}
  					sectionNumber = formatSectionNumber(sections);
  
  					if (Strings.isEmpty(sectionId)) {
  						sectionId = computeHeaderId(sectionNumber, title);
  						if (!identifiers.add(sectionId)) {
  							int idNum = 1;
  							String nbId = sectionId + "-" + idNum; //$NON-NLS-1$
  							while (!identifiers.add(nbId)) {
  								++idNum;
  								nbId = sectionId + "-" + idNum; //$NON-NLS-1$
  							}
  							sectionId = nbId;
  						}
  					}
  
  					matcher.appendReplacement(output, formatSectionTitle(prefix, sectionNumber, title, sectionId));
  
  					if (styledOutline && (relLevel > 0 || prevLevel > 0) && relLevel != prevLevel) {
  						if (relLevel > prevLevel) {
  							for (int i = prevLevel; i < relLevel; ++i) {
  								outline.append("<ul>\n"); //$NON-NLS-1$
  								++nbOpened;
  							}
  						} else {
  							for (int i = relLevel; i < prevLevel; ++i) {
  								outline.append("</ul>\n"); //$NON-NLS-1$
  								--nbOpened;
  							}
  						}
  					}
  
  					addOutlineEntry(outline, relLevel + 1, sectionNumber, title, sectionId, styledOutline);
  				} else {
  					if (Strings.isEmpty(sectionId)) {
  						sectionId = computeHeaderId(null, title);
  						if (!identifiers.add(sectionId)) {
  							int idNum = 1;
  							String nbId = sectionId + "-" + idNum; //$NON-NLS-1$
  							while (!identifiers.add(nbId)) {
  								++idNum;
  								nbId = sectionId + "-" + idNum; //$NON-NLS-1$
  							}
  							sectionId = nbId;
  						}
  					}
  
  					addOutlineEntry(outline, relLevel + 1, null, title, sectionId, styledOutline);
  				}
  				prevLevel = relLevel;
  			}
  		}
  
  		final String newContent;
  		if (output != null) {
  			matcher.appendTail(output);
  			newContent = output.toString();
  		} else {
  			newContent = content;
  		}
  
  		outline.append("\n"); //$NON-NLS-1$
  		if (styledOutline) {
  			for (int i = 0; i <= nbOpened; ++i) {
  				outline.append("</ul>\n"); //$NON-NLS-1$
  			}
  		}
  
  		final String outlineTag = getDocumentParser().getOutlineOutputTag();
  		return newContent.replaceAll(Pattern.quote(outlineTag), outline.toString());
  	}