wrappers around replacement strings {foo}
- * Example input: {foo}
- * Example output: {foo}
- * @param {string} html
- * @returns {string}
- */
-function removeCodeWrappers(html) {
+interface CleanBasicHtmlOptions {
+ allowBr?: boolean;
+ firstChildInnerContent?: boolean;
+ removeCodeWrappers?: boolean;
+ createDocument?: (html: string) => Document;
+}
+
+function removeCodeWrappers(html: string): string {
return html.replace(/]*>((.*?){.*?}(.*?))<\/code>/gi, '$1');
}
-/**
- * Parses an html string and returns a cleaned version
- * @param {string} html
- * @param {Object} _options
- * @param {boolean} [_options.allowBr] - if true,
tags will be kept
- * @param {boolean} [_options.firstChildInnerContent] - if true, only the innerHTML of the first element will be returned
- * @param {boolean} [_options.removeCodeWrappers] - if true, wrappers around replacement strings {foo} will be removed
- * @returns {string}
- */
-export default function cleanBasicHtml(html = '', _options = {}) {
+export default function cleanBasicHtml(html: string = '', _options: CleanBasicHtmlOptions = {}): string | null {
const defaults = {};
- const options = Object.assign({}, defaults, _options);
+ const options: CleanBasicHtmlOptions = Object.assign({}, defaults, _options);
if (!options.createDocument) {
const Parser = (typeof DOMParser !== 'undefined' && DOMParser) || (typeof window !== 'undefined' && window.DOMParser);
if (!Parser) {
- // eslint-disable-next-line ghost/ghost-custom/no-native-error
throw new Error('cleanBasicHtml() must be passed a `createDocument` function as an option when used in a non-browser environment');
}
- options.createDocument = function (docHtml) {
+ options.createDocument = function (docHtml: string): Document {
const parser = new Parser();
return parser.parseFromString(docHtml, 'text/html');
};
}
- let cleanHtml = html;
+ let cleanHtml: string = html;
if (!options.allowBr || cleanHtml === '
') {
cleanHtml = cleanHtml
@@ -55,7 +45,7 @@ export default function cleanBasicHtml(html = '', _options = {}) {
// remove any elements that have a blank textContent
if (cleanHtml) {
- let doc = options.createDocument(cleanHtml);
+ const doc = options.createDocument(cleanHtml);
// don't analyze the document if it's empty (can result in storing
tags if allowed)
if (doc.body.textContent === '') {
@@ -64,7 +54,7 @@ export default function cleanBasicHtml(html = '', _options = {}) {
doc.body.querySelectorAll('*').forEach((element) => {
// Treat Zero Width Non-Joiner characters as spaces
- if (!element.textContent.trim().replace(/\u200c+/g, '')) {
+ if (!element.textContent?.trim().replace(/\u200c+/g, '')) {
if (options.allowBr && element.tagName === 'BR') {
// keep it
return;
@@ -72,9 +62,9 @@ export default function cleanBasicHtml(html = '', _options = {}) {
if (options.allowBr && element.querySelector('br')) {
return element.replaceWith(doc.createElement('br'));
}
- if (element.textContent.length > 0) {
+ if (element.textContent && element.textContent.length > 0) {
// keep a single space to avoid collapsing spaces
- let space = doc.createTextNode(' ');
+ const space = doc.createTextNode(' ');
return element.replaceWith(space);
}
return element.remove();
diff --git a/packages/kg-clean-basic-html/src/index.ts b/packages/kg-clean-basic-html/src/index.ts
new file mode 100644
index 0000000000..400c8e18ee
--- /dev/null
+++ b/packages/kg-clean-basic-html/src/index.ts
@@ -0,0 +1 @@
+export {default} from './clean-basic-html.js';
diff --git a/packages/kg-clean-basic-html/test/clean-basic-html.test.js b/packages/kg-clean-basic-html/test/clean-basic-html.test.ts
similarity index 74%
rename from packages/kg-clean-basic-html/test/clean-basic-html.test.js
rename to packages/kg-clean-basic-html/test/clean-basic-html.test.ts
index 81c46370fb..8219014bf3 100644
--- a/packages/kg-clean-basic-html/test/clean-basic-html.test.js
+++ b/packages/kg-clean-basic-html/test/clean-basic-html.test.ts
@@ -1,16 +1,17 @@
// Switch these lines once there are useful utils
-// const testUtils = require('./utils');
-require('./utils');
+// import testUtils from './utils/index.js';
+import './utils/index.js';
-const {JSDOM} = require('jsdom');
-const cleanBasicHtml = require('../');
+import should from 'should';
+import {JSDOM} from 'jsdom';
+import cleanBasicHtml from '../src/clean-basic-html.js';
describe('cleanBasicHtml', function () {
- let options = {};
+ let options: {createDocument: (html: string) => Document};
before(function () {
options = {
- createDocument(html) {
+ createDocument(html: string) {
return (new JSDOM(html)).window.document;
}
};
@@ -26,42 +27,42 @@ describe('cleanBasicHtml', function () {
const html = '
';
const result = cleanBasicHtml(html, options);
- result.should.equal('');
+ (result as string).should.equal('');
});
it('keeps whitespace between text', function () {
const html = '
Testing Significant Whitespace
';
const result = cleanBasicHtml(html, options);
- result.should.equal('Testing Significant Whitespace');
+ (result as string).should.equal('Testing Significant Whitespace');
});
it('removes DOM elements with blank text content', function () {
const html = '
';
const result = cleanBasicHtml(html, options);
- result.should.equal('');
+ (result as string).should.equal('');
});
it('keeps elements with text content', function () {
const html = ' Test ';
const result = cleanBasicHtml(html, options);
- result.should.equal(' Test ');
+ (result as string).should.equal(' Test ');
});
it('can extract first element content', function () {
const html = 'Headline italic
';
const result = cleanBasicHtml(html, {...options, firstChildInnerContent: true});
- result.should.equal('Headline italic');
+ (result as string).should.equal('Headline italic');
});
it('return empty string if firstChildInnerContent option enabled and there is no first child element ', function () {
const html = '';
const result = cleanBasicHtml(html, {...options, firstChildInnerContent: true});
- result.should.equal('');
+ (result as string).should.equal('');
});
describe('options.removeCodeWrappers', function () {
@@ -69,21 +70,21 @@ describe('cleanBasicHtml', function () {
const html = '{foo}';
const result = cleanBasicHtml(html, {...options, removeCodeWrappers: true});
- result.should.equal('{foo}');
+ (result as string).should.equal('{foo}');
});
it('removes any wrappers around replacement strings {foo}', function () {
const html = '{foo}';
const result = cleanBasicHtml(html, {...options, removeCodeWrappers: true});
- result.should.equal('{foo}');
+ (result as string).should.equal('{foo}');
});
it('removes any wrappers around replacement strings {foo, "default"}', function () {
const html = 'Hey {first_name, "there"},
';
const result = cleanBasicHtml(html, {...options, removeCodeWrappers: true});
- result.should.equal('Hey {first_name, "there"},
');
+ (result as string).should.equal('Hey {first_name, "there"},
');
});
});
});
diff --git a/packages/kg-clean-basic-html/test/utils/assertions.js b/packages/kg-clean-basic-html/test/utils/assertions.ts
similarity index 100%
rename from packages/kg-clean-basic-html/test/utils/assertions.js
rename to packages/kg-clean-basic-html/test/utils/assertions.ts
diff --git a/packages/kg-clean-basic-html/test/utils/index.js b/packages/kg-clean-basic-html/test/utils/index.ts
similarity index 76%
rename from packages/kg-clean-basic-html/test/utils/index.js
rename to packages/kg-clean-basic-html/test/utils/index.ts
index 0d67d86ff8..f385b7bf56 100644
--- a/packages/kg-clean-basic-html/test/utils/index.js
+++ b/packages/kg-clean-basic-html/test/utils/index.ts
@@ -5,7 +5,7 @@
*/
// Require overrides - these add globals for tests
-require('./overrides');
+import './overrides.js';
// Require assertions - adds custom should assertions
-require('./assertions');
+import './assertions.js';
diff --git a/packages/kg-clean-basic-html/test/utils/overrides.js b/packages/kg-clean-basic-html/test/utils/overrides.js
deleted file mode 100644
index 90203424ee..0000000000
--- a/packages/kg-clean-basic-html/test/utils/overrides.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is required before any test is run
-
-// Taken from the should wiki, this is how to make should global
-// Should is a global in our eslint test config
-global.should = require('should').noConflict();
-should.extend();
-
-// Sinon is a simple case
-// Sinon is a global in our eslint test config
-global.sinon = require('sinon');
diff --git a/packages/kg-clean-basic-html/test/utils/overrides.ts b/packages/kg-clean-basic-html/test/utils/overrides.ts
new file mode 100644
index 0000000000..6138e929ff
--- /dev/null
+++ b/packages/kg-clean-basic-html/test/utils/overrides.ts
@@ -0,0 +1,15 @@
+// This file is required before any test is run
+
+// Taken from the should wiki, this is how to make should global
+// Should is a global in our eslint test config
+import should from 'should';
+import sinon from 'sinon';
+
+// @types/should is incomplete — noConflict and extend exist at runtime
+const shouldModule = should as unknown as {noConflict(): typeof should; extend(): void};
+Object.defineProperty(globalThis, 'should', {value: shouldModule.noConflict(), writable: true, configurable: true});
+shouldModule.extend();
+
+// Sinon is a simple case
+// Sinon is a global in our eslint test config
+Object.defineProperty(globalThis, 'sinon', {value: sinon, writable: true, configurable: true});
diff --git a/packages/kg-clean-basic-html/tsconfig.cjs.json b/packages/kg-clean-basic-html/tsconfig.cjs.json
new file mode 100644
index 0000000000..bd981491bc
--- /dev/null
+++ b/packages/kg-clean-basic-html/tsconfig.cjs.json
@@ -0,0 +1,13 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "outDir": "build/cjs",
+ "verbatimModuleSyntax": false,
+ "declaration": false,
+ "declarationMap": false,
+ "sourceMap": false,
+ "incremental": false
+ }
+}
diff --git a/packages/kg-clean-basic-html/tsconfig.json b/packages/kg-clean-basic-html/tsconfig.json
new file mode 100644
index 0000000000..56c51dd045
--- /dev/null
+++ b/packages/kg-clean-basic-html/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "es2022",
+ "module": "ES2022",
+ "moduleResolution": "bundler",
+ "rootDir": "src",
+ "outDir": "build/esm",
+ "strict": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "incremental": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/kg-clean-basic-html/tsconfig.test.json b/packages/kg-clean-basic-html/tsconfig.test.json
new file mode 100644
index 0000000000..b092804ad8
--- /dev/null
+++ b/packages/kg-clean-basic-html/tsconfig.test.json
@@ -0,0 +1,16 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "rootDir": ".",
+ "outDir": null,
+ "noEmit": true,
+ "declaration": false,
+ "declarationMap": false,
+ "sourceMap": false,
+ "incremental": false
+ },
+ "include": [
+ "src/**/*",
+ "test/**/*"
+ ]
+}