Example #1
0
static void Word_postProcessHTML(WordConverter *conv, DFNode *node)
{
    DFNode *next;
    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;

        switch (child->tag) {
            case HTML_SPAN: {
                const char *className = DFGetAttribute(child,HTML_CLASS);
                if (DFStringEquals(className,DFBookmarkClass)) {
                    if (child->first != NULL)
                        next = child->first;
                    DFRemoveNodeButKeepChildren(child);
                }
                break;
            }
            case HTML_CAPTION: {
                const char *counterName = NULL;

                if ((child->prev != NULL) && (child->prev->tag == HTML_FIGURE) &&
                    (DFChildWithTag(child->prev,HTML_FIGCAPTION) == NULL)) {
                    child->tag = HTML_FIGCAPTION;
                    counterName = "figure";
                    DFAppendChild(child->prev,child);
                }
                else if ((child->prev != NULL) && (child->prev->tag == HTML_TABLE) &&
                         (DFChildWithTag(child->prev,HTML_CAPTION) == NULL)) {
                    counterName = "table";
                    DFInsertBefore(child->prev,child,child->prev->first);
                }
                else if ((child->next != NULL) && (child->next->tag == HTML_FIGURE) &&
                         (DFChildWithTag(child->next,HTML_FIGCAPTION) == NULL)) {
                    child->tag = HTML_FIGCAPTION;
                    counterName = "figure";
                    DFInsertBefore(child->next,child,child->next->first);
                }
                else if ((child->next != NULL) && (child->next->tag == HTML_TABLE) &&
                         (DFChildWithTag(child->next,HTML_CAPTION) == NULL)) {
                    counterName = "table";
                    DFSetAttribute(child,HTML_STYLE,"caption-side: top");
                    DFInsertBefore(child->next,child,child->next->first);
                }

                if (counterName != NULL) {
                    char *beforeText = extractPrefix(child,counterName);
                    if (beforeText != NULL) {
                        CSSStyle *style = CSSSheetLookupElement(conv->styleSheet,DFNodeName(child),NULL,1,0);
                        if (CSSGet(CSSStyleBefore(style),"content") == NULL) {
                            CSSPut(CSSStyleRule(style),"counter-increment",counterName);
                            CSSPut(CSSStyleBefore(style),"content",beforeText);
                        }
                    }
                    free(beforeText);
                }
                break;
            }
            case HTML_NAV: {
                if (HTML_isParagraphTag(node->tag)) {

                    if (child->prev != NULL) {
                        DFNode *beforeP = DFCreateElement(conv->package->document,node->tag);
                        while (child->prev != NULL)
                            DFInsertBefore(beforeP,child->prev,beforeP->first);
                        DFInsertBefore(node->parent,beforeP,node);
                    }
                    DFInsertBefore(node->parent,child,node);

                    if ((node->first == NULL) ||
                        ((node->first->tag == HTML_BR) && (node->first->next == NULL))) {
                        DFRemoveNode(node);
                        return;
                    }
                    next = NULL;
                }
                break;
            }
        }
    }

    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;
        Word_postProcessHTML(conv,child);
    }
}
static void adjustMarginLeft(DFNode *element, double adjustPct, int noTextIndent)
{
    if ((element->tag != HTML_TABLE) && !HTML_isParagraphTag(element->tag))
        return;;

    const char *cssText = DFGetAttribute(element,HTML_STYLE);
    CSSProperties *properties = CSSPropertiesNewWithString(cssText);

    double oldMarginLeft = 0;
    if (CSSGet(properties,"margin-left") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"margin-left"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            oldMarginLeft = length.value;

        if (CSSGet(properties,"width") != NULL) {
            CSSLength length = CSSLengthFromString(CSSGet(properties,"width"));
            if (CSSLengthIsValid(length) && (length.units == UnitsPct)) {
                double oldWidth = length.value;
                double newWidth = oldWidth + oldMarginLeft;
                char buf[100];
                CSSPut(properties,"width",DFFormatDoublePct(buf,100,newWidth));
            }
        }
    }

    double oldTextIndent = 0;
    if (CSSGet(properties,"text-indent") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"text-indent"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            oldTextIndent = length.value;
    }

    double newMarginLeft = oldMarginLeft + adjustPct;
    double newTextIndent = oldTextIndent;

    if (newMarginLeft < 0)
        newMarginLeft = 0;
    if (fabs(newMarginLeft) >= 0.01) {
        char buf[100];
        CSSPut(properties,"margin-left",DFFormatDoublePct(buf,100,newMarginLeft));
    }
    else {
        CSSPut(properties,"margin-left",NULL);
    }

    if (noTextIndent) {
        CSSPut(properties,"text-indent",NULL);
    }
    else if (newTextIndent < -newMarginLeft) {
        // Don't allow negative text-indent
        newTextIndent = -newMarginLeft;
        if (fabs(newTextIndent) >= 0.01) {
            char buf[100];
            CSSPut(properties,"text-indent",DFFormatDoublePct(buf,100,newTextIndent));
        }
        else {
            CSSPut(properties,"text-indent",NULL);
        }
    }

    char *propertiesText = CSSPropertiesCopyDescription(properties);
    if (strlen(propertiesText) == 0)
        DFRemoveAttribute(element,HTML_STYLE);
    else
        DFSetAttribute(element,HTML_STYLE,propertiesText);
    free(propertiesText);

    CSSPropertiesRelease(properties);
}
Example #3
0
static void Word_preProcessHTML(WordConverter *word, DFNode *node)
{
    switch (node->tag) {
        case HTML_TABLE:
        case HTML_FIGURE: {
            DFNode *next;
            for (DFNode *child = node->first; child != NULL; child = next) {
                next = child->next;

                if ((child->tag != HTML_CAPTION) && (child->tag != HTML_FIGCAPTION))
                    continue;

                WordCaption *caption = WordCaptionNew(child);
                WordObjectsSetCaption(word->objects,caption,node);
                caption->contentStart = child->first;
                WordCaptionRelease(caption);

                const char *className = DFGetAttribute(child,HTML_CLASS);
                CSSStyle *style;
                if (child->tag == HTML_CAPTION)
                    style = CSSSheetLookupElement(word->styleSheet,"caption",className,0,0);
                else
                    style = CSSSheetLookupElement(word->styleSheet,"figcaption",className,0,0);

                CSSProperties *before = CSSStyleBefore(style);
                if (CSSGet(before,"content") != NULL)
                    Word_addContentParts(child,CSSGet(before,"content"),caption);

                child->tag = HTML_P;
                DFSetAttribute(child,HTML_CLASS,"Caption");
                DFInsertBefore(node->parent,child,node->next);
                Word_preProcessHTML(word,child);
            }

            // The HTML normalization process ensures that apart from the <figcaption> element,
            // all children of a <figure> are paragraphs or containers. Currently the editor only
            // lets you create figures that contain a single image, so it's always a single
            // paragraph. Since the HTML <figure> element gets mapped to a single <w:p> element
            // by WordParagraphLens, we want to make sure it only contains inline children.

            for (DFNode *child = node->first; child != NULL; child = next) {
                next = child->next;
                if (HTML_isParagraphTag(child->tag))
                    DFRemoveNodeButKeepChildren(child);
            }

            // FIXME: Handle <div>, <pre>, lists, tables etc which could also theoretically
            // exist inside the <figure> element

            break;
        }
        case HTML_NAV: {
            const char *className = DFGetAttribute(node,HTML_CLASS);
            const char *instr = NULL;
            if (DFStringEquals(className,DFTableOfContentsClass))
                instr = " TOC \\o \"1-3\" ";
            else if (DFStringEquals(className,DFListOfFiguresClass))
                instr = " TOC \\c \"Figure\" ";
            else if (DFStringEquals(className,DFListOfTablesClass))
                instr = " TOC \\c \"Table\" ";

            if (instr != NULL) {
                DFNode *p = DFCreateElement(word->html,HTML_P);
                DFNode *field = DFCreateChildElement(p,HTML_SPAN);
                DFSetAttribute(field,HTML_CLASS,DFFieldClass);
                DFCreateChildTextNode(field,instr);
                DFInsertBefore(node->parent,p,node);
                DFRemoveNode(node);
            }
            break;
        }
    }

    DFNode *next;
    for (DFNode *child = node->first; child != NULL; child = next) {
        next = child->next;
        Word_preProcessHTML(word,child);
    }
}