Esempio n. 1
0
def action(elem, doc):
    if isinstance(elem, pf.Table):
        table = elem.caption.list[0].text
        headers = list(map(pf.stringify, elem.header.content))
        headers_sql = ",".join(headers)
        placeholders_sql = ",".join(["?"] * len(headers))
        doc.sql.execute(f"create table {table} ({headers_sql})")
        for row in elem.content:
            row_values = [pf.stringify(cell) for cell in row.content]
            doc.sql.execute(
                f"insert into {table}({headers_sql}) values ({placeholders_sql})",
                row_values,
            )
        return []
    if isinstance(elem, pf.CodeBlock):
        if elem.classes != ["pandocsql"]:
            return
        table = doc.sql.execute(elem.text)
        headers = [col[0] for col in table.description]
        rows = list(table)

        def c(t):
            return pf.TableCell(pf.Para(pf.Str(str(t))))

        def r(cs):
            return pf.TableRow(*list(map(c, cs)))

        return [pf.Table(*list(map(r, rows)), header=r(headers))]
Esempio n. 2
0
def csv_to_table_ast(options, data):
    """provided to panflute.yaml_filter to parse its content as pandoc table.
    """
    # prepare table in list from data/include
    table_list = read_csv(
        options.get('include', None),
        data,
        encoding=options.get('include-encoding', None),
        csv_kwargs=options.get('csv-kwargs', dict()),
    )

    # regularize table: all rows should have same length
    n_col = regularize_table_list(table_list)

    # Initialize the `options` output from `panflute.yaml_filter`
    width = get_width_wrap(options, n_col, table_list)

    # parse list to panflute table
    table_body = parse_table_list(options.get('markdown', False), table_list)
    del table_list
    # extract header row
    header_row = table_body.pop(0) if (
        len(table_body) > 1 and options.get('header', True)) else None

    # parse alignment
    alignment = parse_alignment(options.get('alignment', None), n_col)
    del n_col
    # get caption
    caption = get_caption(options)

    return panflute.Table(*table_body,
                          caption=caption,
                          alignment=alignment,
                          width=width,
                          header=header_row)
Esempio n. 3
0
def test_all():
    x=pf.Para(pf.Str("a"))
    y=pf.Para(pf.Str("b"))
    c1=pf.TableCell(x)
    c2=pf.TableCell(y)
    row=pf.TableRow(c1,c2)
    t1 = pf.Table(row)
    t2 = pf.Table(row, header=row)

    print(t1.header)
    print(t2.header)

    with io.StringIO() as f:
        pf.dump(pf.Doc(t1), f)
        print(f.getvalue())

    with io.StringIO() as f:
        pf.dump(pf.Doc(t2), f)
        print(f.getvalue())
Esempio n. 4
0
def finalize(doc):
	c1 = pf.TableCell(pf.Plain(pf.Str("Element")))
	c2 = pf.TableCell(pf.Plain(pf.Str("Frequency")))
	header = pf.TableRow(c1, c2)
	rows = []
	for tag in doc.counter:
		c1 = pf.TableCell(pf.Plain(pf.Str(tag)))
		c2 = pf.TableCell(pf.Plain(pf.Str(str(doc.counter[tag]))))
		rows.append(pf.TableRow(c1, c2))
	table = pf.Table(*rows, header=header)
	doc.content = [table] # bugbug?
Esempio n. 5
0
def convert2table(options, data, **__):
    """
    provided to panflute.yaml_filter to parse its content as pandoc table.
    """
    # prepare table in list from data/include
    raw_table_list = read_data(options.get('include', None), data)
    # delete element if table is empty (by returning [])
    # element unchanged if include is invalid (by returning None)
    try:
        assert raw_table_list and raw_table_list is not None
    except AssertionError:
        panflute.debug("pantable: table is empty or include is invalid")
        # [] means delete the current element; None means kept as is
        return raw_table_list
    # regularize table: all rows should have same length
    table_list, number_of_columns = regularize_table_list(raw_table_list)

    # Initialize the `options` output from `panflute.yaml_filter`
    # parse width
    width = get_width(options, number_of_columns)
    # auto-width when width is not specified
    if width is None:
        width = auto_width(get_table_width(options), number_of_columns,
                           table_list)
    # delete element if table is empty (by returning [])
    # width remains None only when table is empty
    try:
        assert width is not None
    except AssertionError:
        panflute.debug("pantable: table is empty")
        return []
    # parse alignment
    alignment = parse_alignment(options.get('alignment', None),
                                number_of_columns)
    header = options.get('header', True)
    markdown = options.get('markdown', False)

    # get caption: parsed as markdown into panflute AST if non-empty.
    caption = panflute.convert_text(str(
        options['caption']))[0].content if 'caption' in options else None
    # parse list to panflute table
    table_body = parse_table_list(markdown, table_list)
    # extract header row
    header_row = table_body.pop(0) if (len(table_body) > 1
                                       and header) else None
    return panflute.Table(*table_body,
                          caption=caption,
                          alignment=alignment,
                          width=width,
                          header=header_row)
Esempio n. 6
0
def fenced_action(options, data, element, doc):
    # We'll only run this for CodeBlock elements of class 'csv'
    title = options.get('title', 'Untitled Table')
    title = [pf.Str(title)]
    has_header = options.get('has-header', False)

    with io.StringIO(data) as f:
        reader = csv.reader(f)
        body = []
        for row in reader:
            cells = [pf.TableCell(pf.Plain(pf.Str(x))) for x in row]
            body.append(pf.TableRow(*cells))

    header = body.pop(0) if has_header else None
    table = pf.Table(*body, header=header, caption=title)
    return table
