-
Notifications
You must be signed in to change notification settings - Fork 2
Conversation
3b615fa
to
8231bba
Compare
3d92fdf
to
1022cdb
Compare
e4414f2
to
441457e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do realize this is a WIP so don't take my comments as criticism, I just wrote whenever I did find things that raised questions.
doc/odoo_integration_workflow.md
Outdated
```bash | ||
npm run build | ||
npm run build-odoo | ||
cp build/webpack/build/build-full-odoo.js <your_odoo_path>/addons/web_editor/static/lib/jabberwock/jabberwock.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why cp
instead of mv
?
doc/odoo_integration_workflow.md
Outdated
``` | ||
`odoo-integration.js` will load the script `build-full.js`. | ||
The default loaded script is `http://localhost:8080/build-full.js`. | ||
You might want to change the port if your development port is not "8080". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where?
examples/utils/jabberwocky.xml
Outdated
<div class="homepage" style="display: none;"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you do this in jabberwocky.xml
instead of creating a new file?
Is this template basically a copy of some template in Odoo? If so which one? Would be nice to keep its name.
I'm not looking at the template in details as I'm assuming it's just a duplicate from Odoo. If you tell me it's not then I'll look at it more closely.
const selectedNode = params.context.range.selectedNodes().map(node => node.clone()); | ||
const nodeWithFormat: InlineNode = selectedNode.find( | ||
node => | ||
node instanceof InlineNode && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never do instanceof
for vNodes, we have is
for that...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be fair, we discussed with chm a few days ago and he told me that using instanceof
would be orders of magnitude faster than using .is
once the memory is merged. I'm not feeling confident about the usefulness of .is
apart from being shorter to write so it's possible it might get the axe at some point.
async getSelectedLink(params: CommandParams): Promise<string> { | ||
const selectedNode = params.context.range.selectedNodes().map(node => node.clone()); | ||
const nodeWithFormat: InlineNode = selectedNode.find( | ||
node => | ||
node instanceof InlineNode && | ||
node.formats.find(format => format instanceof LinkFormat), | ||
) as InlineNode; | ||
const linkFormat: LinkFormat = | ||
nodeWithFormat && | ||
(nodeWithFormat.formats.find(format => format instanceof LinkFormat) as LinkFormat); | ||
return linkFormat ? linkFormat.url : ''; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this code is irrelevant now that modifiers were merged. Also there is already a function doing exactly this in Link
.
async getSelectedText(params: CommandParams): Promise<string> { | ||
const selectedNode = params.context.range.selectedNodes().map(node => node.clone()); | ||
const container = new ContainerNode(); | ||
container.append(...selectedNode); | ||
const renderer = this.editor.plugins.get(Renderer); | ||
const renderedNode = await renderer.render<HTMLElement[]>( | ||
HtmlDomRenderingEngine.id, | ||
container, | ||
); | ||
// todo: what if there is more rendered nodes? | ||
return renderedNode ? renderedNode[0].innerText : ''; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh? Why do you go through the rendering for that?
getSelectedText(params: CommandParams): string {
const targettedNodes = params.context.range.targettedNodes();
let text = '';
for (const node of targettedNodes) {
if (!node.ancestor(ancestor => targettedNodes.includes(ancestor))) {
text += node.textContent;
}
}
return text;
}
let classes: string; | ||
if (vNode instanceof InlineNode) { | ||
classes = vNode.formats.map(format => format.attributes.class as string).join(' '); | ||
} else { | ||
classes = vNode.attributes.class as string; | ||
} | ||
return new Set(classes.split(' ')); | ||
} | ||
_setClasses(vNode: VNode, classes: Set<string>): void { | ||
vNode.attributes.class = [...classes].join(' '); | ||
const classesString = [...classes].join(' '); | ||
if (vNode instanceof InlineNode) { | ||
const lastAttribute = vNode.formats[0]?.attributes; | ||
if (lastAttribute) { | ||
lastAttribute.class = classesString; | ||
} else { | ||
vNode.formats.push(new Format()); | ||
} | ||
} else { | ||
vNode.attributes.class = classesString; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Irrelevant with ClassList
.
441457e
to
7515027
Compare
7515027
to
4b47b7d
Compare
packages/plugin-char/src/Char.ts
Outdated
@@ -32,7 +33,7 @@ export class Char<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T> | |||
handler: this.insertText, | |||
}, | |||
insertHtml: { | |||
handler: this.insertHtml, | |||
handler: this.insertHtml.bind(this), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it's not. The idea (at least at first) was to be able to associate something like makeBold
to applyFormat(BOLD)
. The point is the method name on the plugin does not necessarily match the command name.
if (!domParser) { | ||
// TODO: remove this when the editor can be instantiated on | ||
// something else than DOM. | ||
throw new Error(`No DOM parser installed.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I agree with this comment. I'm not sure, though.
export class HtmlNode extends AtomicNode { | ||
domNode: Node; | ||
constructor(params: HtmlNodeParams) { | ||
super(); | ||
this.domNode = params.domNode; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it's to have a VNode
in our tree that represents a dom Node that needs to specifically be the exact same dom Node at rendering rather than being re-generated, to keep the listeners etc etc. If that's the case then I guess the name of the class could better reflect this.
@@ -37,7 +37,7 @@ | |||
</select> | |||
</t> | |||
<t t-else=""> | |||
<button t-attf-class="fas {{toolbarItem.class}} fa-fw" | |||
<button t-attf-class="fa {{toolbarItem.class}} fa-fw" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess Odoo does not use the same version of FontAwesome as the one @Zinston used ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the previous version of FontAwesome indeed. I thought Odoo had upgraded to FA5 though...
test/core/JWEditor.test.ts
Outdated
// import { expect } from 'chai'; | ||
// import JWEditor from '../../packages/core/src/JWEditor'; | ||
|
||
// function createElementAndAppend(): HTMLElement { | ||
// const element = document.createElement('div'); | ||
// element.innerHTML = ` | ||
// <p>Hello world!</p> | ||
// `; | ||
// document.body.appendChild(element); | ||
// return element; | ||
// } | ||
|
||
// describe('core', () => { | ||
// describe('JWEditor', () => { | ||
// let element; | ||
// beforeEach(() => { | ||
// element = createElementAndAppend(); | ||
// }); | ||
// afterEach(() => { | ||
// element.remove(); | ||
// }); | ||
// it.skip('init and start without argument', () => {}); | ||
// it.skip('init and start with text as value', () => {}); | ||
// it.skip('init and start with html as value', () => {}); | ||
// it('init and start with node inside the dom', () => { | ||
// const editor = new JWEditor(element); | ||
// editor.start(); | ||
// expect(element.parentElement).to.equal(document.body); | ||
// expect(editor.el.parentElement).to.equal(document.body); | ||
// editor.stop(); | ||
// expect(editor.el.parentElement).to.be.null; | ||
|
||
// // try again to check if multiples call generate inconsistencies | ||
// editor.start(); | ||
// expect(element.parentElement).to.equal(document.body); | ||
// expect(editor.el.parentElement).to.equal(document.body); | ||
// editor.stop(); | ||
// expect(editor.el.parentElement).to.be.null; | ||
// }); | ||
// it.skip('init and start with node outside the dom', () => {}); | ||
// }); | ||
// describe('getValue', () => { | ||
// it('should properly get the value once edited', () => { | ||
// const element = createElementAndAppend(); | ||
// const editor = new JWEditor(element); | ||
// editor.start(); | ||
// // todo: simulate keyboard eventns | ||
// expect(editor.getValue()).to.equal('<div><p>Hello world!</p></div>'); | ||
// editor.stop(); | ||
// element.remove(); | ||
// }); | ||
// }); | ||
// describe('setValue', () => { | ||
// it('should properly set the value', () => { | ||
// const element = createElementAndAppend(); | ||
// const element2 = document.createElement('p'); | ||
// element2.innerHTML = 'This is a paragraph'; | ||
|
||
// const editor = new JWEditor(element); | ||
// editor.start(); | ||
// editor.setValue(element2); | ||
// expect(editor.getValue()).to.equal(element2.outerHTML); | ||
// // debugger; | ||
// editor.stop(); | ||
// element.remove(); | ||
// element2.remove(); | ||
// }); | ||
// }); | ||
// }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean delete ?
webpack-base.config.js
Outdated
content, | ||
'return JWEditor', | ||
'});', | ||
].join('\n'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you look at how they did it in owl for that ?
'packages/build-odoo-integration/odoo-integration.ts', | ||
); | ||
|
||
const mainConfig = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have moved the file first in order to read the actual diff.
packages/core/src/Dispatcher.ts
Outdated
|
||
await this._dispatchHooks(commandId, args); | ||
} | ||
return result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result
type: any
Return type: Promise<void>
return result;
...
@@ -277,7 +289,7 @@ export class JWEditor { | |||
commandName: C, | |||
params?: CommandParams<P, C>, | |||
): Promise<void> { | |||
await this.dispatcher.dispatch(commandName, params); | |||
return await this.dispatcher.dispatch(commandName, params); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This goes with the comment above about the Dispatcher
.
webpack-base.config.js
Outdated
const content = await fs.promises.readFile(filename); | ||
const newContent = [ | ||
"odoo.define('web_editor.jabberwock', function(require) {", | ||
"// 'use strict';", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the //
?
7b4ec3d
to
1fadef6
Compare
1fadef6
to
601ca2f
Compare
[FIX] OdooSnippet: apply classes to LinkFormat instead of CharNodes (and unbreakable divider)
d014667
to
58da570
Compare
I'm closing this PR in favor of #210. |
Corresponding Odoo branch:
master-implement-jabberwock-nby
Original odoo branch commits for comment safeguarding purposes:
odoo-dev/odoo@ba26712
odoo-dev/odoo@05fefe2