void WebVTTParser::constructTreeFromToken(Document& document) { QualifiedName tagName(nullAtom, AtomicString(m_token.name()), xhtmlNamespaceURI); // http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules switch (m_token.type()) { case WebVTTTokenTypes::Character: { String content(m_token.characters()); // FIXME: This should be 8bit if possible. RefPtr<Text> child = Text::create(document, content); m_currentNode->parserAppendChild(child); break; } case WebVTTTokenTypes::StartTag: { RefPtr<WebVTTElement> child; WebVTTNodeType nodeType = tokenToNodeType(m_token); if (nodeType != WebVTTNodeTypeNone) child = WebVTTElement::create(nodeType, &document); if (child) { if (m_token.classes().size() > 0) child->setAttribute(classAttr, AtomicString(m_token.classes())); if (child->webVTTNodeType() == WebVTTNodeTypeVoice) child->setAttribute(WebVTTElement::voiceAttributeName(), AtomicString(m_token.annotation())); else if (child->webVTTNodeType() == WebVTTNodeTypeLanguage) { m_languageStack.append(AtomicString(m_token.annotation())); child->setAttribute(WebVTTElement::langAttributeName(), m_languageStack.last()); } if (!m_languageStack.isEmpty()) child->setLanguage(m_languageStack.last()); m_currentNode->parserAppendChild(child); m_currentNode = child; } break; } case WebVTTTokenTypes::EndTag: { WebVTTNodeType nodeType = tokenToNodeType(m_token); if (nodeType != WebVTTNodeTypeNone) { if (nodeType == WebVTTNodeTypeLanguage && m_currentNode->isWebVTTElement() && toWebVTTElement(m_currentNode.get())->webVTTNodeType() == WebVTTNodeTypeLanguage) m_languageStack.removeLast(); if (m_currentNode->parentNode()) m_currentNode = m_currentNode->parentNode(); } break; } case WebVTTTokenTypes::TimestampTag: { unsigned position = 0; String charactersString(StringImpl::create8BitIfPossible(m_token.characters())); double time = collectTimeStamp(charactersString, &position); if (time != malformedTime) m_currentNode->parserAppendChild(ProcessingInstruction::create(document, "timestamp", charactersString)); break; } default: break; } m_token.clear(); }
void VTTTreeBuilder::constructTreeFromToken(Document& document) { // http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules switch (m_token.type()) { case VTTTokenTypes::Character: { m_currentNode->parserAppendChild(Text::create(document, m_token.characters())); break; } case VTTTokenTypes::StartTag: { VTTNodeType nodeType = tokenToNodeType(m_token); if (nodeType == VTTNodeTypeNone) break; VTTNodeType currentType = m_currentNode->isVTTElement() ? toVTTElement(m_currentNode.get())->webVTTNodeType() : VTTNodeTypeNone; // <rt> is only allowed if the current node is <ruby>. if (nodeType == VTTNodeTypeRubyText && currentType != VTTNodeTypeRuby) break; RefPtrWillBeRawPtr<VTTElement> child = VTTElement::create(nodeType, &document); if (!m_token.classes().isEmpty()) child->setAttribute(classAttr, m_token.classes()); if (nodeType == VTTNodeTypeVoice) { child->setAttribute(VTTElement::voiceAttributeName(), m_token.annotation()); } else if (nodeType == VTTNodeTypeLanguage) { m_languageStack.append(m_token.annotation()); child->setAttribute(VTTElement::langAttributeName(), m_languageStack.last()); } if (!m_languageStack.isEmpty()) child->setLanguage(m_languageStack.last()); m_currentNode->parserAppendChild(child); m_currentNode = child; break; } case VTTTokenTypes::EndTag: { VTTNodeType nodeType = tokenToNodeType(m_token); if (nodeType == VTTNodeTypeNone) break; // The only non-VTTElement would be the DocumentFragment root. (Text // nodes and PIs will never appear as m_currentNode.) if (!m_currentNode->isVTTElement()) break; VTTNodeType currentType = toVTTElement(m_currentNode.get())->webVTTNodeType(); bool matchesCurrent = nodeType == currentType; if (!matchesCurrent) { // </ruby> auto-closes <rt>. if (currentType == VTTNodeTypeRubyText && nodeType == VTTNodeTypeRuby) { if (m_currentNode->parentNode()) m_currentNode = m_currentNode->parentNode(); } else { break; } } if (nodeType == VTTNodeTypeLanguage) m_languageStack.removeLast(); if (m_currentNode->parentNode()) m_currentNode = m_currentNode->parentNode(); break; } case VTTTokenTypes::TimestampTag: { String charactersString = m_token.characters(); double parsedTimeStamp; if (VTTParser::collectTimeStamp(charactersString, parsedTimeStamp)) m_currentNode->parserAppendChild(ProcessingInstruction::create(document, "timestamp", charactersString)); break; } default: break; } }