Esempio n. 7
0
def action(table, doc):
    if not isinstance(table, pf.Div) or 'tonytable' not in table.classes:
        return None

    rows = []

    kwargs = {}

    headers = []
    widths = []
    examples = []

    header = pf.Null()
    width = 0
    table.content.append(pf.HorizontalRule())
    for elem in table.content:
        if isinstance(elem, pf.Header):
            header, width = build_header(elem)
        elif isinstance(elem, pf.CodeBlock):
            headers.append(header)
            widths.append(width)
            header = pf.Null()
            width = 0

            examples.append(build_code(elem, doc.format))
        elif isinstance(elem, pf.HorizontalRule) and examples:
            if not all(isinstance(header, pf.Null) for header in headers):
                rows.append(build_row(headers))

            if 'width' not in kwargs:
                kwargs['width'] = widths

            rows.append(build_row(examples))

            headers = []
            widths = []
            examples = []
        else:
            pf.debug("[Warning] The following is ignored by a Tony Table:",
                     pf.stringify(elem))

    return pf.Table(*rows, **kwargs)
Esempio n. 8
0
def odoo2table_ast(options, data):
    """provided to panflute.yaml_filter to parse its content as pandoc table.
    """
    # prepare table in list from data/include
    table_list = read_data(
        options.get('url'),
        options.get('port', 80),
        options.get('database', options.get('url')),
        options.get('login'),
        options.get('password'),
        options.get('model'),
        options.get('fields'),
        options.get('domain', []),
        firstrow=data,
    )

    # regularize table: all rows should have same length
    n_col = regularize_table_list(table_list)

    # Initialize the `options` output from `panflute.yaml_filter`
    width = get_width_wrap(options, n_col, table_list)

    # parse list to panflute table
    table_body = parse_table_list(options.get('markdown', False), table_list)
    del table_list
    # extract header row
    header_row = table_body.pop(0) if (
        len(table_body) > 1 and options.get('header', True)) else None

    # parse alignment
    alignment = parse_alignment(options.get('alignment', None), n_col)
    del n_col
    # get caption
    caption = get_caption(options)

    return panflute.Table(*table_body,
                          caption=caption,
                          alignment=alignment,
                          width=width,
                          header=header_row)
Esempio n. 9
0
def proc_csv_table(elm, doc):
    if type(elm) == pf.CodeBlock and 'csv-table' in elm.classes:
        sys.stderr.write('csv-table #' + elm.identifier + '\n')
        attr = elm.attributes

        caption = attr.get('caption', None)
        if 'caption' in attr:
            del attr['caption']

        alignment = attr.get('alignment', None)
        if 'alignment' in attr:
            del attr['alignment']

        width = attr.get('width', None)
        if 'width' in attr:
            del attr['width']

        with io.StringIO(elm.text.replace('\r\n', '\n')) as dat:
            reader = csv.reader(dat, dialect=csv.excel, strict=True)
            body = []
            for row in reader:
                cells = [pf.TableCell(pf.Plain(pf.Str(x))) for x in row]
                body.append(pf.TableRow(*cells))

        if 'header' in attr:
            header = body.pop(0)
            del attr['header']
        else:
            header = None

        return pf.Div(
            # content
            pf.Table(*body,
                     header=header,
                     caption=caption,
                     alignment=alignment,
                     width=width),
            identifier=elm.identifier,
            classes=elm.classes,
            attributes=attr)
Esempio n. 10
0
def caps(elem, doc):
    data = getJson('data.json')
    if isinstance(elem, pf.RawBlock) and (elem.format == 'html'):
        if elem.text == "<!-- feedback -->":
            feedback = data[data['subject']+str(data['questionNumber'])]
            body = []
            i=0
            for item in feedback:
                cells = [str(i+1),item]
                cells = [pf.TableCell(pf.Plain(Str(cell))) for cell in cells]
                row = pf.TableRow(*cells)
            
                body.append(pf.TableBody(row))
                i=i+1

            cells = ['Nr.','Empfehlung']
            cells = [pf.TableCell(pf.Plain(Str(cell))) for cell in cells]
            row = pf.TableRow(*cells)
            head = pf.TableHead(row)

            width = [0.1,0.7]
            alignment = ['AlignDefault'] * len(width)
            caption = 'Empfehlungen'
            caption = pf.Caption(Para(Str(caption)))
            return pf.Div(pf.Table(*body, colspec=zip(alignment, width), caption=caption))
        
        if elem.text == "<!-- textelementen -->":
            subject = data[data['subject']+str(data['questionNumber'])+'_cna']
            body = []
            i=0
            for item in subject:
                cells = [item[0], item[1]]
                cells = [pf.TableCell(pf.Plain(Str(cell))) for cell in cells]
                row = pf.TableRow(*cells)
            
                body.append(pf.TableBody(row))
                i=i+1

            cells = ['Abschnitt','Schlusselwörter']
            cells = [pf.TableCell(pf.Plain(Str(cell))) for cell in cells]
            row = pf.TableRow(*cells)
            head = pf.TableHead(row)

            width = [0.16,0.7]
            alignment = ['AlignDefault'] * len(width)
            caption = 'Textelementen'
            caption = pf.Caption(Para(Str(caption)))
            return pf.Div(pf.Table(*body, colspec=zip(alignment, width), caption=caption))

        if elem.text == "<!-- unterschied -->":
            expert = data[data['subject']+str(data['questionNumber'])+'_expert_keyword']
            student = data[data['subject']+str(data['questionNumber'])+'_keyword']
            sorted_expert = sorted(expert, key = lambda k:k['degree'])
            sorted_student = sorted(student, key = lambda k:k['degree'])
            unterschied = []
            for e in expert:
                unterschied.append(e["displayName"]+"("+str(round(float(e["degree"])*100, 2))+")")
                
            for e in expert:
                inside = True
                for s in student:
                    if e['displayName'] == s['displayName']:
                        inside= False
                        break
                if not inside:
                    unterschied.append(e["displayName"]+"("+str(round(float(e["degree"])*100, 2))+")")
                
                break
            string =''
            if len(unterschied) == 1:
                string+= str(unterschied[0])
            elif len(unterschied)>1:
                string = unterschied[0]
                for index in range(1, len(unterschied)-1): 
                    string +=', '+ str(unterschied[index])

            body = []
            
            cells = [string]
            cells = [pf.TableCell(pf.Plain(Str(cell))) for cell in cells]
            row = pf.TableRow(*cells)
        
            body.append(pf.TableBody(row))
                

            

            width = [0.8]
            alignment = ['AlignDefault'] * len(width)
            caption = 'Textelementen'
            caption = pf.Caption(Para(Str(caption)))
            return pf.Div(pf.Table(*body, colspec=zip(alignment, width), caption=caption))


        if elem.text == "- gemeinsam -":
            expert = data[data['subject']+str(data['questionNumber'])+'_expert_keyword']
            student = data[data['subject']+str(data['questionNumber'])+'_keyword']
            sorted_expert = sorted(expert, key = lambda k:k['degree'])
            sorted_student = sorted(student, key = lambda k:k['degree'])
            gemeinsam = []
            for e in expert:
                for s in student:
                    if e['displayName'] == s['displayName']:
                        gemeinsam.append(e["displayName"]+"("+str(round(float(e["degree"])*100, 2))+")")
                    break
                else:
                    continue
                break
            string =''
            gemeinsam = [x["displayName"]+"("+str(round(float(x["degree"])*100, 2))+")" for x in expert+student if (any(e['displayName'])==x['displayName'] for e in  expert) and (any(s['displayName'])==x['displayName'] for s in student)]
            if len(gemeinsam) == 1:
                string+= gemeinsam[0]
            elif len(gemeinsam)>1:
                string = gemeinsam[0]
                for index in range(1, len(gemeinsam)-1): 
                    string +=', '+ gemeinsam[index]

            return string

    if type(elem) == Str: 
        if elem.text == "-topicName-":
            subject = data['subject'] +" Frage nummer " + str(data['questionNumber'])
            elem.text = subject
            return elem
        
        if elem.text == "-textelementen-":
            subject = data[data['subject']+str(data['questionNumber'])+'_cna']
            subject = subject.replace("_", " ")
            elem.text = subject
            return elem
        
        if elem.text == "-question_number-":
            feedback = str(data['questionNumber'])
            elem.text = feedback
            return elem

        if elem.text == "-gemeinsam-":
            expert = data[data['subject']+str(data['questionNumber'])+'_expert_keyword']
            student = data[data['subject']+str(data['questionNumber'])+'_keyword']
            sorted_expert = reversed(sorted(expert, key = lambda k:k['degree']))
            sorted_student = reversed(sorted(student, key = lambda k:k['degree']))
            
            string =''
            list_of_all_values = [value for elem in sorted_student
                      for value in elem.values()]
            gemeinsam = [x["displayName"] for x in sorted_expert if x['displayName'] in list_of_all_values]
            if len(gemeinsam) == 1:
                string+= gemeinsam[0]
            elif len(gemeinsam)>1:
                string = gemeinsam[0]
                for index in range(1, len(gemeinsam)-1): 
                    string +=', '+ gemeinsam[index]
            elem.text = string
            return elem

        if elem.text == "-unterschied1-":
            expert = data[data['subject']+str(data['questionNumber'])+'_expert_keyword']
            student = data[data['subject']+str(data['questionNumber'])+'_keyword']
            sorted_expert = reversed(sorted(expert, key = lambda k:k['degree']))
            sorted_student = reversed(sorted(student, key = lambda k:k['degree']))
            
            string =''
            list_of_all_values = [value for elem in sorted_student
                      for value in elem.values()]
            gemeinsam = [x["displayName"] for x in sorted_expert if x['displayName'] not in list_of_all_values]
            if len(gemeinsam) == 1:
                string+= gemeinsam[0]
            elif len(gemeinsam)>1:
                string = gemeinsam[0]
                for index in range(1, len(gemeinsam)-1): 
                    string +=', '+ gemeinsam[index]
            elem.text = string
            return elem

        if elem.text == "-unterschied2-":
            expert = data[data['subject']+str(data['questionNumber'])+'_expert_keyword']
            student = data[data['subject']+str(data['questionNumber'])+'_keyword']
            sorted_expert = reversed(sorted(expert, key = lambda k:k['degree']))
            sorted_student = reversed(sorted(student, key = lambda k:k['degree']))
            
            string =''
            list_of_all_values = [value for elem in sorted_expert
                      for value in elem.values()]
            gemeinsam = [x["displayName"] for x in sorted_student if x['displayName'] not in list_of_all_values]
            if len(gemeinsam) == 1:
                string+= gemeinsam[0]
            elif len(gemeinsam)>1:
                string = gemeinsam[0]
                for index in range(1, len(gemeinsam)-1): 
                    string +=', '+ gemeinsam[index]
            elem.text = string
            return elem

        if elem.text == "-expert-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_expert_keyword.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_expert_keyword.png'):
                return None

            return Image(alt, url=src, title='')

        if elem.text == "-student-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_keyword.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_keyword.png'):
                return None

            return Image(alt, url=src, title='')

        if elem.text == "-content-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_content.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_content.png'):
                return None

            return Image(alt, url=src, title='')
        
        if elem.text == "-heat-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_content_heat.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_content_heat.png'):
                return None

            return Image(alt, url=src, title='')
        
        if elem.text == "-topic-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_topic.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_topic.png'):
                return None

            return Image(alt, url=src, title='')

        if elem.text == "-argument-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_argument.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_argument.png'):
                return None

            return Image(alt, url=src, title='')
        
        if elem.text == "-wordtovec-":
            caption = "caption"
            src = 'rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_word2vec.png'
            alt = Str(caption)

            if not os.path.isfile('rb_api/pandoc_filters/images/'+data['subject']+str(data['questionNumber'])+'_cna_word2vec.png'):
                return None

            return Image(alt, url=src, title='')
