-
-
Notifications
You must be signed in to change notification settings - Fork 392
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core/beforeSave): support modifications before save (#3909)
- Loading branch information
1 parent
cee0f04
commit 56552de
Showing
5 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { docLink, showError } from "./utils.js"; | ||
import { sub } from "./pubsubhub.js"; | ||
|
||
export const name = "core/before-save"; | ||
|
||
export function run(conf) { | ||
if (!conf.beforeSave) return; | ||
|
||
if ( | ||
!Array.isArray(conf.beforeSave) || | ||
conf.beforeSave.some( | ||
el => typeof el !== "function" || el.constructor.name === "AsyncFunction" | ||
) | ||
) { | ||
const msg = docLink`${"[beforeSave]"} configuration option must be an array of synchronous JS functions.`; | ||
showError(msg, name); | ||
return; | ||
} | ||
|
||
sub( | ||
"beforesave", | ||
documentElement => { | ||
performTransformations(conf.beforeSave, documentElement.ownerDocument); | ||
}, | ||
{ once: true } | ||
); | ||
} | ||
/** | ||
* @param {Array<Function>} transforms | ||
* @param {Document} | ||
*/ | ||
function performTransformations(transforms, doc) { | ||
let pos = 0; | ||
for (const fn of transforms) { | ||
try { | ||
fn(doc); | ||
} catch (err) { | ||
const nameOrPosition = `\`${fn.name}\`` || `at position ${pos}`; | ||
const msg = docLink`Function ${nameOrPosition}\` threw an error during processing of ${"[beforeSave]"}.`; | ||
const hint = "See developer console."; | ||
showError(msg, name, { hint }); | ||
console.error(err); | ||
} finally { | ||
pos++; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<script class="remove"> | ||
const modifier1 = exportedDoc => { | ||
const p = exportedDoc.createElement("p"); | ||
p.id = "p1"; | ||
p.textContent = "This is paragraph 1"; | ||
exportedDoc.body.appendChild(p); | ||
}; | ||
const modifier2 = exportedDoc => { | ||
const p = exportedDoc.createElement("p"); | ||
p.id = "p2"; | ||
p.textContent = "This is a sync paragraph"; | ||
exportedDoc.body.appendChild(p); | ||
}; | ||
const respecConfig = { | ||
specStatus: "unofficial", | ||
shortName: "i", | ||
editors: [ | ||
{ name: "Foo", url: "https://foo.com/" }, | ||
], | ||
beforeSave: [modifier1, modifier2], | ||
}; | ||
</script> | ||
<section id="abstract"> | ||
<p>abstract.</p> | ||
</section> | ||
<section id="sotd"> | ||
<p>CUSTOM PARAGRAPH</p> | ||
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { | ||
errorFilters, | ||
flushIframes, | ||
getExportedDoc, | ||
makeRSDoc, | ||
makeStandardOps, | ||
} from "../SpecHelper.js"; | ||
|
||
describe("Core - beforeSave config option", () => { | ||
afterAll(flushIframes); | ||
const beforeSaveErrors = errorFilters.filter("core/before-save"); | ||
it("allows modification before saving", async () => { | ||
const ops = makeStandardOps(); | ||
ops.config = null; // use src doc's config | ||
const doc = await makeRSDoc(ops, "spec/core/before-save-spec.html"); | ||
expect(doc.getElementById("p1")).toBeNull(); | ||
expect(doc.getElementById("p2")).toBeNull(); | ||
const exportedDoc = await getExportedDoc(doc); | ||
expect(exportedDoc.querySelectorAll("#p1").length).toBe(1); | ||
expect(exportedDoc.querySelectorAll("#p2").length).toBe(1); | ||
// make sure that the functions are run in order... | ||
const p1 = exportedDoc.querySelector("#p1"); | ||
const p2 = exportedDoc.querySelector("#p2"); | ||
expect(p1.nextElementSibling).toBe(p2); | ||
}); | ||
|
||
it("complains if it's not passed an array", async () => { | ||
const ops = makeStandardOps({ beforeSave: "not a array" }); | ||
const doc = await makeRSDoc(ops); | ||
const errors = beforeSaveErrors(doc); | ||
expect(errors.length).toBe(1); | ||
expect(errors[0].message).toContain("array of synchronous JS functions"); | ||
}); | ||
|
||
it("complains if it's not passed a function in the array", async () => { | ||
const ops = makeStandardOps({ beforeSave: ["not a function", () => {}] }); | ||
const doc = await makeRSDoc(ops); | ||
const errors = beforeSaveErrors(doc); | ||
expect(errors.length).toBe(1); | ||
expect(errors[0].message).toContain("array of synchronous JS functions"); | ||
}); | ||
|
||
it("complains if passed an async function", async () => { | ||
const ops = makeStandardOps({ beforeSave: [() => {}, async () => {}] }); | ||
const doc = await makeRSDoc(ops); | ||
const errors = beforeSaveErrors(doc); | ||
expect(errors.length).toBe(1); | ||
expect(errors[0].message).toContain("array of synchronous JS functions"); | ||
}); | ||
}); |