diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index ede4576f..2dcd452e 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -4,7 +4,8 @@ Changelog 5.0.0b4 (unreleased) -------------------- -- Nothing changed yet. +- Fix ck_ruid_to_url transform for tags with style and url("resolveuid/xxxx") + [gotcha] 5.0.0b3 (2023-11-13) diff --git a/src/collective/ckeditor/tests/test_transform.py b/src/collective/ckeditor/tests/test_transform.py index 1ad86c80..f158c531 100644 --- a/src/collective/ckeditor/tests/test_transform.py +++ b/src/collective/ckeditor/tests/test_transform.py @@ -41,6 +41,36 @@ def testFindTagA(self): self.assertEquals(len(unique), 1) self.assertEquals(unique, set(["abcdef"])) + def testFindTagAWithAbsoluteURL(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = "Link" + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 0) + # double quotes + text = 'Link' + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 0) + + def testFindTagAWithAnchor(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = "Link" + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals(tags[0], ("", + 'abcdef', 'resolveuid/abcdef')) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = 'Link' + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals(tags[0], ('', + 'abcdef', 'resolveuid/abcdef')) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + def testFindTagEmbed(self): from collective.ckeditor.transforms import ck_ruid_to_url # single quotes @@ -61,6 +91,278 @@ def testFindTagEmbed(self): self.assertEquals(unique, set(["abcdef"])) def testFindTagWithStyle(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithStyleAndViewInUrl(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithMoreStyle(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithEvenMoreStyle(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithStyleWithAposEntity(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithStyleAndViewInUrlWithAposEntity(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithMoreStyleWithAposEntity(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithEvenMoreStyleWithAposEntity(self): + from collective.ckeditor.transforms import ck_ruid_to_url + # single quotes + text = ( + "
" + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ("
", + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + # double quotes + text = ( + '
' + "content
" + ) + tags, unique = ck_ruid_to_url.find_tags_with_resolveuid(text) + self.assertEquals(len(tags), 1) + self.assertEquals( + tags[0], + ('
', + 'abcdef', 'resolveuid/abcdef') + ) + self.assertEquals(len(unique), 1) + self.assertEquals(unique, set(["abcdef"])) + + def testFindTagWithStyleWithoutQuotEntity(self): from collective.ckeditor.transforms import ck_ruid_to_url # single quotes text = ( @@ -91,7 +393,7 @@ def testFindTagWithStyle(self): self.assertEquals(len(unique), 1) self.assertEquals(unique, set(["abcdef"])) - def testFindTagWithMoreStyle(self): + def testFindTagWithMoreStyleWithoutQuotEntity(self): from collective.ckeditor.transforms import ck_ruid_to_url # single quotes text = ( @@ -126,7 +428,7 @@ def testFindTagWithMoreStyle(self): self.assertEquals(len(unique), 1) self.assertEquals(unique, set(["abcdef"])) - def testFindTagWithEvenMoreStyle(self): + def testFindTagWithEvenMoreStyleWithoutQuotEntity(self): from collective.ckeditor.transforms import ck_ruid_to_url # single quotes text = ( @@ -192,6 +494,34 @@ def mocked(uid): original, compute_url=mocked) self.assertEquals(final, "") + original = ( + "
" + "content
" + ) + final = ck_ruid_to_url.replace_resolveuid_urls_with_absolute_urls( + original, compute_url=mocked) + self.assertEquals( + final, + "
content
") + + original = ( + "
" + "content
" + ) + final = ck_ruid_to_url.replace_resolveuid_urls_with_absolute_urls( + original, compute_url=mocked) + self.assertEquals( + final, + "
content
") + original = ( "
content
") + + original = ( + "
" + "content
" + ) + final = ck_ruid_to_url.replace_resolveuid_urls_with_absolute_urls( + original, compute_url=mocked) + self.assertEquals( + final, + "
content
") diff --git a/src/collective/ckeditor/tests/transform_uids.txt b/src/collective/ckeditor/tests/transform_uids.txt index bd873367..05fdd0d8 100644 --- a/src/collective/ckeditor/tests/transform_uids.txt +++ b/src/collective/ckeditor/tests/transform_uids.txt @@ -1,8 +1,7 @@ Transforms url uids ------------------- -each urls like './resolveuid/abcdef' or 'http://localhost/plone/resolveUID/' -or 'http://localhost/plone/resolveuid/download' +Each urls like 'resolveuid/abcdef' must be transformed on page view by absolute url of each objects resolved uid. Log in as manager @@ -38,7 +37,7 @@ Create a document with resolveuid urls >>> browser.getControl(name='form.widgets.IDublinCore.title').value = 'Test Doc' >>> html_text = ''' ...

Test

- ...

Test