Esempio n. 11
0
def cmptable(table, doc):
    """
    Comparison Tables: Code blocks are the first-class entities that get added
    to the table. Each code block is pushed onto the current row.
    A horizontal rule (`---`) is used to move to the next row.

    In the first row, the last header (if any) leading upto the i'th
    code block is the header for the i'th column of the table.

    The last block quote (if any) is used as the caption.

    # Example

    ::: cmptable

    > compare inspect of unconstrained and constrained types

    ### Before
    ```cpp
    std::visit([&](auto&& x) {
      strm << "got auto: " << x;
    }, v);
    ```

    ### After
    ```cpp
    inspect (v) {
      <auto> x: strm << "got auto: " << x;
    }
    ```

    ---

    ```cpp
    std::visit([&](auto&& x) {
      using X = std::remove_cvref_t<decltype(x)>;
      if constexpr (C1<X>()) {
        strm << "got C1: " << x;
      } else if constexpr (C2<X>()) {
        strm << "got C2: " << x;
      }
    }, v);
    ```

    ```cpp
    inspect (v) {
      <C1> c1: strm << "got C1: " << c1;
      <C2> c2: strm << "got C2: " << c2;
    }
    ```

    :::

    # Generates

    Table: compare inspect of unconstrained and constrained types

    +------------------------------------------------+---------------------------------------------+
    | __Before__                                     | __After__                                   |
    +================================================+=============================================+
    | ```cpp                                         | ```cpp                                      |
    | std::visit([&](auto&& x) {                     | inspect (v) {                               |
    |   strm << "got auto: " << x;                   |   <auto> x: strm << "got auto: " << x;      |
    | }, v);                                         | }                                           |
    |                                                | ```                                         |
    +------------------------------------------------+---------------------------------------------+
    | std::visit([&](auto&& x) {                     | ```cpp                                      |
    |   using X = std::remove_cvref_t<decltype(x)>;  | inspect (v) {                               |
    |   if constexpr (C1<X>()) {                     |   <C1> c1: strm << "got C1: " << c1;        |
    |     strm << "got C1: " << x;                   |   <C2> c2: strm << "got C2: " << c2;        |
    |   } else if constexpr (C2<X>()) {              | }                                           |
    |     strm << "got C2: " << x;                   | ```                                         |
    |   }                                            |                                             |
    | }, v);                                         |                                             |
    +------------------------------------------------+---------------------------------------------+
    """

    if not isinstance(table, pf.Div):
        return None

    if not any(cls in table.classes for cls in ['cmptable', 'tonytable']):
        return None

    rows = []
    kwargs = {}

    headers = []
    widths = []
    examples = []

    header = pf.Null()
    caption = None
    width = 0

    first_row = True
    table.content.append(pf.HorizontalRule())

    def warn(elem):
        pf.debug('mpark/wg21:', type(elem), pf.stringify(elem, newlines=False),
                 'in a comparison table is ignored')

    for elem in table.content:
        if isinstance(elem, pf.Header):
            if not isinstance(header, pf.Null):
                warn(header)

            if first_row:
                header = pf.Plain(*elem.content)
                width = float(elem.attributes['width']) if 'width' in elem.attributes else 0
            else:
                warn(elem)
        elif isinstance(elem, pf.BlockQuote):
            if caption is not None:
                warn(caption)

            caption = elem
        elif isinstance(elem, pf.CodeBlock):
            if first_row:
                headers.append(header)
                widths.append(width)

                header = pf.Null()
                width = 0

            examples.append(elem)
        elif isinstance(elem, pf.HorizontalRule) and examples:
            first_row = False

            rows.append(pf.TableRow(*[pf.TableCell(example) for example in examples]))
            examples = []
        else:
            warn(elem)

    if not all(isinstance(header, pf.Null) for header in headers):
        kwargs['header'] = pf.TableRow(*[pf.TableCell(header) for header in headers])

    if caption is not None:
        kwargs['caption'] = caption.content[0].content

    kwargs['width'] = widths

    return pf.Table(*rows, **kwargs)
Esempio n. 12
0
def convert2table(options, data, doc, element):
    """
    provided to pf.yaml_filter to parse its content as pandoc table.
    """
    logstring("convert2table: received " + str(options) + ":" + str(data), doc)
    # prepare table in list from data/include
    raw_table_list = read_data(options.get("include", None), data, doc)
    # delete element if table is empty (by returning [])
    # element unchanged if include is invalid (by returning None)
    try:
        assert raw_table_list and raw_table_list is not None
    except AssertionError:
        logstring("pantable: table is empty or include is invalid", doc)
        # [] means delete the current element; None means kept as is
        return raw_table_list
    # regularize table: all rows should have same length
    table_list, number_of_columns = regularize_table_list(raw_table_list, doc)

    # Initialize the `options` output from `pf.yaml_filter`
    # parse width
    width = get_width(options, number_of_columns, doc)
    # auto-width when width is not specified
    if width is None:
        width = auto_width(get_table_width(options, doc), number_of_columns,
                           table_list, doc)
    # delete element if table is empty (by returning [])
    # width remains None only when table is empty
    try:
        assert width is not None
    except AssertionError:
        logstring("pantable: table is empty", doc)
        return []
    # parse alignment
    alignment = parse_alignment(options.get("alignment", None),
                                number_of_columns, doc)
    header = options.get("header", True)
    markdown = options.get("markdown", True)  # Boaz: change default to True

    # get caption: parsed as markdown into panflute AST if non-empty.
    caption_ = options.get("caption", "")
    caption = pf.convert_text(caption_)[0].content if caption_ else None
    # parse list to panflute table
    table_body = parse_table_list(markdown, table_list, doc)
    # extract header row
    header_row = table_body.pop(0) if (len(table_body) > 1
                                       and header) else None
    T = pf.Table(
        *table_body,
        caption=caption,
        alignment=alignment,
        width=width,
        header=header_row,
    )
    id = options.get("identifier", options.get("id", ""))
    if not id:
        return T
    if doc.format == "latex":
        return [T, pf.Para(pf.RawInline(fr"\label{{{id}}}", format="latex"))]
    if doc.format == "html":
        return [
            pf.Para(pf.RawInline(fr'<a name="{id}"></a>', format="html")), T
        ]
    return T
Esempio n. 13
0
def action(element, doc):
    """
    return None -> element unchanged
    return [] -> delete element
    """
    if not isinstance(element, pf.Div):
        return None
    if not "divtable" in element.classes:
        return None

    rows = []
    headers = []
    header_found = False
    widths = []
    aligns = []
    caption = None
    for tbl_el in element.content:

        if isinstance(tbl_el, pf.Div) and "thead" in tbl_el.classes:
            headers = []
            assert isinstance(
                tbl_el.content[0],
                pf.Para), "the table header div must contain a paragraph"
            for head_el in tbl_el.content[0].content:

                if isinstance(head_el, pf.Span):
                    if list(head_el.content):
                        header_found = True
                    headers.append(pf.TableCell(pf.Plain(*head_el.content)))
                    if "width" in head_el.attributes:
                        widths.append(float(head_el.attributes["width"]))
                    else:
                        widths.append(0)
                    if "align" in head_el.attributes:
                        align = str(head_el.attributes["align"]).capitalize()
                        assert align in [
                            "Left", "Right", "Center", "Default"
                        ], "table alignment must be one of left, right, center or default"
                        aligns.append("Align" + align)
                    else:
                        aligns.append("AlignDefault")

        elif isinstance(tbl_el, pf.Div) and "tcaption" in tbl_el.classes:
            assert isinstance(
                tbl_el.content[0],
                pf.Para), "the table caption div must contain a paragraph"
            caption = list(tbl_el.content[0].content)

        elif isinstance(tbl_el, pf.Div) and "trow" in tbl_el.classes:
            row = []
            for row_el in tbl_el.content:
                if isinstance(row_el, pf.Div) and "tcell" in row_el.classes:
                    col = []
                    for col_el in row_el.content:
                        col.append(col_el)
                    row.append(pf.TableCell(*col))

            rows.append(pf.TableRow(*row))

        else:
            pass

    kwargs = {}
    if header_found:
        kwargs["header"] = pf.TableRow(*headers)
    if widths:
        kwargs["width"] = widths
    if aligns:
        kwargs["alignment"] = aligns
    if not caption is None:
        kwargs["caption"] = caption

    return pf.Table(*rows, **kwargs)
