-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Base URL and iframed editables support #665
Comments
IMO: using |
I have the impression that having an iframe editor is a must-have in many cases. Although we can try to convince ourselves that the CSS issue can be solved, I doubt that it is the reality in the real world. I'm in fact more worried about the CSS aspect of it than the base URL issue, which WE could solve in other ways, as we can see. |
I agree that CSS issue is a bigger problem because it needs to be resolved by the other developers. Base URL is something that we can do with or without iframes and it's quite transparent to the other developers. |
The feature requested by the user #1401. |
👍 |
There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may be relevant, so if you're interested in the solution, leave a comment or reaction under this issue. |
I am in the process of upgrading a CMS from CK4 to CK5 and are affected by this issue. The CMS uses different domains for admin and view. As an example we uses www.example.com for the view and www-adm.example.com for the admin. So we are using baseHref so that relative links inside CK uses the view-domain, even if the editing is done on the admin domain. Just want to ask if this is something that has not been totally ruled out to be included in CK5? The issue has gone stale, so I am not expecting this to be included in the near future. However I plan to make a plugin that resolves relative URLs based on a supplied view-url base, before preview in the editor. But it must not affect the data that is stored, as I want to keep the relative url. Any tips on how this can be done in CK5 would be appreciated. |
I first wasted hours on trying to use editorDowncast converters with dispatcher listening on the import {Plugin} from '@ckeditor/ckeditor5-core';
import type {
DowncastWriter,
ViewNode,
ViewElement,
} from '@ckeditor/ckeditor5-engine';
import { createLinkElement, ensureSafeUrl } from '@ckeditor/ckeditor5-link/src/utils';
export default class ViewUrlConversion extends Plugin {
/**
* @inheritDoc
*/
public static get pluginName() {
return 'ViewUrlConversion' as const;
}
public init(): void {
const config = this.editor.config.get('vrtx');
if (config?.viewUrl) {
const viewUrl = config.viewUrl;
this.editor.conversion.for('editingDowncast')
.attributeToElement({
model: 'linkHref',
view: (href, conversionApi) => {
const resolvedUrl = (href)
? new URL(href, config.viewUrl).href
: '';
return createLinkElement(
ensureSafeUrl(resolvedUrl),
conversionApi
);
},
converterPriority: 'high',
});
this.editor.editing.view.document.registerPostFixer(
(writer) => {
const children =
writer.document.getRoot()?.getChildren();
if (children) {
return this.fixViewUrls(children, writer, viewUrl);
}
return false;
}
);
}
}
private fixViewUrls(
children: IterableIterator<ViewNode>,
writer: DowncastWriter,
viewUrl: URL,
): boolean {
let changed = false;
for (const node of children) {
if (node.is('element')) {
if (node.name === 'a' && node.hasAttribute('href')) {
changed = this.resolveViewUrl(
node,
'href',
viewUrl,
writer
) || changed;
}
else if (
(
node.name === 'img'
|| node.name === 'video'
|| node.name === 'audio'
|| node.name === 'source'
|| node.name === 'track'
|| node.name === 'iframe'
)
&& node.hasAttribute('src')
) {
changed = this.resolveViewUrl(
node,
'src',
viewUrl,
writer
) || changed;
}
else if (node.name === 'form' && node.hasAttribute('action')) {
changed = this.resolveViewUrl(
node,
'action',
viewUrl,
writer
) || changed;
}
if (node.name === 'video' && node.hasAttribute('poster')) {
changed = this.resolveViewUrl(
node,
'poster',
viewUrl,
writer
) || changed;
}
changed = this.fixViewUrls(node.getChildren(), writer, viewUrl)
|| changed;
}
}
return changed;
}
private resolveViewUrl(
node: ViewElement,
key: string,
base: URL,
writer: DowncastWriter,
): boolean {
const url = node.getAttribute(key);
const resolvedUrl = (url)
? new URL(url, base).href
: '';
if (resolvedUrl && resolvedUrl !== url) {
writer.setAttribute(
key,
resolvedUrl,
node
);
return true;
}
return false;
}
} |
Thanks for sharing @nilsfr! |
You are welcome. I did investigate this a bit more and discovered that the post-fixer for the editor view is called on every interaction with the editable area. It is sub-optimal to traverse the the object model for every mouse click and every key-stroke. I would like to limit it so it is only called on structural changes, but have not found a way to do it. Of cause it must not be more expensive to discover that it is a structural change, than to just traverse the object model. However it looks to me to be fast enough, but I have not tested with really large object models. I will run with this until we experience performance issues. |
When using this post-fixer for the view I have problems removing links in the editor. Because the href-attribute is changed it looks like the modelRange to viewRange mapping gets messed up. When I click on a link it gets converted into tree links.
|
As Ckeditor5 got confused by the changes made to a-hrefs by the editing post-fixer I ended up overriding the editingDowncast converter for linkHrefs (ckeditor5-link plugin). Now I am able to remove links. I still handle a-hrefs in the post fixer as a fallback. I have updated the code example above to include the editingDowncast converter. |
CKEditor 4 supports
config.baseHref
which lets you configure the value of the<base>
tag used in an<iframe>
which the editor creates to wrap the content.The main use case for this attribute is in CMSes where content is often edited in different places where it's then displayed. If relative paths to e.g. images are used, then those paths wouldn't work in the admin part of the CMS. By defining
config.baseHref
to a similar path to where the content will be then served to the users you can solve all these issues.Iframed editables
First of all, we haven't implemented yet an editor creator which would use iframed editable. So far, we're using inlined editables. They are much lighter and creates far fewer issues than iframed editables.
Iframed editables have two important advantages, though:
<base>
tag.The first problem can be workarounded using inline editables, so it wasn't that critical. Basically, it all boils down to writing a proper stylesheet which will reset CMSes styles in the editor content. While not trivial, this is doable. And let's not forget that the content in the editor doesn't need to (or even shouldn't) look exactly like the content on a target page. This approach is often proposed to encourage users to think about the content itself, not the styling.
Can base URLs be solved without iframes? I think so. E.g. the image feature can prepend the base URL to
src
s of images in the content (although, withsrcset
this is a bit more tricky). The link feature needs to prepend this base URL to "open link" link. It all seems doable, but will need to be considered by all features which has something to do with URLs.Would iframes make it easier? Yes, perhaps for the image feature, but not for the link feature (because balloon would be outside the iframe).
Do we want to support iframes? No, if we'll be able to solve other issues using inline editables. Iframes are a mess.
Questions
config.baseUrl
to existing features?cc @fredck @wwalc
My answers would be maybe and yes.
The text was updated successfully, but these errors were encountered: