Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Support replacing Bard TipTap extensions by jacksleight · Pull Request #4314 · statamic/cms · GitHub
Skip to content

Support replacing Bard TipTap extensions - #4314

Merged
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace
Nov 24, 2021
Merged

Support replacing Bard TipTap extensions#4314
jasonvarga merged 11 commits into
statamic:3.2from
jacksleight:tiptap-extension-replace

Conversation

@jacksleight

@jacksleightjacksleight commented Sep 26, 2021

Copy link
Copy Markdown
Contributor

This PR makes it possible to replace the built-in Bard TipTap nodes/marks with extended versions without causing duplication or errors. It also brings the Bard editor inline with the Bard Augmentor, which already supports node and mark class replacement.

The problems this solves are:

  • There’s currently no way to access the built-in extension classes without importing TipTap. And even if you do that you still wouldn't have access to Statamic’s extension classes.
  • Statamic.$bard.extend() always appends extensions to the list, even if they’re intended to replace built-in extensions. While TipTap mostly handles this gracefully, it still adds both, which causes duplication and throws errors if the extension has plugins.
  • Normally Statamic only adds the extensions that are applicable to the buttons enabled in Bard, however if you’re replacing built-in extensions the replacement always gets added, even if the relevant button isn’t enabled.

The changes are:

  • Added Statamic.$bard.tiptap.extensions which exposes the built-in extension classes, so they can easily be extended without importing TipTap.
  • Added Statamic.$bard.extendReplace() which will allow you to register callbacks that will return replacement extensions.
  • The BardFieldtype component has been updated to apply the replacement extensions, but it only does that if the original extension is in the list.
  • To ensure replacement extensions can have the same configuration as default ones a couple of additional variables (languages and levels) are now being passed to the callbacks.
  • To ensure the Paragraph extension can be replaced it's being included in the default list.

This shouldn’t cause any BC breaks. Statamic.$bard.extend() still does exactly what it used to.

Sidenote

I’ve tried to do this with zero changes to the existing APIs, but that does mean that the naming is a bit awkward now:

  • extend()
  • extendReplace()
  • buttons()

I wonder if it might be worth changing these to something more consistent and descriptive, like:

  • addExtensions()
  • replaceExtensions()
  • addButtons()
  • With extend() and buttons() as aliases for BC

This would be consistent with the equivalent methods in the Bard Augmentor as well.

I’ll leave that decision to you. I can make those changes if you agree.

Testing

Here is a simple example that can be used to test this change. It replaces the Heading extension with a custom version with a tweaked schema.

The heading text should change to red and if you check the list of extensions being passed to the TipTap editor it should only have one instance of a Heading extension (the custom one), or none if the heading buttons aren't enabled.

const{ Heading }=Statamic.$bard.tiptap.extensions;classCustomHeadingextendsHeading{getschema(){return{
...super.schema,toDOM: node=>[`h${node.attrs.level}`,{style: 'color: red',},0],}}}Statamic.booting(()=>{Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);});

@jacksleightjacksleight changed the title Support replacing built-in Bard/TipTap extensionsSupport replacing built-in Bard TipTap extensionsSep 26, 2021
@jacksleightjacksleight changed the title Support replacing built-in Bard TipTap extensionsSupport replacing Bard TipTap extensionsSep 27, 2021
@jacksleight

Copy link
Copy Markdown
ContributorAuthor

This is now ready for review, when you have time. Thanks!

@jasonvargajasonvarga self-assigned this Nov 23, 2021
@jasonvarga

jasonvarga commented Nov 23, 2021

Copy link
Copy Markdown
Member

Sorry for the delay.

Nice PR! I'm making a few changes though.

Instead of this:

Statamic.$bard.extendReplace(({ levels })=>[[Heading,newCustomHeading({ levels })],]);

You'll be able specify the extension by name, and the actual extension will be provided in the callback.

Statamic.$bard.replaceExtension('heading',({ extension })=>{returnnewCustomHeading({levels: extension.options.levels});// or even justreturnnewCustomHeading(extension.options);});

I'm gonna deprecate $bard.extend() and rename it to $bard.addExtension() like you suggested.
As well as change your extendReplace to replaceExtension.
I'll leave buttons as-is though, because you can add buttons or just manipulate them.

@jacksleight

jacksleight commented Nov 23, 2021

Copy link
Copy Markdown
ContributorAuthor

Amazing! That new replacement solution is much better!

I just committed one small change I missed in the original PR.

TipTap includes the Doc, Text and Paragraph nodes by default. Statamic is already overriding Doc, and this PR overrides Paragraph, which just leaves Text.

The TipTap editor has a useBuiltInExtensions option that you can set to false if you're overriding those extensions (https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap/src/Editor.js#L131).

I've set that and added Text to the list, so all the extensions are only added once now.

@jasonvarga

Copy link
Copy Markdown
Member

Awesome, thanks!

@jasonvarga
jasonvarga merged commit 5b87637 into statamic:3.2Nov 24, 2021
@jacksleight
jacksleight deleted the tiptap-extension-replace branch November 24, 2021 09:47
@jasonvargajasonvarga mentioned this pull request Feb 13, 2023
Sign up for freeto 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.

2 participants

@jacksleight@jasonvarga