Esempio n. 14
0
    def convert(self):
        doc = panflute.Doc(
            api_version=(1, 17, 5),
            metadata={
                'pagetitle': self.title,
            },
        )

        doc.content.append(panflute.Header(panflute.Str(self.title)))

        lists = {}
        tables = {}
        table_rows = {}
        table_cells = {}

        for chunk in self._attr_chunks():
            self.logger.debug(chunk)
            container = panflute.Para()
            cdiv = panflute.Div(container)

            # Handle lists
            if 'list_class' in chunk[0]['attrs']:
                lc = chunk[0]['attrs']['list_class']
                check_state = None
                if lc in ['checked', 'unchecked']:
                    check_state = lc
                    lc = 'checklist'
                ld = chunk[0]['attrs']['list_depth']

                # prune any lists that are lower than us, they're finished
                for i in list(lists.keys()):
                    if i > ld:
                        lists.pop(i)

                # non-homogenous list types can be immediately adjacent without
                # ending up merged
                if ld in lists and lists[ld]['class'] != lc:
                    lists.pop(ld)

                # checklists are a special case, they can't contain other lists
                if lc != 'checklist' and lists and lists[1][
                        'class'] == 'checklist':
                    lists = {}

                # make sure any intermediate lists were created, including
                # the top level because boxnotes
                for i in range(1, ld + 1):
                    if i not in lists:
                        lists[i] = self._list(lc, i)
                        if i != ld:
                            lists[i]['pf'].content.append(panflute.ListItem())
                        lp = lists[i]['pf']
                        if lc == 'checklist':
                            lp = panflute.Div(lp, classes=['checklist'])
                        if i == 1:
                            doc.content.append(lp)
                        else:
                            lists[i - 1]['pf'].content[-1].content.append(lp)

                # set the container for the other subchunks
                container = panflute.Plain()
                cdiv.content = [container]
                cdiv.classes.append(lc)
                if check_state:
                    cdiv.classes.append(check_state)
                lists[ld]['pf'].content.append(panflute.ListItem(cdiv))

                if check_state == 'checked':
                    container.content.append(panflute.Str(CHECKED))
                elif check_state == 'unchecked':
                    container.content.append(panflute.Str(UNCHECKED))

            elif 'table_id' in chunk[-1]['attrs']:
                table_id = chunk[-1]['attrs']['table_id']
                row_id = chunk[-1]['attrs']['table_row']
                cell_id = row_id + chunk[-1]['attrs']['table_col']

                if table_id not in tables:
                    # There's some magic in the constructor for panflute tables
                    # that isn't exposed in any other way, so we can't create
                    # the table until we've finished populating the rows.
                    # Instead, use a placeholder div to locate it within the
                    # document.
                    tables[table_id] = {
                        'div': panflute.Div(),
                        'rows': [],
                    }
                    doc.content.append(tables[table_id]['div'])
                if row_id not in table_rows:
                    table_rows[row_id] = panflute.TableRow()
                    tables[table_id]['rows'].append(table_rows[row_id])
                if cell_id not in table_cells:
                    cdiv = panflute.Div(panflute.Plain())
                    table_cells[cell_id] = panflute.TableCell(cdiv)
                    table_rows[row_id].content.append(table_cells[cell_id])
                container = table_cells[cell_id].content[0].content[0]

            else:
                lists = {}
                doc.content.append(cdiv)

            if 'align' in chunk[0]['attrs']:
                cdiv.attributes['style'] = 'text-align: ' + chunk[0]['attrs'][
                    'align'] + ';'

            for subchunk in chunk:
                if subchunk['newlines'] > 1:
                    # we've had an extra linebreak, no more adding on to lists
                    lists = {}

                # don't do anything with markers
                if subchunk['text'] == '*' and 'lmkr' in subchunk['attrs']:
                    continue

                scont = container
                if 'href' in subchunk['attrs']:
                    scont = panflute.Link(url=subchunk['attrs']['href'])
                    container.content.append(scont)

                if 'image' in subchunk['attrs']:
                    scont.content.append(
                        panflute.Image(
                            url=self._image(subchunk['attrs']['author'],
                                            subchunk['attrs']['image'])))
                    continue

                span = panflute.Span()
                lines = subchunk['text'].splitlines()
                while lines:
                    subtext = lines.pop(0)
                    span.content.append(panflute.Str(subtext))
                    if lines:
                        span.content.append(panflute.LineBreak())

                if 'font' in subchunk['attrs']:
                    color = subchunk['attrs']['font'].get('color', '000000')
                    size = subchunk['attrs']['font'].get('size', 'medium')
                    span.classes.append('font-size-' + size)
                    span.classes.append('font-color-' + color)

                    # I don't actually know what the possible colors are and I
                    # don't feel like finding out, so just inject it as an
                    # inline style.
                    if color != '000000':
                        span.attributes['style'] = 'color: #' + color + ';'

                if subchunk['attrs'].get('underline'):
                    span.classes.append('underline')
                if subchunk['attrs'].get('bold'):
                    span = panflute.Strong(span)
                if subchunk['attrs'].get('italic'):
                    span = panflute.Emph(span)
                if subchunk['attrs'].get('strikethrough'):
                    span = panflute.Strikeout(span)
                scont.content.append(span)

        # Actually create the tables
        for x in tables:
            tables[x]['div'].content.append(panflute.Table(*tables[x]['rows']))

        with io.StringIO() as f:
            panflute.dump(doc, f)
            return f.getvalue()
Esempio n. 15
0
def fenced_action(options, data, element, doc):
	# We'll only run this for CodeBlock elements of class 'table'
	caption     = options.get('caption', 'Untitled Table')
	#caption     = [pf.Str(caption)]
	filepath    = options.get('file')
	has_header  = options.get('header', True)
	width       = options.get('width', 1)
	total_width = float(options.get('total_width', .8))
	align       = options.get('align', 'default')
	nrows       = options.get('rows', 0)
	ncols       = options.get('cols', 0)
	csvargs     = options.get('csvargs', {})
	dtargs      = options.get('dtargs', {})
	mediadir    = doc.get_metadata('mediadir')

	csvargs['dialect']   = csvargs.get('dialect', "unix")
	csvargs['delimiter'] = csvargs.get('delimiter', "\t").encode().decode('unicode_escape')

	f = io.StringIO(data) if data else open(filepath)
	try:
		reader = csv.reader(f, **csvargs)
		body = []
		for i, row in enumerate(reader):
			if nrows and i > nrows:
				continue
			cells = [	pf.TableCell(formatCell(x))
						for k, x in enumerate(row) if not ncols or k < ncols]
			body.append(pf.TableRow(*cells))
	finally:
		f.close()

	ncols = min(ncols, len(row)) if ncols else len(row)
	if has_header:
		header = body.pop(0)
		if body and len(body[0].content) == len(header.content) + 1:
			header.content.insert(0, pf.TableCell(pf.Plain(pf.Str(''))))
	elif nrows:
		header = None
		body = body[:nrows]

	if not isinstance(width, list):
		width = [width]
	if len(width) == 1 and ncols:
		width = width * ncols
	sumwidth    = float(sum(width))
	total_width = min(total_width, 1)
	width       = [float(wid)*float(total_width)/sumwidth for wid in width]
	if not isinstance(align, list):
		align = [align]
	if len(align) == 1 and ncols:
		align = align * ncols
	align = ['Align' + al.capitalize() for al in align]

	if mediadir and filepath:
		# copy file to mediadir and check if file exists
		filepath = Path(filepath)
		mediadir = Path(mediadir)
		mediadir.mkdir(exist_ok = True, parents = True)
		destfile = mediadir / filepath.name
		destfile = _copyfile(filepath, destfile)

		caption = [pf.Link(	pf.Str(caption),
							url = str(destfile.relative_to(destfile.parent.parent)),
							title = 'Right clink and "Save link as" to download whole table.',
							attributes = {'target': '_blank'})]
	else:
		caption = [pf.Str(caption)]

	table = pf.Table(*body,
		header=header, caption=caption, width=width, alignment = align)
	if dtargs is False:
		return pf.Div(table, classes = ['tablewrapper'])
	else:
		return pf.Div(table, classes = ['tablewrapper', 'datatablewrapper'], attributes = {
			'data-datatable': json.dumps(dtargs)
		})
Esempio n. 16
0
def tonytable(table, doc):
    """
    Tony Tables: CodeBlocks are the first-class entities that get added
    to the table. The last (if any) header leading upto a CodeBlock is
    the header that gets attached to the table cell with the CodeBlock.

    Each CodeBlock entry is pushed onto the current row. Horizontal rule
    is used to move to the next row.

    # Example

    ::: tonytable

    ### Before
    ```cpp
    std::visit([&](auto&& x) {
      strm << "got auto: " << x;
    }, v);
    ```

    ### After
    ```cpp
    inspect (v) {
      <auto> x: strm << "got auto: " << x;
    }
    ```

    ---

    ```cpp
    std::visit([&](auto&& x) {
      using X = std::remove_cvref_t<decltype(x)>;
      if constexpr (C1<X>()) {
        strm << "got C1: " << x;
      } else if constexpr (C2<X>()) {
        strm << "got C2: " << x;
      }
    }, v);
    ```

    ```cpp
    inspect (v) {
      <C1> c1: strm << "got C1: " << c1;
      <C2> c2: strm << "got C2: " << c2;
    }
    ```

    :::

    # Generates

    +------------------------------------------------+-------------------------------------------------+
    | __Before__                                     | __After__                                       |
    +------------------------------------------------+-------------------------------------------------+
    | ```cpp                                         | ```cpp                                          |
    | std::visit([&](auto&& x) {                     | inspect (v) {                                   |
    |   strm << "got auto: " << x;                   |   <auto> x: strm << "got auto: " << x;          |
    | }, v);                                         | }                                               |
    |                                                | ```                                             |
    +------------------------------------------------+-------------------------------------------------+
    | std::visit([&](auto&& x) {                     | ```cpp                                          |
    |   using X = std::remove_cvref_t<decltype(x)>;  | inspect (v) {                                   |
    |   if constexpr (C1<X>()) {                     |   <C1> c1: strm << "got C1: " << c1;            |
    |     strm << "got C1: " << x;                   |   <C2> c2: strm << "got C2: " << c2;            |
    |   } else if constexpr (C2<X>()) {              | }                                               |
    |     strm << "got C2: " << x;                   | ```                                             |
    |   }                                            |                                                 |
    | }, v);                                         |                                                 |
    +------------------------------------------------+-------------------------------------------------+
    """
    def build_header(elem):
        # We use a `pf.RawInline` here because setting the `align`
        # attribute on `pf.Div` does not work for some reason.
        header = pf.Plain(pf.RawInline('<div align="center">', 'html'),
                          pf.Strong(*elem.content),
                          pf.RawInline('</div>', 'html'))
        width = float(
            elem.attributes['width']) if 'width' in elem.attributes else 0
        return header, width

    def build_code(elem, format):
        if (format != 'gfm'):
            return elem
        lang = ' lang="{}"'.format(elem.classes[0]) if elem.classes else ''
        code = html.escape(elem.text)
        return pf.RawBlock('\n\n<pre{lang}>\n{code}\n</pre>'.format(lang=lang,
                                                                    code=code))

    def build_row(elems):
        return pf.TableRow(*[pf.TableCell(elem) for elem in elems])

    if not isinstance(table, pf.Div) or 'tonytable' not in table.classes:
        return None

    rows = []

    kwargs = {}

    headers = []
    widths = []
    examples = []

    header = pf.Null()
    width = 0
    table.content.append(pf.HorizontalRule())
    for elem in table.content:
        if isinstance(elem, pf.Header):
            header, width = build_header(elem)
        elif isinstance(elem, pf.CodeBlock):
            headers.append(header)
            widths.append(width)
            header = pf.Null()
            width = 0

            examples.append(build_code(elem, doc.format))
        elif isinstance(elem, pf.HorizontalRule) and examples:
            if not all(isinstance(header, pf.Null) for header in headers):
                rows.append(build_row(headers))

            if 'width' not in kwargs:
                kwargs['width'] = widths

            rows.append(build_row(examples))

            headers = []
            widths = []
            examples = []
        else:
            pf.debug("[Warning] The following is ignored by a Tony Table:",
                     pf.stringify(elem))

    return pf.Table(*rows, **kwargs)
Esempio n. 17
0
def columns(elem, doc):
    ## Desactivar para pandoc nuevo
    if type(
            elem
    ) == pf.Div and 'columns' in elem.classes and not doc.pandoc_columns:
        ## Eliminar de elem.classes
        if doc.disable_columns:
            elem.classes.remove('columns')
        doc.column_count = 0
        doc.prev_column = None
        #pf.debug("Entra")
        ## Process column attributes
        if "width" in elem.attributes:
            doc.columns_width = Dimension(elem.attributes["width"])
        else:
            doc.columns_width = Dimension("600px")

        if "colsep" in elem.attributes:
            doc.columns_sep = Dimension(elem.attributes["colsep"])
        else:
            doc.columns_sep = Dimension("0pt")

        to_patch = doc.columns_to_patch  ## Keep track of object
        doc.columns_to_patch = []  ## Clean columns to patch
        if doc.format == 'beamer':
            left = pf.RawBlock('\\begin{columns}', format='latex')
            right = pf.RawBlock('\\end{columns}', format='latex')
            if doc.columns_sep.width != 0:
                rep_text = '\\hspace{' + doc.columns_sep.to_latex() + '}'
            else:
                rep_text = '% no sep'
            for col in to_patch:
                col.text = col.text.replace("COLSEP", rep_text)
            elem.content = [left] + list(elem.content) + [right]
            return elem
        elif html_format(doc.format):
            elem.attributes[
                "style"] = "style=width:" + doc.columns_width.to_html(
                ) + ";margin:0 auto;line-break-after: always;"
            #elem.content = list(elem.content) + [pf.RawBlock('<br/>', format='html')]
            if doc.columns_sep.width != 0:
                rep_text = doc.columns_sep.to_html()
            else:
                rep_text = '2px'
            #Patch column HTML attributes
            for col in to_patch:
                col.attributes["style"] = col.attributes["style"].replace(
                    "COLSEP", rep_text)
            return [
                elem,
                pf.RawBlock('<br style=\"clear:both\"/>', format='html')
            ]
        elif doc.format == 'latex':
            left = pf.RawBlock('\\begin{center}', format='latex')
            right = pf.RawBlock('\\end{center}', format='latex')
            if doc.columns_sep.width != 0:
                rep_text = '\\hspace{' + doc.columns_sep.to_latex() + '}%\n'
            else:
                rep_text = ''
            for col in to_patch:
                col.text = col.text.replace("COLSEP", rep_text)

            elem.content = [left] + list(elem.content) + [right]
            return
        elif doc.format == 'docx':
            row = pf.TableRow()
            for col in to_patch:
                row.content.append(col)
            rows = [row]
            return pf.Table(*rows)
        else:
            return
    elif type(
            elem
    ) == pf.Div and 'column' in elem.classes and not doc.pandoc_columns:
        ## Eliminar de elem.classes
        if doc.disable_columns:
            elem.classes.remove('column')
        doc.column_count = doc.column_count + 1
        if "width" in elem.attributes:
            width = Dimension(elem.attributes["width"])
        else:
            width = Dimension("50%")

        if doc.format == 'beamer':
            left = pf.RawBlock('\\begin{column}{' + width.to_latex() + '}',
                               format='latex')
            right = pf.RawBlock('\\end{column}', format='latex')
            if doc.column_count > 1:
                rb = pf.RawBlock('COLSEP', format='latex')
                doc.columns_to_patch.append(rb)
                elem.content = [rb] + [left] + list(elem.content) + [right]
            else:
                elem.content = [left] + list(elem.content) + [right]
            return elem
        elif html_format(doc.format):
            if doc.column_count > 1:
                fval = "left"  #"right"
            else:
                fval = "left"
            elem.attributes["style"] = "style=width:" + width.to_html(
            ) + ";float:" + fval + ';margin-right:COLSEP'
            doc.columns_to_patch.append(elem)
            return
        elif doc.format == 'latex':
            if doc.prev_column == None:
                left = pf.RawBlock('\\begin{minipage}{' + width.to_latex() +
                                   '}',
                                   format='latex')
                right = pf.RawBlock('\\end{minipage}', format='latex')
                elem.content = [left] + list(elem.content) + [right]
            else:
                closing_minipage = doc.prev_column.content[
                    -1]  ## Last item ...
                closing_minipage.text = '\\end{minipage} %\nCOLSEP\\begin{minipage}{' + width.to_latex(
                ) + '}'
                right = pf.RawBlock('\\end{minipage}', format='latex')
                doc.columns_to_patch.append(closing_minipage)
                elem.content = list(elem.content) + [right]
            doc.prev_column = elem
            return elem
        elif doc.format == 'docx':
            obj = pf.TableCell(*elem.content)
            doc.columns_to_patch.append(obj)
            return elem
        else:
            return