+ ...

Test

... ''' % (uid, uid) >>> browser.getControl(name='form.widgets.IRichTextBehavior.text').value = html_text >>> browser.getControl('Save').click() diff --git a/src/collective/ckeditor/transforms/ck_ruid_to_url.py b/src/collective/ckeditor/transforms/ck_ruid_to_url.py index b520f7c3..301f73c4 100644 --- a/src/collective/ckeditor/transforms/ck_ruid_to_url.py +++ b/src/collective/ckeditor/transforms/ck_ruid_to_url.py @@ -24,22 +24,40 @@ def replace_resolveuid_urls_with_absolute_urls(text, compute_url=uuidToURL): TAG_WITH_URL_RE = r'(\<(img|a|embed)[^>]*>)' -TAG_WITH_URL = re.compile(TAG_WITH_URL_RE, re.I | re.S) +TAG_WITH_URL = re.compile(TAG_WITH_URL_RE, re.IGNORECASE | re.DOTALL) TAG_WITH_STYLE_RE = r'(\<[^>]*style=[^>]*url\([^>]*>)' -TAG_WITH_STYLE = re.compile(TAG_WITH_STYLE_RE, re.I | re.S) +TAG_WITH_STYLE = re.compile( + TAG_WITH_STYLE_RE, re.IGNORECASE | re.DOTALL) RUID_URL = 'resolveuid' -RUID_URL_BETWEEN_QUOTES_RE = ( - r'(?P[^\"\']*%s/(?P[^\/\"\'#? ]*))' % RUID_URL +RUID_URL_BETWEEN_SINGLE_QUOTES_RE = ( + r"'(?P%s/(?P[^'/#]*))[^']*'" + % RUID_URL ) -RUID_URL_BETWEEN_QUOTES = re.compile(RUID_URL_BETWEEN_QUOTES_RE, re.I | re.S) +RUID_URL_BETWEEN_SINGLE_QUOTES = re.compile( + RUID_URL_BETWEEN_SINGLE_QUOTES_RE, re.IGNORECASE | re.DOTALL) -RUID_URL_BETWEEN_PARENS_RE = ( - r'[^(]*\((?P[^\"\')]*%s/(?P[^\/\"\')#? ]*))' % RUID_URL + +RUID_URL_BETWEEN_DOUBLE_QUOTES_RE = ( + r'"(?P%s/(?P[^"/#]*))[^"]*"' + % RUID_URL + ) +RUID_URL_BETWEEN_DOUBLE_QUOTES = re.compile( + RUID_URL_BETWEEN_DOUBLE_QUOTES_RE, re.IGNORECASE | re.DOTALL) + + +RUID_URL_INSIDE_PARENS_AND_QUOT_OR_APOS_RE = ( + r'(?P[^(]*%s/(?P[^)/#&]*))[^(]*' + % RUID_URL + ) +RUID_URL_BETWEEN_PARENS_AND_QUOT_OR_APOS_RE = ( + r'\(("|')?%s("|')?\)' + % RUID_URL_INSIDE_PARENS_AND_QUOT_OR_APOS_RE ) -RUID_URL_BETWEEN_PARENS = re.compile(RUID_URL_BETWEEN_PARENS_RE, re.I | re.S) +RUID_URL_BETWEEN_PARENS_AND_QUOT_OR_APOS = re.compile( + RUID_URL_BETWEEN_PARENS_AND_QUOT_OR_APOS_RE, re.IGNORECASE | re.DOTALL) def find_tags_with_resolveuid(data): @@ -47,14 +65,21 @@ def find_tags_with_resolveuid(data): unique_uids = set() for m in TAG_WITH_URL.finditer(data): - ruid = re.search(RUID_URL_BETWEEN_QUOTES, m.group(0)[:3000]) + ruid = re.search(RUID_URL_BETWEEN_SINGLE_QUOTES, m.group(0)[:3000]) + if ruid: + tags_with_resolveuid.append( + (m.group(0), ruid.group('uid'), ruid.group('url_with_uid')) + ) + + for m in TAG_WITH_URL.finditer(data): + ruid = re.search(RUID_URL_BETWEEN_DOUBLE_QUOTES, m.group(0)[:3000]) if ruid: tags_with_resolveuid.append( (m.group(0), ruid.group('uid'), ruid.group('url_with_uid')) ) for m in TAG_WITH_STYLE.finditer(data): - ruid = re.search(RUID_URL_BETWEEN_PARENS, m.group(0)[:3000]) + ruid = re.search(RUID_URL_BETWEEN_PARENS_AND_QUOT_OR_APOS, m.group(0)[:3000]) if ruid: tags_with_resolveuid.append( (m.group(0), ruid.group('uid'), ruid.group('url_with_uid'))