⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sourceformatter.java

📁 HTML解析器是一个Java库
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
				}
				appendEssentialNewLine();
				// Insert our indent:
				appendIndent(depth);
				// Write the rest of the line including any indent greater than the first line's indent:
				appendLineKeepWhiteSpace(end,depth);
			}
			assert index==end;
		}

		private boolean appendTextRemoveIndentation(final int end) throws IOException {
			assert index<end;
			appendLineKeepWhiteSpace(end,0);
			if (index==end) return true;
			while (index!=end) {
				// Skip over the original indent:
				while (true) {
					final char ch=sourceText.charAt(index);
					if (!(ch==' ' || ch=='\t')) break;
					if (++index==end) return false;
				}
				appendEssentialNewLine();
				// Write the rest of the line including any indent greater than the first line's indent:
				appendLineKeepWhiteSpace(end,0);
			}
			assert index==end;
			return false;
		}
	
		private int getStartOfLinePos(final int end, final boolean atStartOfLine) {
			// returns the starting position of the next complete line containing text, or -1 if texts starts on the current line (hence not a complete line).
			// sets index to the start of the text following the returned position, or end, whichever comes first.
			int startOfLinePos=atStartOfLine ? index : -1;
			while (true) {
				final char ch=sourceText.charAt(index);
				if (ch=='\n' || ch=='\r') {
					startOfLinePos=index+1;
				} else if (!(ch==' ' || ch=='\t')) break;
				if (++index==end) break;
			}
			return startOfLinePos;
		}
	
		private void appendSpecifiedTextInline(final CharSequence text, int depth) throws IOException {
			final int textLength=text.length();
			int i=appendSpecifiedLine(text,0);
			if (i<textLength) {
				final int subsequentLineDepth=depth+1;
				do {
					while (Segment.isWhiteSpace(text.charAt(i))) if (++i>=textLength) return; // trim whitespace.
					appendEssentialNewLine();
					appendIndent(subsequentLineDepth);
					i=appendSpecifiedLine(text,i);
				} while (i<textLength);
			}
		}
	
		private int appendSpecifiedLine(final CharSequence text, int i) throws IOException {
			// Writes the first line from the specified text starting from the specified position.
			// The line break characters are not written.
			// Returns the position following the first line break character(s), or text.length() if the text contains no line breaks.
			final int textLength=text.length();
			while (true) {
				final char ch=text.charAt(i);
				if (ch=='\r') {
					final int nexti=i+1;
					if (nexti<textLength && text.charAt(nexti)=='\n') return i+2;
				}
				if (ch=='\n') return i+1;
				appendable.append(ch);
				if (++i>=textLength) return i;
			}
		}
	
		private boolean appendTextInline(final int end, int depth, final boolean increaseIndentAfterFirstLineBreak) throws IOException {
			// returns true if all text was on one line, otherwise false
			assert index<end;
			appendLineKeepWhiteSpace(end,depth);
			if (index==end) return true;
			final int subsequentLineDepth=increaseIndentAfterFirstLineBreak ? depth+1 : depth;
			do {
				while (Segment.isWhiteSpace(sourceText.charAt(index))) if (++index==end) return false; // trim whitespace.
				appendEssentialNewLine(); // essential because we might be inside a tag attribute value.  If new lines in normal text aren't required this method wouldn't have been called.
				appendIndent(subsequentLineDepth);
				appendLineKeepWhiteSpace(end,subsequentLineDepth);
			} while (index<end);
			assert index==end;
			return false;
		}
	
		private void appendLineKeepWhiteSpace(final int end, final int depth) throws IOException {
			// Writes the first line from the source text starting from index, ending at the specified end position.
			// The line break characters are not written.
			// Sets index to the position following the first line break character(s), or end if the text contains no line breaks, guaranteed index<=end.
			// Any tags encountered are written using the appendTag method, whose output may include line breaks.
			assert index<end;
			updateNextTag();
			while (true) {
				while (nextTag!=null && index==nextTag.begin) {
					appendTag(nextTag,depth,end);
					if (index==end) return;
				}
				final char ch=sourceText.charAt(index);
				if (ch=='\r') {
					final int nextindex=index+1;
					if (nextindex<end && sourceText.charAt(nextindex)=='\n') {
						index+=2;
						assert index<=end;
						return;
					}
				}
				if (ch=='\n') {
					index++;
					assert index<=end;
					return;
				}
				appendable.append(ch);
				if (++index==end) return;
			}
		}		
	
		private void appendTextCollapseWhiteSpace(final int end, final int depth) throws IOException {
			assert index<end;
			boolean lastWasWhiteSpace=false;
			updateNextTag();
			while (index<end) {
				while (nextTag!=null && index==nextTag.begin) {
					if (lastWasWhiteSpace) {
						appendable.append(' ');
						lastWasWhiteSpace=false;
					}
					appendTag(nextTag,depth,end);
					if (index==end) return;
				}
				final char ch=sourceText.charAt(index++);
				if (Segment.isWhiteSpace(ch)) {
					lastWasWhiteSpace=true;
				} else {
					if (lastWasWhiteSpace) {
						appendable.append(' ');
						lastWasWhiteSpace=false;
					}
					appendable.append(ch);
				}
			}
			if (lastWasWhiteSpace) appendable.append(' ');
			assert index==end;
		}
	
		private void appendContentPreformatted(final int end, final int depth) throws IOException {
			assert index<end;
			updateNextTag();
			do {
				while (nextTag!=null && index==nextTag.begin) {
					appendTag(nextTag,depth,end);
					if (index==end) return;
				}
				appendable.append(sourceText.charAt(index));
			} while (++index<end);
			assert index==end;
		}
	
		private void appendTag(final Tag tag, final int depth, final int end) throws IOException {
			// sets index to last position written
			assert index==tag.begin;
			assert index<end;
			nextTag=tag.getNextTag();
			final int tagEnd=(tag.end<end) ? tag.end : end;
			assert index<tagEnd;
			if (tag.getTagType()==StartTagType.COMMENT || tag.getTagType()==StartTagType.CDATA_SECTION || tag.getTagType().isServerTag()) {
				appendTextPreserveIndentation(tagEnd,depth);
			} else if (tidyTags) {
				final String tidyTag=tag.tidy();
				if ((tag instanceof StartTag) && ((StartTag)tag).getAttributes()!=null)
					appendable.append(tidyTag);
				else
					appendSpecifiedTextInline(tidyTag,depth);
				index=tagEnd;
			} else {
				appendTextInline(tagEnd,depth,true); // Write tag keeping linefeeds. This will add an indent to any attribute values containing linefeeds, but the normal situation where line breaks are between attributes will look nice.
			}
			if (end<=tag.end || !(tag instanceof StartTag)) {
				assert index<=end;
				return;
			}
			if ((tag.name==HTMLElementName.SCRIPT && !indentScriptElements) || tag.getTagType().isServerTag()) {
				// NOTE SERVER ELEMENTS CONTAINING NON-INLINE TAGS WILL NOT FORMAT PROPERLY. NEED TO INVESTIGATE INCLUDING SUCH SERVER ELEMENTS IN DOCUMENT HIERARCHY.
				// this is a script or server start tag, we may need to append the whole element:
				final Element element=tag.getElement();
				final EndTag endTag=element.getEndTag();
				if (endTag==null) {
					assert index<=end;
					return;
				}
				final int contentEnd=(end<endTag.begin) ? end : endTag.begin;
				boolean singleLineContent=true;
				if (index!=contentEnd) {
					// elementContainsMarkup should be made into a TagType property one day.
					// for the time being assume all server element content is code, although this is not true for some Mason elements.
					final boolean elementContainsMarkup=false;
					if (elementContainsMarkup) {
						singleLineContent=appendTextInline(contentEnd,depth+1,false);
					} else {
						singleLineContent=appendTextPreserveIndentation(contentEnd,depth);
					}
				}
				if (endTag.begin>=end) {
					assert index<=end;
					return;
				}
				if (!singleLineContent) {
					appendEssentialNewLine(); // some server or client side scripting languages might need the final new line
					appendIndent(depth);
				}
				assert index==endTag.begin;
				appendTag(endTag,depth,end);
			}
			assert index<=end;
		}
		
	  private void appendIndent(final int depth) throws IOException {
			if (!removeLineBreaks) for (int x=0; x<depth; x++) appendable.append(indentString);
	  }
	
		private void appendFormattingNewLine() throws IOException {
			if (!removeLineBreaks) appendable.append(newLine);
		}

		private void appendEssentialNewLine() throws IOException {
			appendable.append(newLine);
		}
	
		private boolean containsOnlyInlineLevelChildElements(final Element element) {
			// returns true if the element contains only inline-level elements except for SCRIPT elements.
			final Collection<Element> childElements=element.getChildElements();
			if (childElements.isEmpty()) return true;
			for (Element childElement : childElements) {
				final String elementName=childElement.getName();
				if (elementName==HTMLElementName.SCRIPT || !HTMLElements.getInlineLevelElementNames().contains(elementName)) return false;
				if (!containsOnlyInlineLevelChildElements(childElement)) return false;
			}
			return true;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -