# Path: mdn/utils.py
# def join_content(content_bits):
#     """Construct a string with just the right whitespace."""
#     out = ''
#     nospace_before = '!,.;?[ '
#     nospace_after = ' '
#     for bit in content_bits:
#         if bit:
#             if (out and out[-1] not in nospace_after and
#                     bit[0] not in nospace_before):
#                 out += ' '
#             out += bit
#     return out
# 
# Path: mdn/visitor.py
# class Extractor(Recorder):
#     """Extracts information from parsed HTML.
# 
#     The Extractor works from trunk nodes to leaf nodes.
#     """
# 
#     extractor_name = 'Extractor'
# 
#     def initialize_extractor(self, elements=None, debug=False, **kwargs):
#         """Setup extractor plus common variables."""
#         self.initialize_tracker(**kwargs)
#         self.elements = elements or []
#         self.debug = debug
# 
#     def extract(self):
#         """Extract data from a parsed list of elements.
# 
#         This is used when you need sibling processing of a tree, rather than
#         subtree processing during parsing.
#         """
#         self.setup_extract()
#         state = 'begin'
#         for element in self.elements:
#             state = self.walk(state, element)
#         return self.extracted_data()
# 
#     def setup_extract(self):
#         """Setup the extraction state variables."""
#         raise NotImplementedError(
#             '.setup_extract method is not implemented')  # pragma: no cover
# 
#     def walk(self, state, element):
#         """
#         Walk a parsed element.
# 
#         Keyword Attributes:
#         state - A string specifying the current state
#         element - The element being walked
# 
#         Return is the new state
#         """
#         old_state = state
#         state, recurse = self.entering_element(state, element)
#         if state != old_state:
#             self.report_transition('entering', element, old_state, state)
#         if recurse and hasattr(element, 'children'):
#             for child in element.children:
#                 state = self.walk(state, child)
#         old_state = state
#         state = self.leaving_element(state, element)
#         if state != old_state:
#             self.report_transition('leaving', element, old_state, state)
#         return state
# 
#     def report_transition(self, phase, element, old_state, new_state):
#         """Report transitions, for debugging."""
#         if self.debug:  # pragma: no cover
#             print('In {}, state changed from "{}" to "{}" when {} {}'.format(
#                 self.extractor_name, old_state, new_state, phase, element))
# 
#     def entering_element(self, state, element):
#         """
#         Extract data (state or information) from entering an element.
# 
#         Return is a tuple of:
#             - The next state
#             - True if the element's children should be walked for extraction.
#         """
#         raise NotImplementedError(
#             '.entering_element method is not implemented')  # pragma: no cover
# 
#     def leaving_element(self, state, element):
#         """
#         Extract data (state or information) from leaving an element.
# 
#         Return is the next state.
#         """
#         raise NotImplementedError(
#             '.leaving_element method is not implemented')  # pragma: no cover
# 
#     def extracted_data(self):
#         """
#         Finalize the extracted data.
# 
#         Return is a dictionary of data items.
#         """
#         raise NotImplementedError(
#             '.extracted_data method is not implemented')  # pragma: no cover
# 
#     def is_tag(self, element, tag):
#         """Return True if element matches the tag."""
#         return getattr(element, 'tag', None) == tag


from .html import HnElement, HTMLElement, HTMLText
from .kumascript import (
    KumaScript, KumaVisitor, SpecName, Spec2, kumascript_grammar)
from .utils import join_content
from .visitor import Extractor
        self.name = visitor.section_name or ''

    def extract_spec2(self, td_element):
        reparsed = kumascript_grammar.parse(td_element.raw)
        visitor = Spec2Visitor(data=self.data, offset=td_element.start)
        visitor.visit(reparsed)
        self.issues.extend(visitor.issues)
        if visitor.mdn_key:
            # Standard Spec2 KumaScript - check for match
            spec2_key = visitor.mdn_key
            if spec2_key != self.key:
                self.add_issue(
                    'spec_mismatch', td_element, spec2_key=spec2_key,
                    specname_key=self.key)
        elif visitor.spec2_item:
            # Text like 'Standard' or non-standard KumaScript
            item = visitor.spec2_item
            if isinstance(item, HTMLText) and not isinstance(item, KumaScript):
                self.add_issue(
                    'spec2_converted', item, key=self.key,
                    original=item.cleaned)
        else:
            self.add_issue('spec2_omitted', td_element)

    def extract_specdesc(self, td_element):
        reparsed = kumascript_grammar.parse(td_element.raw)
        visitor = SpecDescVisitor(data=self.data, offset=td_element.start)
        visitor.visit(reparsed)
        self.issues.extend(visitor.issues)
        html = [item.to_html() for item in visitor.desc_items]

