Ejemplo n.º 1
0
 def test_rule_false_for_attr(self):
     """
     Test that attribute_rule() drops attributes
     when the corresponding rule returns False
     """
     tag = self.soup.b
     fn = attribute_rule({"foo": False})
     fn(tag)
     self.assertEqual(str(tag), "<b>baz</b>")
Ejemplo n.º 2
0
 def test_rule_true_for_attr(self):
     """
     Test that attribute_rule() does not change attributes
     when the corresponding rule returns True
     """
     tag = self.soup.b
     fn = attribute_rule({"foo": True})
     fn(tag)
     self.assertEqual(str(tag), '<b foo="bar">baz</b>')
Ejemplo n.º 3
0
 def test_no_rule_for_attr(self):
     """
     Test that attribute_rule() drops attributes for
     which no rule has been defined.
     """
     tag = self.soup.b
     fn = attribute_rule({"snowman": "barbecue"})
     fn(tag)
     self.assertEqual(str(tag), "<b>baz</b>")
Ejemplo n.º 4
0
 def test_callable_returns_None(self):
     """
     Test that when the rule returns a callable,
     attribute_rule() replaces the attribute with
     the result of calling the callable on the attribute.
     """
     tag = self.soup.b
     fn = attribute_rule({"foo": lambda x: None})
     fn(tag)
     self.assertEqual(str(tag), "<b>baz</b>")
Ejemplo n.º 5
0
 def test_callable_called_on_attr(self):
     """
     Test that when the rule returns a callable,
     attribute_rule() replaces the attribute with
     the result of calling the callable on the attribute.
     """
     tag = self.soup.b
     fn = attribute_rule({"foo": len})
     fn(tag)
     self.assertEqual(str(tag), '<b foo="3">baz</b>')
