Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support non-destructive editing of content w/ legacy shortcodes #1013

Merged
merged 1 commit into from
Feb 17, 2022

Conversation

alicewriteswrongs
Copy link
Contributor

@alicewriteswrongs alicewriteswrongs commented Feb 16, 2022

Pre-Flight checklist

  • Screenshots and design review for any changes that affect layout or styling
    • Desktop screenshots
    • Mobile width screenshots
  • Testing
    • Code is tested
    • Changes have been manually tested

What are the relevant tickets? #1025

(Required)

What's this PR do?

This implements support for nondestructively editing markdown files which have 'legacy' shortcodes in them (these are shortcodes inserted into converted content by ocw-to-hugo to support a series of things which aren't supported in plain markdown).

How should this be manually tested?

You'll need to get some shortcode-filled markdown into one of your pages and then test out that it displays like in the little video below.

  • Arguments to shortcodes should be retained between saves
  • shortcode opening / closing state should be saved

etc

This is a little snippet that you might want to try:

Soundness and Validity
----------------------
  
{{< quiz_multiple_choice questionId="Q1_div" >}}{{< quiz_choices >}}{{< quiz_choice isCorrect="false" >}}&nbsp; sound, satisfiable &nbsp;{{< /quiz_choice >}}
{{< quiz_choice isCorrect="false" >}}&nbsp; valid, satisfiable &nbsp;{{< /quiz_choice >}}
{{< quiz_choice isCorrect="true" >}}&nbsp; sound, valid &nbsp;{{< /quiz_choice >}}
{{< quiz_choice isCorrect="false" >}}&nbsp; valid, true &nbsp;{{< /quiz_choice >}}{{< /quiz_choices >}}
{{< quiz_solution / >}}{{< /quiz_multiple_choice >}}

it's an example of a quiz, which uses a whole bunch of shortcodes, opening and closing ones, with arguments, etc.

Screenshots (if appropriate)

Screen.Recording.2022-02-16.at.6.20.36.PM.mov

@codecov-commenter
Copy link

codecov-commenter commented Feb 16, 2022

Codecov Report

Merging #1013 (c42895e) into master (cc50b15) will increase coverage by 0.11%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1013      +/-   ##
==========================================
+ Coverage   90.56%   90.67%   +0.11%     
==========================================
  Files         196      197       +1     
  Lines        7547     7627      +80     
  Branches     1318     1329      +11     
==========================================
+ Hits         6835     6916      +81     
  Misses        627      627              
+ Partials       85       84       -1     
Impacted Files Coverage Δ
static/js/lib/ckeditor/plugins/ResourceEmbed.ts 92.18% <ø> (ø)
static/js/lib/ckeditor/CKEditor.ts 100.00% <100.00%> (ø)
static/js/lib/ckeditor/plugins/LegacyShortcodes.ts 100.00% <100.00%> (ø)
...tic/js/lib/ckeditor/plugins/TableMarkdownSyntax.ts 100.00% <100.00%> (ø)
static/js/lib/ckeditor/plugins/constants.ts 100.00% <100.00%> (ø)
static/js/util/factories/websites.ts 98.50% <0.00%> (+1.49%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cc50b15...c42895e. Read the comment docs.

@alicewriteswrongs alicewriteswrongs changed the title [WIP] support non-destructive editing of content w/ legacy shortcodes support non-destructive editing of content w/ legacy shortcodes Feb 16, 2022
Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 The looks good to me and is working well in local trials.

One request: I think we should add baseurl to the legacy list. No baseurls have been converted yet (hopefully will today) but even after that conversion some will remain for a while.

@@ -64,3 +64,25 @@ export const TABLE_ALLOWED_ATTRS: string[] = ["colspan", "rowspan"]
* with a double quote and captures anything in between the quotes.
*/
export const ATTRIBUTE_REGEX = /(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|\s*\/?[>"']))+.)["']?/g

export const LEGACY_SHORTCODES = [
Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requested Change: I think we should add baseurl to the list. Hopefully we'll remove it soon there's still some lingering baseurl issues #1015

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok cool, I was too optimistic 😃

Copy link
Contributor Author

@alicewriteswrongs alicewriteswrongs Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also am I right in thinking that there's no harm in having it in the list even after the issue has been addressed via your PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also am I right in thinking that there's no harm in having it in the list even after the issue has been address via your PR?

yes, i agree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not there then the rule won't apply right? There shouldn't be any harm to simply including it in this list, as even if we have a need for it in the future for some reason it would be manually inserted by us and won't be touched by editors.

}

export default class LegacyShortcodes extends Plugin {
static get requires(): Plugin[] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: I'm not suggesting we should necessarily worry about this now... just writing it down

I think there's something weird here... I think the Plugin[] type annotation is referring to globalThis.Plugin. https://developer.mozilla.org/en-US/docs/Web/API/Plugin , not to CKEditor plugins.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oooo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's why it's throwing errors...I'll take a minute to see if I can fix that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird...so I changed import Plugin from ... to import { default as CKEditorPlugin } from ... and then I get an error about being unable to use that type in a static method...I think I might just leave this off for now in the interest of time

but it would be good to fix!


const tag = `<span ${DATA_ISCLOSING}="${isClosing}" ${
shortcodeArgs ?
`${DATA_ARGUMENTS}="${escape(shortcodeArgs)}"` :
Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question/Suggestion: I was unfamiliar with escape and VSCode highlighted it, so I looked it up on MDN. MDN says not to use it, but doesn't really explain why. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape Would encodeURIComponent work instead?

Edit: Google makes me think that the reason it's recommended against is that it occasionally produces invalid URLs. Since we're not using it for that, probably not a concern? But if something not deprecated works, that seems better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use encoreURIComponent, I'll swap that in and make sure the tests pass real quick. The reason to do it is just that if it's not escaped then the text w/in the arguments to a shortcode can cause issues correctly finding the boundaries of the HTML tags later on and things get all messed up. When I was hacking on it I actually used btoa and atob to be 100% sure I wasn't going to get any characters I didn't expect in the arguments string, haha

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, it seems that escape doesn't support "higher order unicode characters," and the only suggestion I see as a replacement as well is encode/decodeUriComponent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, I already made the change since all the tests pass with it

Copy link
Contributor

@gumaerc gumaerc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm approving this, as it tested out well for me locally. I think the things @ChristopherChudzicki noted should be checked out still though. The escape thing isn't critical as it's not going away anytime soon, but might be better to use encodeUriComponent.


const tag = `<span ${DATA_ISCLOSING}="${isClosing}" ${
shortcodeArgs ?
`${DATA_ARGUMENTS}="${escape(shortcodeArgs)}"` :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, it seems that escape doesn't support "higher order unicode characters," and the only suggestion I see as a replacement as well is encode/decodeUriComponent

@@ -64,3 +64,25 @@ export const TABLE_ALLOWED_ATTRS: string[] = ["colspan", "rowspan"]
* with a double quote and captures anything in between the quotes.
*/
export const ATTRIBUTE_REGEX = /(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|\s*\/?[>"']))+.)["']?/g

export const LEGACY_SHORTCODES = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not there then the rule won't apply right? There shouldn't be any harm to simply including it in this list, as even if we have a need for it in the future for some reason it would be manually inserted by us and won't be touched by editors.

This implements support for nondestructively editing markdown files
which have 'legacy' shortcodes in them (these are shortcodes inserted
into converted content by ocw-to-hugo to support a series of things
which aren't supported in plain markdown).

A manifest of these shortcodes is declared in
`static/js/lib/ckeditor/plugins/constants.ts`, and support for them is
implemented in a new CKEditor plugin called `LegacyShortcodes`.

This will enable non-destructive editing of markdown content which
contains these shortcodes, fixing an issue we were seeing where raw
shortcodes that were unknown to CKEditor were being escaped and the
showing up in the rendered HTML. This fixes this by adding a node type
to CKEditor for each one, and adding basical logic for preserving any
arguments to the shortcodes.

Note that this change does NOT in any way way enable _editing these
shortcodes themselves_. Instead, they are made obvious in the editor
with a basic display, but it is up to the content editors to not delete
them or anything like that (and right now they could only be added to a
file manually in the Django admin or shell).

pr #1013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants