[FIX] compiler: call translate function with correct string

Before this commit, the parser would remove all consecutive white spaces
for text nodes. After that, the code generator would call the translate
function with the resulting string, which then is different than what we
would expect.

With this commit, we make sure we apply the translation before removing
the additional whitespace. To do that, we have to move the code
processing the string from the parser into the code generator, which
actually makes sense, as the parser should only collect all useful
information without applying too much logic.

closes #1351
This commit is contained in:
Géry Debongnie
2023-03-06 12:00:25 +01:00
committed by Sam Degueldre
parent cdad48d3a6
commit 7ac81ed5fe
5 changed files with 35 additions and 8 deletions
+6
View File
@@ -32,6 +32,7 @@ import {
import { OwlError } from "../runtime/error_handling";
type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
const whitespaceRE = /\s+/g;
export interface Config {
translateFn?: (s: string) => string;
@@ -166,6 +167,7 @@ interface Context {
nameSpace?: string;
tModelSelectedExpr?: string;
ctxVar?: string;
inPreTag?: boolean;
}
function createContext(parentCtx: Context, params?: Partial<Context>): Context {
@@ -534,6 +536,9 @@ export class CodeGenerator {
const match = translationRE.exec(value) as any;
value = match[1] + this.translateFn(match[2]) + match[3];
}
if (!ctx.inPreTag) {
value = value.replace(whitespaceRE, " ");
}
if (!block || forceNewBlock) {
block = this.createBlock(block, "text", ctx);
@@ -746,6 +751,7 @@ export class CodeGenerator {
tKeyExpr: ctx.tKeyExpr,
nameSpace,
tModelSelectedExpr,
inPreTag: ctx.inPreTag || ast.tag === "pre",
});
this.compileAST(child, subCtx);
}
+2 -6
View File
@@ -261,16 +261,12 @@ function parseTNode(node: Element, ctx: ParsingContext): AST | null {
// Text and Comment Nodes
// -----------------------------------------------------------------------------
const lineBreakRE = /[\r\n]/;
const whitespaceRE = /\s+/g;
function parseTextCommentNode(node: Node, ctx: ParsingContext): AST | null {
if (node.nodeType === Node.TEXT_NODE) {
let value = node.textContent || "";
if (!ctx.inPreTag) {
if (lineBreakRE.test(value) && !value.trim()) {
return null;
}
value = value.replace(whitespaceRE, " ");
if (!ctx.inPreTag && lineBreakRE.test(value) && !value.trim()) {
return null;
}
return { type: ASTType.Text, value };
@@ -64,3 +64,16 @@ exports[`translation support translation is done on the trimmed text, with extra
}
}"
`;
exports[`translation support translation works, even if initial string has inner consecutive white space 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>un mot</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
+2 -2
View File
@@ -26,10 +26,10 @@ describe("qweb parser", () => {
});
});
test("white spaces are condensed into a single space", async () => {
test("white spaces are maintained", async () => {
expect(parse(" ")).toEqual({
type: ASTType.Text,
value: " ",
value: " ",
});
});
+12
View File
@@ -88,4 +88,16 @@ describe("translation support", () => {
expect(fixture.innerHTML).toBe("<div> mot </div>");
expect(translateFn).toHaveBeenCalledWith("word");
});
test("translation works, even if initial string has inner consecutive white space", async () => {
class SomeComponent extends Component {
static template = xml`<div>some word</div>`;
}
const translateFn = jest.fn((expr: string) => (expr === "some word" ? "un mot" : expr));
await mount(SomeComponent, fixture, { translateFn });
expect(translateFn).toHaveBeenCalledWith("some word");
expect(fixture.innerHTML).toBe("<div>un mot</div>");
});
});