Skip to content

Commit

Permalink
fix: Fix issues detected by integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
mmichaelis committed Oct 6, 2023
1 parent 537c1af commit 5deb873
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
47 changes: 42 additions & 5 deletions packages/ckeditor5-coremedia-bbcode/src/rules/BBCodeCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,46 @@ import { BBCodeProcessingRule } from "./BBCodeProcessingRule";
import { removeLeadingAndTrailingNewlines } from "../BBCodeUtils";

const escapeLanguage = (language: string): string => language.replace(/([\][])/g, "\\$1");

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.
const ckeditorCodeBlockLanguageClassPrefix = "language-";

/**
* Determines the language as it is set in CKEditor's data view for a given
* code block. The language is attached as class to the nested `<code>`
* element, like `language-css`. For plain text, the class added is
* `language-plaintext`. Classes like this may be ignored by optional
* parameter `forceUnset`.
*
* Typical CKEditor Code Blocks:
*
* ```xml
* <pre><code class="language-plaintext">TEXT</code></pre>
* <pre><code class="language-css">CSS</code></pre>
* ```
*
* @param element - element to try to determine language for
* @param forceUnset - languages that enforce `undefined` as return value
* @returns the detected language or `undefined` if it cannot be determined or
* is enforced to signal _unset_.
*/
const determineLanguage = (element: HTMLPreElement, forceUnset = ["plaintext"]): string | undefined => {
const { firstElementChild } = element;
if (!(firstElementChild instanceof HTMLElement)) {
return;
}

const languageCls = Array.from(firstElementChild.classList).find((cls) =>
cls.startsWith(ckeditorCodeBlockLanguageClassPrefix),
);
if (!languageCls) {
return;
}

const language = languageCls.replace(ckeditorCodeBlockLanguageClassPrefix, "");
if (!language || forceUnset.includes(language)) {
return;
}
return language;
};

/**
* Maps `<pre>` to `[code]`.
Expand All @@ -13,13 +53,10 @@ export class BBCodeCode implements BBCodeProcessingRule {
if (!(element instanceof HTMLPreElement)) {
return;
}
// CKEditor 5 encodes the language as `language` in dataset.
const {
dataset: { language },
} = element;
const language = determineLanguage(element);
const trimmed = removeLeadingAndTrailingNewlines(content);
if (language) {
return `[code=${escapeLanguage(language)}]${trimmed}\n[/code]\n`;
return `[code=${escapeLanguage(language)}]\n${trimmed}\n[/code]\n`;
}
return `[code]\n${trimmed}\n[/code]\n`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class BBCodeList implements BBCodeProcessingRule {
return `[list]\n${content.trim()}\n[/list]\n`;
}
if (element instanceof HTMLOListElement) {
return `[list=${element.type}]\n${content.trim()}\n[/list]\n`;
return `[list=${element.type || "1"}]\n${content.trim()}\n[/list]\n`;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BBCodeProcessingRule } from "./BBCodeProcessingRule";
import { isText } from "@coremedia/ckeditor5-dom-support";

/**
* Maps `<thead>`, `<tbody>`, `<tfoot>` to corresponding BBCode.
Expand All @@ -10,19 +11,26 @@ export class BBCodeTableSection implements BBCodeProcessingRule {
if (!(element instanceof HTMLTableSectionElement)) {
return;
}
const { tagName } = element;
const { nextSibling, tagName } = element;

// Minor Pretty-Print Optimization to not pile up newlines when a
// corresponding newline already exists in HTML.
const finalNewline = isText(nextSibling) && nextSibling?.textContent?.startsWith("\n") ? "" : "\n";

const normalizedTagName = tagName.toLowerCase();

switch (normalizedTagName) {
case "thead":
return `[thead]\n${content.trim()}\n[/thead]\n`;
return `[thead]\n${content.trim()}\n[/thead]${finalNewline}`;
case "tfoot":
return `[tfoot]\n${content.trim()}\n[/tfoot]\n`;
return `[tfoot]\n${content.trim()}\n[/tfoot]${finalNewline}`;
case "tbody":
// More detailed handling below.
break;
default:
return;
}

// We now know that we have a `<tbody>` element. Apply some
// simplification to the resulting BBCode, when `<tbody>` is the only
// table section element.
Expand All @@ -32,7 +40,7 @@ export class BBCodeTableSection implements BBCodeProcessingRule {
// within the table. Thus, no need for surrounding `[tbody]`.
return content.trim();
}
return `[tbody]\n${content.trim()}\n[/tbody]\n`;
return `[tbody]\n${content.trim()}\n[/tbody]${finalNewline}`;
}
}

Expand Down

0 comments on commit 5deb873

Please sign in to comment.