mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More HTML transform actions
This commit is contained in:
parent
6e10d67683
commit
8f6c3dff7e
@ -41,7 +41,8 @@ ACTION_MAP = {a.name: a for a in (
|
|||||||
Action('add_classes', _('Add classes'), _('Add the specified classes, for e.g.:') + ' bold green', _('Space separated class names')),
|
Action('add_classes', _('Add classes'), _('Add the specified classes, for e.g.:') + ' bold green', _('Space separated class names')),
|
||||||
Action('remove_classes', _('Remove classes'), _('Remove the specified classes, for e.g:') + ' bold green', _('Space separated class names')),
|
Action('remove_classes', _('Remove classes'), _('Remove the specified classes, for e.g:') + ' bold green', _('Space separated class names')),
|
||||||
Action('remove_attrs', _('Remove attributes'), _(
|
Action('remove_attrs', _('Remove attributes'), _(
|
||||||
'Remove the specified attributes from the tag. Multiple attribute names should be separated by spaces'), _('Space separated attribute names')),
|
'Remove the specified attributes from the tag. Multiple attribute names should be separated by spaces.'
|
||||||
|
' The special value * removes all attributes.'), _('Space separated attribute names')),
|
||||||
Action('add_attrs', _('Add attributes'), _('Add the specified attributes, for e.g.:') + ' class="red" name="test"', _('Space separated attribute names')),
|
Action('add_attrs', _('Add attributes'), _('Add the specified attributes, for e.g.:') + ' class="red" name="test"', _('Space separated attribute names')),
|
||||||
Action('empty', _('Empty the tag'), _('Remove all contents from the tag')),
|
Action('empty', _('Empty the tag'), _('Remove all contents from the tag')),
|
||||||
Action('wrap', _('Wrap the tag'), _(
|
Action('wrap', _('Wrap the tag'), _(
|
||||||
@ -209,19 +210,65 @@ def remove_classes(classes, tag):
|
|||||||
|
|
||||||
def remove_attrs(attrs, tag):
|
def remove_attrs(attrs, tag):
|
||||||
changed = False
|
changed = False
|
||||||
|
if not tag.attrib:
|
||||||
|
return False
|
||||||
for a in attrs:
|
for a in attrs:
|
||||||
if tag.attrib.pop(a, None) is not None:
|
if a == '*':
|
||||||
changed = True
|
changed = True
|
||||||
|
tag.attrib.clear()
|
||||||
|
else:
|
||||||
|
if tag.attrib.pop(a, None) is not None:
|
||||||
|
changed = True
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
def parse_attrs(text):
|
||||||
|
div = parse(f'<div {text} ></div>', fragment_context='div')[0]
|
||||||
|
return div.items()
|
||||||
|
|
||||||
|
|
||||||
|
def add_attrs(attrib, tag):
|
||||||
|
orig = tag.items()
|
||||||
|
for k, v in attrib:
|
||||||
|
tag.set(k, v)
|
||||||
|
return orig != tag.items()
|
||||||
|
|
||||||
|
|
||||||
|
def empty(tag):
|
||||||
|
changed = len(tag) > 0 or bool(tag.text)
|
||||||
|
tag.text = None
|
||||||
|
del tag[:]
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
def parse_start_tag(text):
|
||||||
|
tag = parse(text, namespace_elements=True, fragment_context='div')[0]
|
||||||
|
return {'tag': tag.tag, 'attrib': tag.items()}
|
||||||
|
|
||||||
|
|
||||||
|
def wrap(data, tag):
|
||||||
|
elem = tag.makeelement(data['tag'])
|
||||||
|
for k, v in data['attrib']:
|
||||||
|
elem.set(k, v)
|
||||||
|
elem.tail = tag.tail
|
||||||
|
tag.tail = None
|
||||||
|
p = tag.getparent()
|
||||||
|
idx = p.index(tag)
|
||||||
|
p.insert(idx, elem)
|
||||||
|
elem.append(tag)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
action_map = {
|
action_map = {
|
||||||
'rename': lambda data: partial(rename_tag, qualify_tag_name(data)),
|
'rename': lambda data: partial(rename_tag, qualify_tag_name(data)),
|
||||||
'remove': lambda data: remove_tag,
|
'remove': lambda data: remove_tag,
|
||||||
'unwrap': lambda data: unwrap_tag,
|
'unwrap': lambda data: unwrap_tag,
|
||||||
|
'empty': lambda data: empty,
|
||||||
'add_classes': lambda data: partial(add_classes, str.split(data)),
|
'add_classes': lambda data: partial(add_classes, str.split(data)),
|
||||||
'remove_classes': lambda data: partial(remove_classes, str.split(data)),
|
'remove_classes': lambda data: partial(remove_classes, str.split(data)),
|
||||||
'remove_attrs': lambda data: partial(remove_attrs, str.split(data)),
|
'remove_attrs': lambda data: partial(remove_attrs, str.split(data)),
|
||||||
|
'add_attrs': lambda data: partial(add_attrs, parse_attrs(data)),
|
||||||
|
'wrap': lambda data: partial(wrap, parse_start_tag(data)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -436,6 +483,24 @@ def test(return_tests=False): # {{{
|
|||||||
p = r('<p class="c" x="y" id="p">')[0]
|
p = r('<p class="c" x="y" id="p">')[0]
|
||||||
self.assertTrue(t('remove_attrs', 'class id')(p))
|
self.assertTrue(t('remove_attrs', 'class id')(p))
|
||||||
self.ae(list(p.attrib), ['x'])
|
self.ae(list(p.attrib), ['x'])
|
||||||
|
p = r('<p class="c" x="y" id="p">')[0]
|
||||||
|
self.assertTrue(t('remove_attrs', '*')(p))
|
||||||
|
self.ae(list(p.attrib), [])
|
||||||
|
|
||||||
|
p = r()[0]
|
||||||
|
self.assertTrue(t('add_attrs', "class='c' data-m=n")(p))
|
||||||
|
self.ae(p.items(), [('class', 'c'), ('data-m', 'n')])
|
||||||
|
p = r('<p a=1>')[0]
|
||||||
|
self.assertTrue(t('add_attrs', "a=2")(p))
|
||||||
|
self.ae(p.items(), [('a', '2')])
|
||||||
|
|
||||||
|
p = r('<p>t<span>s')[0]
|
||||||
|
self.assertTrue(t('empty')(p))
|
||||||
|
ax(p, '<p/>')
|
||||||
|
|
||||||
|
p = r('<p>t<span>s</p>tail')[0]
|
||||||
|
self.assertTrue(t('wrap', '<div a=b c=d>')(p))
|
||||||
|
ax(p.getparent(), '<div a="b" c="d"><p>t<span>s</span></p></div>tail')
|
||||||
|
|
||||||
tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestTransforms)
|
tests = unittest.defaultTestLoader.loadTestsFromTestCase(TestTransforms)
|
||||||
if return_tests:
|
if return_tests:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user