Skip to content

Commit

Permalink
add returnedValueIsTrustedHtml so the function used on original ele…
Browse files Browse the repository at this point in the history
…ment is `innerHTML` instead of the safer `innerText`
  • Loading branch information
NicolasCARPi committed May 6, 2023
1 parent c98620c commit 745d699
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog for malle

## 2.3.0

* Add `returnedValueIsTrustedHtml` so the function used on original element is `innerHTML` instead of the safer `innerText`.

## 2.2.0

* Add `color`, `date`, `time` input types.
Expand Down
7 changes: 7 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ default: `true`

By default, the `fun` function won't be called in the input value is the same as the original value. Set to `false` to always call `fun` regardless of input.

#### returnedValueIsTrustedHtml
boolean

default: `false`

If `true`, `innerHTML` is used instead of `innerText` with the returned value from the server. Helps with html-encoded strings ending up wrongly displayed after an edit/save. Only set to `true` if you sanitize output and have a strict CSP.

#### selectOptions
`Array<SelectOptions>`

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@deltablot/malle",
"version": "2.2.0",
"version": "2.3.0",
"description": "Make text elements malleable, without dependencies.",
"main": "dist/main.js",
"typings": "dist/main.d.ts",
Expand Down
12 changes: 9 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface Options {
onEnter?: Action;
placeholder?: string;
requireDiff?: boolean;
returnedValueIsTrustedHtml?: boolean;
selectOptions?: Array<SelectOptions> | Promise<Array<SelectOptions>>;
selectOptionsValueKey?: string;
selectOptionsTextKey?: string;
Expand All @@ -69,13 +70,17 @@ export class Malle {
opt: Options;
original: HTMLElement;
input: HTMLInputElement|HTMLSelectElement;
innerFun: string;

constructor(options: Options) {
this.opt = this.normalizeOptions(options);
this.debug(`Options: ${JSON.stringify(this.opt)}`);
if (this.opt.listenNow) {
this.listen();
}
// by default we use innerText to insert the return value, but if we know it's trusted html we get back, we allow using innerHTML instead
// once setHTML() becomes more widespread, we'll use that instead
this.innerFun = this.opt.returnedValueIsTrustedHtml ? 'innerHTML' : 'innerText';
}

/**
Expand All @@ -102,6 +107,7 @@ export class Malle {
onEnter: Action.Submit,
placeholder: '',
requireDiff: true,
returnedValueIsTrustedHtml: false,
selectOptions: [],
selectOptionsValueKey: 'value',
selectOptionsTextKey: 'text',
Expand Down Expand Up @@ -164,7 +170,7 @@ export class Malle {
}
}
this.opt.fun.call(this, this.input.value, this.original, event, this.input).then((value: string) => {
this.original.innerText = this.opt.inputType === InputType.Select ? (this.input as HTMLSelectElement).options[(this.input as HTMLSelectElement).selectedIndex].text : value;
this.original[this.innerFun] = this.opt.inputType === InputType.Select ? (this.input as HTMLSelectElement).options[(this.input as HTMLSelectElement).selectedIndex].text : value;
this.form.replaceWith(this.original);
// execute the after hook
if (typeof this.opt.after === 'function') {
Expand Down Expand Up @@ -268,8 +274,8 @@ export class Malle {
o.forEach(o => {
const option = document.createElement('option');
option.value = o[this.opt.selectOptionsValueKey];
option.innerText = o[this.opt.selectOptionsTextKey];
option.selected = (o.selected ?? false) || this.original.innerText === o[this.opt.selectOptionsTextKey];
option[this.innerFun] = o[this.opt.selectOptionsTextKey];
option.selected = (o.selected ?? false) || this.original[this.innerFun] === o[this.opt.selectOptionsTextKey];
input.appendChild(option);
});
});
Expand Down

0 comments on commit 745d699

Please sign in to comment.