# Path: mdn/utils.py
# def join_content(content_bits):
#     """Construct a string with just the right whitespace."""
#     out = ''
#     nospace_before = '!,.;?[ '
#     nospace_after = ' '
#     for bit in content_bits:
#         if bit:
#             if (out and out[-1] not in nospace_after and
#                     bit[0] not in nospace_before):
#                 out += ' '
#             out += bit
#     return out
# 
# Path: mdn/visitor.py
# class Extractor(Recorder):
#     """Extracts information from parsed HTML.
# 
#     The Extractor works from trunk nodes to leaf nodes.
#     """
# 
#     extractor_name = 'Extractor'
# 
#     def initialize_extractor(self, elements=None, debug=False, **kwargs):
#         """Setup extractor plus common variables."""
#         self.initialize_tracker(**kwargs)
#         self.elements = elements or []
#         self.debug = debug
# 
#     def extract(self):
#         """Extract data from a parsed list of elements.
# 
#         This is used when you need sibling processing of a tree, rather than
#         subtree processing during parsing.
#         """
#         self.setup_extract()
#         state = 'begin'
#         for element in self.elements:
#             state = self.walk(state, element)
#         return self.extracted_data()
# 
#     def setup_extract(self):
#         """Setup the extraction state variables."""
#         raise NotImplementedError(
#             '.setup_extract method is not implemented')  # pragma: no cover
# 
#     def walk(self, state, element):
#         """
#         Walk a parsed element.
# 
#         Keyword Attributes:
#         state - A string specifying the current state
#         element - The element being walked
# 
#         Return is the new state
#         """
#         old_state = state
#         state, recurse = self.entering_element(state, element)
#         if state != old_state:
#             self.report_transition('entering', element, old_state, state)
#         if recurse and hasattr(element, 'children'):
#             for child in element.children:
#                 state = self.walk(state, child)
#         old_state = state
#         state = self.leaving_element(state, element)
#         if state != old_state:
#             self.report_transition('leaving', element, old_state, state)
#         return state
# 
#     def report_transition(self, phase, element, old_state, new_state):
#         """Report transitions, for debugging."""
#         if self.debug:  # pragma: no cover
#             print('In {}, state changed from "{}" to "{}" when {} {}'.format(
#                 self.extractor_name, old_state, new_state, phase, element))
# 
#     def entering_element(self, state, element):
#         """
#         Extract data (state or information) from entering an element.
# 
#         Return is a tuple of:
#             - The next state
#             - True if the element's children should be walked for extraction.
#         """
#         raise NotImplementedError(
#             '.entering_element method is not implemented')  # pragma: no cover
# 
#     def leaving_element(self, state, element):
#         """
#         Extract data (state or information) from leaving an element.
# 
#         Return is the next state.
#         """
#         raise NotImplementedError(
#             '.leaving_element method is not implemented')  # pragma: no cover
# 
#     def extracted_data(self):
#         """
#         Finalize the extracted data.
# 
#         Return is a dictionary of data items.
#         """
#         raise NotImplementedError(
#             '.extracted_data method is not implemented')  # pragma: no cover
# 
#     def is_tag(self, element, tag):
#         """Return True if element matches the tag."""
#         return getattr(element, 'tag', None) == tag


# Path: mdn/specifications.py
from .html import HnElement, HTMLElement, HTMLText
from .kumascript import (
    KumaScript, KumaVisitor, SpecName, Spec2, kumascript_grammar)
from .utils import join_content
from .visitor import Extractor

        self.name = visitor.section_name or ''

    def extract_spec2(self, td_element):
        reparsed = kumascript_grammar.parse(td_element.raw)
        visitor = Spec2Visitor(data=self.data, offset=td_element.start)
        visitor.visit(reparsed)
        self.issues.extend(visitor.issues)
        if visitor.mdn_key:
            # Standard Spec2 KumaScript - check for match
            spec2_key = visitor.mdn_key
            if spec2_key != self.key:
                self.add_issue(
                    'spec_mismatch', td_element, spec2_key=spec2_key,
                    specname_key=self.key)
        elif visitor.spec2_item:
            # Text like 'Standard' or non-standard KumaScript
            item = visitor.spec2_item
            if isinstance(item, HTMLText) and not isinstance(item, KumaScript):
                self.add_issue(
                    'spec2_converted', item, key=self.key,
                    original=item.cleaned)
        else:
            self.add_issue('spec2_omitted', td_element)

    def extract_specdesc(self, td_element):
        reparsed = kumascript_grammar.parse(td_element.raw)
        visitor = SpecDescVisitor(data=self.data, offset=td_element.start)
        visitor.visit(reparsed)
        self.issues.extend(visitor.issues)
        html = [item.to_html() for item in visitor.desc_items]

        self.desc = join_content(html)