/** * Accepts a CSSPageNode and breaks down the node into different formatter nodes which should * represent it while rewriting the doc.<br> * The CSSPageNode will be broken down into several nodes of type FormatterCSSSelectorNode, * FormatterCSSBlockNode, and FormatterCSSDeclarationNode (if declarations are present). * * @param pageNode */ private void pushFormatterPageNode(CSSPageNode pageNode) { // Push an At-Node to control the lines separators. FormatterCSSAtRuleNode atNode = new FormatterCSSAtRuleNode(document); // +5 for @page length int pageNodeStart = pageNode.getStartingOffset(); atNode.setBegin(createTextNode(document, pageNodeStart, pageNodeStart + PAGE_AT_RULE_LENGTH)); push(atNode); checkedPop(atNode, -1); CSSPageSelectorNode selector = pageNode.getSelector(); CSSDeclarationNode[] declarations = pageNode.getDeclarations(); int blockStartOffset = getBlockStartOffset(pageNodeStart + 1, document); if (selector != null) { blockStartOffset = getBlockStartOffset(selector.getEndingOffset() + 1, document); FormatterBlockWithBeginNode formatterSelectorNode = new FormatterCSSSelectorNode(document, true, false); formatterSelectorNode.setBegin( createTextNode( document, getBeginWithoutWhiteSpaces(pageNodeStart, document), getEndWithoutWhiteSpaces(pageNodeStart + PAGE_AT_RULE_LENGTH, document) + 1)); push(formatterSelectorNode); checkedPop(formatterSelectorNode, -1); formatterSelectorNode = new FormatterCSSSelectorNode(document, false, false); // we do startingOffset - 1 to account for the ':' formatterSelectorNode.setBegin( createTextNode( document, getBeginWithoutWhiteSpaces(selector.getStartingOffset() - 1, document), getEndWithoutWhiteSpaces(selector.getEndingOffset() + 1, document) + 1)); push(formatterSelectorNode); checkedPop(formatterSelectorNode, -1); } FormatterBlockWithBeginEndNode formatterBlockNode = new FormatterCSSBlockNode(document, false); formatterBlockNode.setBegin(createTextNode(document, blockStartOffset, blockStartOffset + 1)); push(formatterBlockNode); // Don't create text nodes when there are no declarations, or only white space if (declarations != null && declarations.length != 0 && getBeginWithoutWhiteSpaces(blockStartOffset + 1, document) < declarations[0].getStartingOffset()) { formatterBlockNode.addChild( createTextNode(document, blockStartOffset + 1, declarations[0].getStartingOffset())); } pushFormatterDeclarationNodes(pageNode.getEndingOffset(), declarations, formatterBlockNode); checkedPop(formatterBlockNode, -1); formatterBlockNode.setEnd( createTextNode(document, pageNode.getEndingOffset(), pageNode.getEndingOffset() + 1)); }
// This is a temporary fix for custom at-rules. When the parser adds support to return the ruleID, // this will need to // be changed private void pushAtRuleNode(CSSNode atRuleNode) { int length = document.getLength(); int selectorStartingOffset = atRuleNode.getStartingOffset(); int selectEndingOffset = atRuleNode.getEndingOffset(); // Locate first white space after the @rule while (selectorStartingOffset < length) { if (Character.isWhitespace(document.charAt(selectorStartingOffset))) { break; } selectorStartingOffset++; } // Find the starting offset for the selector selectorStartingOffset = getBeginWithoutWhiteSpaces(selectorStartingOffset, document); // Find the end offset for the selector while (selectEndingOffset >= selectorStartingOffset) { if (!Character.isWhitespace(document.charAt(selectEndingOffset - 1))) { break; } selectEndingOffset--; } // Push an At-Node to control the lines separators. FormatterCSSAtRuleNode atNode = new FormatterCSSAtRuleNode(document); atNode.setBegin( createTextNode(document, atRuleNode.getStartingOffset(), selectorStartingOffset)); push(atNode); checkedPop(atNode, -1); // We use a selector node for now, we may want to create a new formatter node type for rule id FormatterBlockWithBeginNode formatterSelectorNode = new FormatterCSSSelectorNode(document, false, false); formatterSelectorNode.setBegin( createTextNode( document, getBeginWithoutWhiteSpaces(selectorStartingOffset, document), getEndWithoutWhiteSpaces(selectEndingOffset, document) + 1)); push(formatterSelectorNode); findAndPushPunctuationNode(TypePunctuation.SEMICOLON, selectEndingOffset, false); checkedPop(formatterSelectorNode, -1); }
/** * Accepts a CSSMediaNode and breaks down the node into different formatter nodes which should * represent it while rewriting the doc.<br> * The statements of the media node will also be recursively added as formatter nodes. * * @param pageNode */ private void pushFormatterMediaNode(CSSMediaNode mediaNode) { // Push an At-Node to control the lines separators. FormatterCSSAtRuleNode atNode = new FormatterCSSAtRuleNode(document); int mediaNodeStart = mediaNode.getStartingOffset(); atNode.setBegin( createTextNode(document, mediaNodeStart, mediaNodeStart + MEDIA_AT_RULE_LENGTH)); push(atNode); checkedPop(atNode, -1); CSSTextNode[] medias = mediaNode.getMedias(); int blockStartOffset = getBlockStartOffset(medias[medias.length - 1].getEndingOffset() + 1, document); pushFormatterMediaSelectorNodes(medias, 0); FormatterBlockWithBeginEndNode formatterBlockNode = new FormatterCSSBlockNode(document, false); formatterBlockNode.setBegin(createTextNode(document, blockStartOffset, blockStartOffset + 1)); push(formatterBlockNode); // Recursively add this node's children CSSNode[] statements = mediaNode.getStatements(); addNodes(statements); if (statements.length > 0) { formatterBlockNode.addChild( createTextNode( document, statements[statements.length - 1].getEndingOffset() + 1, mediaNode.getEndingOffset())); } checkedPop(formatterBlockNode, -1); formatterBlockNode.setEnd( createTextNode(document, mediaNode.getEndingOffset(), mediaNode.getEndingOffset() + 1)); }
/** * Accepts a CSSFontFaceNode and breaks down the node into different formatter nodes which should * represent it while rewriting the doc.<br> * The CSSFontFaceNode will be broken down into several nodes of type FormatterCSSSelectorNode, * FormatterCSSBlockNode, and FormatterCSSDeclarationNode (if declarations are present). * * @param pageNode */ private void pushFormatterFontFaceNode(CSSFontFaceNode faceFontNode) { CSSDeclarationNode[] declarations = faceFontNode.getDeclarations(); int blockStartOffset = getBlockStartOffset(faceFontNode.getStartingOffset() + 9, document); // create a FormatterCSSSelectorNode for @font-face FormatterCSSAtRuleNode atFontFaceNode = new FormatterCSSAtRuleNode(document); atFontFaceNode.setBegin( createTextNode( document, getBeginWithoutWhiteSpaces(faceFontNode.getStartingOffset(), document), getEndWithoutWhiteSpaces(faceFontNode.getStartingOffset() + 9, document) + 1)); push(atFontFaceNode); checkedPop(atFontFaceNode, -1); FormatterBlockWithBeginEndNode formatterBlockNode = new FormatterCSSBlockNode(document, false); formatterBlockNode.setBegin(createTextNode(document, blockStartOffset, blockStartOffset + 1)); push(formatterBlockNode); // Don't create text nodes when there are no declarations, or only white space if (declarations != null && declarations.length != 0 && getBeginWithoutWhiteSpaces(blockStartOffset + 1, document) < declarations[0].getStartingOffset()) { formatterBlockNode.addChild( createTextNode(document, blockStartOffset + 1, declarations[0].getStartingOffset())); } pushFormatterDeclarationNodes(faceFontNode.getEndingOffset(), declarations, formatterBlockNode); checkedPop(formatterBlockNode, -1); formatterBlockNode.setEnd( createTextNode( document, faceFontNode.getEndingOffset(), faceFontNode.getEndingOffset() + 1)); }