Ejemplo n.º 6
0
def register_core_features(features):
    features.register_converter_rule(
        "editorhtml",
        "link",
        [
            WhitelistRule("a", attribute_rule({"href": check_url})),
            LinkTypeRule("page", PageLinkHandler),
        ],
    )

    features.register_converter_rule(
        "editorhtml",
        "bold",
        [
            WhitelistRule("b", allow_without_attributes),
            WhitelistRule("strong", allow_without_attributes),
        ],
    )

    features.register_converter_rule(
        "editorhtml",
        "italic",
        [
            WhitelistRule("i", allow_without_attributes),
            WhitelistRule("em", allow_without_attributes),
        ],
    )

    headings_elements = ["h1", "h2", "h3", "h4", "h5", "h6"]
    for order, element in enumerate(headings_elements):
        features.register_converter_rule(
            "editorhtml", element,
            [WhitelistRule(element, allow_without_attributes)])

    features.register_converter_rule(
        "editorhtml",
        "ol",
        [
            WhitelistRule("ol", allow_without_attributes),
            WhitelistRule("li", allow_without_attributes),
        ],
    )

    features.register_converter_rule(
        "editorhtml",
        "ul",
        [
            WhitelistRule("ul", allow_without_attributes),
            WhitelistRule("li", allow_without_attributes),
        ],
    )

    # Draftail
    features.register_editor_plugin(
        "draftail", "hr",
        draftail_features.BooleanFeature("enableHorizontalRule"))
    features.register_converter_rule(
        "contentstate",
        "hr",
        {
            "from_database_format": {
                "hr": HorizontalRuleHandler(),
            },
            "to_database_format": {
                "entity_decorators": {
                    "HORIZONTAL_RULE": lambda props: DOM.create_element("hr")
                }
            },
        },
    )

    features.register_editor_plugin(
        "draftail",
        "h1",
        draftail_features.BlockFeature({
            "label": "H1",
            "type": "header-one",
            "description": gettext("Heading %(level)d") % {
                "level": 1
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h1",
        {
            "from_database_format": {
                "h1": BlockElementHandler("header-one"),
            },
            "to_database_format": {
                "block_map": {
                    "header-one": "h1"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "h2",
        draftail_features.BlockFeature({
            "label": "H2",
            "type": "header-two",
            "description": gettext("Heading %(level)d") % {
                "level": 2
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h2",
        {
            "from_database_format": {
                "h2": BlockElementHandler("header-two"),
            },
            "to_database_format": {
                "block_map": {
                    "header-two": "h2"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "h3",
        draftail_features.BlockFeature({
            "label": "H3",
            "type": "header-three",
            "description": gettext("Heading %(level)d") % {
                "level": 3
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h3",
        {
            "from_database_format": {
                "h3": BlockElementHandler("header-three"),
            },
            "to_database_format": {
                "block_map": {
                    "header-three": "h3"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "h4",
        draftail_features.BlockFeature({
            "label": "H4",
            "type": "header-four",
            "description": gettext("Heading %(level)d") % {
                "level": 4
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h4",
        {
            "from_database_format": {
                "h4": BlockElementHandler("header-four"),
            },
            "to_database_format": {
                "block_map": {
                    "header-four": "h4"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "h5",
        draftail_features.BlockFeature({
            "label": "H5",
            "type": "header-five",
            "description": gettext("Heading %(level)d") % {
                "level": 5
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h5",
        {
            "from_database_format": {
                "h5": BlockElementHandler("header-five"),
            },
            "to_database_format": {
                "block_map": {
                    "header-five": "h5"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "h6",
        draftail_features.BlockFeature({
            "label": "H6",
            "type": "header-six",
            "description": gettext("Heading %(level)d") % {
                "level": 6
            },
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "h6",
        {
            "from_database_format": {
                "h6": BlockElementHandler("header-six"),
            },
            "to_database_format": {
                "block_map": {
                    "header-six": "h6"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "ul",
        draftail_features.BlockFeature({
            "type": "unordered-list-item",
            "icon": "list-ul",
            "description": gettext("Bulleted list"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "ul",
        {
            "from_database_format": {
                "ul": ListElementHandler("unordered-list-item"),
                "li": ListItemElementHandler(),
            },
            "to_database_format": {
                "block_map": {
                    "unordered-list-item": {
                        "element": "li",
                        "wrapper": "ul"
                    }
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "ol",
        draftail_features.BlockFeature({
            "type": "ordered-list-item",
            "icon": "list-ol",
            "description": gettext("Numbered list"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "ol",
        {
            "from_database_format": {
                "ol": ListElementHandler("ordered-list-item"),
                "li": ListItemElementHandler(),
            },
            "to_database_format": {
                "block_map": {
                    "ordered-list-item": {
                        "element": "li",
                        "wrapper": "ol"
                    }
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "blockquote",
        draftail_features.BlockFeature({
            "type": "blockquote",
            "icon": "openquote",
            "description": gettext("Blockquote"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "blockquote",
        {
            "from_database_format": {
                "blockquote": BlockElementHandler("blockquote"),
            },
            "to_database_format": {
                "block_map": {
                    "blockquote": "blockquote"
                }
            },
        },
    )

    features.register_editor_plugin(
        "draftail",
        "bold",
        draftail_features.InlineStyleFeature({
            "type": "BOLD",
            "icon": "bold",
            "description": gettext("Bold"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "bold",
        {
            "from_database_format": {
                "b": InlineStyleElementHandler("BOLD"),
                "strong": InlineStyleElementHandler("BOLD"),
            },
            "to_database_format": {
                "style_map": {
                    "BOLD": "b"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "italic",
        draftail_features.InlineStyleFeature({
            "type": "ITALIC",
            "icon": "italic",
            "description": gettext("Italic"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "italic",
        {
            "from_database_format": {
                "i": InlineStyleElementHandler("ITALIC"),
                "em": InlineStyleElementHandler("ITALIC"),
            },
            "to_database_format": {
                "style_map": {
                    "ITALIC": "i"
                }
            },
        },
    )

    features.register_editor_plugin(
        "draftail",
        "link",
        draftail_features.EntityFeature(
            {
                "type": "LINK",
                "icon": "link",
                "description": gettext("Link"),
                # We want to enforce constraints on which links can be pasted into rich text.
                # Keep only the attributes Wagtail needs.
                "attributes": ["url", "id", "parentId"],
                "whitelist": {
                    # Keep pasted links with http/https protocol, and not-pasted links (href = undefined).
                    "href": "^(http:|https:|undefined$)",
                },
            },
            js=[
                "wagtailadmin/js/page-chooser-modal.js",
            ],
        ),
    )
    features.register_converter_rule(
        "contentstate",
        "link",
        {
            "from_database_format": {
                "a[href]": ExternalLinkElementHandler("LINK"),
                'a[linktype="page"]': PageLinkElementHandler("LINK"),
            },
            "to_database_format": {
                "entity_decorators": {
                    "LINK": link_entity
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "superscript",
        draftail_features.InlineStyleFeature({
            "type":
            "SUPERSCRIPT",
            "icon":
            "superscript",
            "description":
            gettext("Superscript"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "superscript",
        {
            "from_database_format": {
                "sup": InlineStyleElementHandler("SUPERSCRIPT"),
            },
            "to_database_format": {
                "style_map": {
                    "SUPERSCRIPT": "sup"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "subscript",
        draftail_features.InlineStyleFeature({
            "type":
            "SUBSCRIPT",
            "icon":
            "subscript",
            "description":
            gettext("Subscript"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "subscript",
        {
            "from_database_format": {
                "sub": InlineStyleElementHandler("SUBSCRIPT"),
            },
            "to_database_format": {
                "style_map": {
                    "SUBSCRIPT": "sub"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "strikethrough",
        draftail_features.InlineStyleFeature({
            "type":
            "STRIKETHROUGH",
            "icon":
            "strikethrough",
            "description":
            gettext("Strikethrough"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "strikethrough",
        {
            "from_database_format": {
                "s": InlineStyleElementHandler("STRIKETHROUGH"),
            },
            "to_database_format": {
                "style_map": {
                    "STRIKETHROUGH": "s"
                }
            },
        },
    )
    features.register_editor_plugin(
        "draftail",
        "code",
        draftail_features.InlineStyleFeature({
            "type": "CODE",
            "icon": "code",
            "description": gettext("Code"),
        }),
    )
    features.register_converter_rule(
        "contentstate",
        "code",
        {
            "from_database_format": {
                "code": InlineStyleElementHandler("CODE"),
            },
            "to_database_format": {
                "style_map": {
                    "CODE": "code"
                }
            },
        },
    )