@prezly/docx-cleaner
Advanced tools
Comparing version 0.4.0 to 0.5.0
{ | ||
"name": "@prezly/docx-cleaner", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Normalize dirty HTML and DOCX/RTF documents into clean, understandable HTML", | ||
"license": "MIT", | ||
"main": "build/index.js", | ||
"types": "build/index.d.ts", | ||
"type": "module", | ||
"main": "build/cjs/index.cjs", | ||
"module": "build/esm/index.mjs", | ||
"types": "build/types/index.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./build/types/index.d.ts", | ||
"import": "./build/esm/index.mjs", | ||
"default": "./build/cjs/index.cjs" | ||
} | ||
}, | ||
"files": [ | ||
@@ -21,19 +30,24 @@ "build", | ||
"scripts": { | ||
"build": "tsc --project .", | ||
"build:watch": "tsc -w --project .", | ||
"check": "npm run prettier && npm run test", | ||
"build": "npm run build:types && npm run build:esm && npm run build:cjs", | ||
"build:types": "tsc --build .", | ||
"build:esm": "gulp build:esm", | ||
"build:cjs": "gulp build:cjs", | ||
"watch": "concurrently --kill-others --names 'd.ts,esm ,cjs ' 'npm run watch:types' 'npm run watch:esm' 'npm run watch:cjs'", | ||
"watch:types": "tsc-fancy --preserveConsoleOutput --build . --watch", | ||
"watch:esm": "gulp watch:esm", | ||
"watch:cjs": "gulp watch:cjs", | ||
"test": "npm run test:unit && npm run test:build", | ||
"test:unit": "jest --no-cache --coverage", | ||
"test:build": "npm run test:cjs && npm run test:esm", | ||
"test:esm": "node mockDOMParser.js build/esm/index.mjs", | ||
"test:cjs": "node mockDOMParser.js build/cjs/index.cjs", | ||
"check": "npm run prettier && npm run lint", | ||
"clean": "rimraf build/ node_modules/", | ||
"lint": "eslint ./src --ext .ts", | ||
"prettier": "prettier --check './**/*.(js|ts)'", | ||
"prettier:fix": "npm run prettier -- --write --no-list-different", | ||
"test": "jest --no-cache --coverage", | ||
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --no-cache --watch", | ||
"test:watch": "jest --no-cache --watch", | ||
"release": "npm run release:prepare && npm run release:publish", | ||
"release:prepare": "npm run clean && npm install && npm run build && npm run check", | ||
"release:prepare": "npm run clean && npm install && npm run build && npm run check && npm run test", | ||
"release:publish": "np" | ||
}, | ||
"engines": { | ||
"node": ">=14.0", | ||
"npm": ">=7.0" | ||
}, | ||
"dependencies": { | ||
@@ -43,4 +57,16 @@ "validator": "^13.5.2" | ||
"devDependencies": { | ||
"@babel/core": "^7.16.5", | ||
"@babel/preset-env": "^7.16.5", | ||
"@babel/preset-typescript": "^7.16.5", | ||
"@types/jest": "^27.0.2", | ||
"@types/validator": "^13.1.3", | ||
"@typescript-eslint/eslint-plugin": "^5.8.1", | ||
"@typescript-eslint/parser": "^5.8.1", | ||
"babel-plugin-add-import-extension": "^1.6.0", | ||
"concurrently": "^6.5.1", | ||
"eslint": "^8.5.0", | ||
"eslint-plugin-import": "^2.25.3", | ||
"gulp": "^4.0.2", | ||
"gulp-babel": "^8.0.0", | ||
"gulp-rename": "^2.0.0", | ||
"jest": "^27.3.1", | ||
@@ -51,4 +77,5 @@ "np": "^7.5.0", | ||
"ts-jest": "^27.0.7", | ||
"tsc-fancy": "^1.1.2", | ||
"typescript": "^4.4.4" | ||
} | ||
} |
@@ -17,3 +17,3 @@ # @prezly/docx-cleaner | ||
const handlePaste = (event: ClipboardEvent<HTMLTextAreaElement>) => { | ||
function handlePaste(event: ClipboardEvent<HTMLTextAreaElement>) { | ||
const html = event.clipboardData.getData('text/html'); | ||
@@ -20,0 +20,0 @@ const rtf = event.clipboardData.getData('text/rtf'); |
@@ -1,2 +0,2 @@ | ||
import cleanDocx from './cleanDocx'; | ||
import { cleanDocx } from './cleanDocx'; | ||
import { readTestFile } from './test-utils'; | ||
@@ -3,0 +3,0 @@ |
@@ -20,3 +20,3 @@ import { | ||
const cleanDocx = (html: string, rtf: string): string => { | ||
export function cleanDocx(html: string, rtf: string): string { | ||
const document = parser.parseFromString(preCleanHtml(html), 'text/html'); | ||
@@ -42,4 +42,2 @@ const { body } = document; | ||
return postCleanHtml(body.innerHTML); | ||
}; | ||
export default cleanDocx; | ||
} |
@@ -1,5 +0,56 @@ | ||
export * from './constants'; | ||
export * from './lib'; | ||
export * from './types'; | ||
export { LINE_FEED, NO_BREAK_SPACE, SPACE, ZERO_WIDTH_SPACE, CARRIAGE_RETURN } from './constants'; | ||
export { | ||
cleanTabCount, | ||
cleanTextNodes, | ||
isDocxContent, | ||
postCleanHtml, | ||
preCleanHtml, | ||
getListContentHtml, | ||
cleanSpans, | ||
cleanCrLf, | ||
cleanQuotes, | ||
changeTagName, | ||
cleanEmptyElements, | ||
cleanEmptyParagraphs, | ||
cleanFontElements, | ||
cleanFootnotes, | ||
cleanImageElements, | ||
cleanLinkElements, | ||
cleanListElements, | ||
getVShapes, | ||
getVShapeSpid, | ||
getRtfImagesByType, | ||
getRtfImagesMap, | ||
getRtfImageHex, | ||
getRtfImageSpid, | ||
getRtfImageMimeType, | ||
traverseTexts, | ||
traverseElements, | ||
unwrapElement, | ||
parseHtmlElement, | ||
cleanBrElements, | ||
cleanSpacerun, | ||
isElement, | ||
generateSpaces, | ||
getComments, | ||
isComment, | ||
traverseComments, | ||
traverse, | ||
getListLevel, | ||
isList, | ||
getListTypeNode, | ||
hexToBase64, | ||
isBookmark, | ||
isFootnote, | ||
isOrderedList, | ||
isOrderedListSymbol, | ||
isFragmentHref, | ||
isText, | ||
removeNodesBetweenComments, | ||
removeHtmlSurroundings, | ||
buildList, | ||
} from './lib'; | ||
export { default as cleanDocx } from './cleanDocx'; | ||
export type { RtfImagesMap, RtfImage } from './types'; | ||
export { cleanDocx } from './cleanDocx'; |
/* eslint-disable no-continue */ | ||
import getListContentHtml from './getListContentHtml'; | ||
import getListLevel from './getListLevel'; | ||
import isBookmark from './isBookmark'; | ||
import isList from './isList'; | ||
import isOrderedList from './isOrderedList'; | ||
import parseHtmlElement from './parseHtmlElement'; | ||
import { getListContentHtml } from './getListContentHtml'; | ||
import { getListLevel } from './getListLevel'; | ||
import { isBookmark } from './isBookmark'; | ||
import { isList } from './isList'; | ||
import { isOrderedList } from './isOrderedList'; | ||
import { parseHtmlElement } from './parseHtmlElement'; | ||
@@ -15,3 +15,3 @@ interface Result { | ||
const buildList = (element: Element): Result => { | ||
export function buildList(element: Element): Result { | ||
const listLevel = getListLevel(element); | ||
@@ -59,4 +59,2 @@ let listHtml = ''; | ||
return { list, nextSibling }; | ||
}; | ||
export default buildList; | ||
} |
@@ -1,2 +0,2 @@ | ||
const changeTagName = (element: Element, tagName: string): Element => { | ||
export function changeTagName(element: Element, tagName: string): Element { | ||
const newElement = document.createElement(tagName); | ||
@@ -19,4 +19,2 @@ | ||
return newElement; | ||
}; | ||
export default changeTagName; | ||
} |
import { LINE_FEED } from '../constants'; | ||
import isComment from './isComment'; | ||
import removeNodesBetweenComments from './removeNodesBetweenComments'; | ||
import traverseElements from './traverseElements'; | ||
import { isComment } from './isComment'; | ||
import { removeNodesBetweenComments } from './removeNodesBetweenComments'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanBrElements = (rootNode: Node): void => { | ||
export function cleanBrElements(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -33,4 +33,2 @@ if (element.tagName !== 'BR') { | ||
}); | ||
}; | ||
export default cleanBrElements; | ||
} |
@@ -1,5 +0,3 @@ | ||
const cleanCrLf = (html: string): string => { | ||
export function cleanCrLf(html: string): string { | ||
return html.replace(/\r\n/gm, '\n').replace(/\r/gm, '\n'); | ||
}; | ||
export default cleanCrLf; | ||
} |
@@ -1,10 +0,10 @@ | ||
import traverseElements from './traverseElements'; | ||
import { traverseElements } from './traverseElements'; | ||
const ALLOWED_EMPTY_ELEMENTS = ['BR', 'IMG']; | ||
const isEmpty = (element: Element): boolean => { | ||
function isEmpty(element: Element): boolean { | ||
return !ALLOWED_EMPTY_ELEMENTS.includes(element.nodeName) && !element.innerHTML.trim(); | ||
}; | ||
} | ||
const removeIfEmpty = (element: Element): void => { | ||
function removeIfEmpty(element: Element): void { | ||
if (isEmpty(element)) { | ||
@@ -19,5 +19,5 @@ const { parentElement } = element; | ||
} | ||
}; | ||
} | ||
const cleanEmptyElements = (rootNode: Node): void => { | ||
export function cleanEmptyElements(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -27,4 +27,2 @@ removeIfEmpty(element); | ||
}); | ||
}; | ||
export default cleanEmptyElements; | ||
} |
@@ -5,14 +5,18 @@ /* eslint-disable no-param-reassign */ | ||
import traverseElements from './traverseElements'; | ||
import { traverseElements } from './traverseElements'; | ||
const isEmptyOp = (element: Element): boolean => | ||
element.nodeName === 'O:P' && element.textContent === NO_BREAK_SPACE; | ||
function isEmptyOp(element: Element): boolean { | ||
return element.nodeName === 'O:P' && element.textContent === NO_BREAK_SPACE; | ||
} | ||
const isEmpty = (element: Element): boolean => | ||
element.children.length === 1 && | ||
element.firstElementChild !== null && | ||
(isEmptyOp(element.firstElementChild) || isEmpty(element.firstElementChild)); | ||
function isEmpty(element: Element): boolean { | ||
return ( | ||
element.children.length === 1 && | ||
element.firstElementChild !== null && | ||
(isEmptyOp(element.firstElementChild) || isEmpty(element.firstElementChild)) | ||
); | ||
} | ||
const cleanEmptyParagraphs = (rootNode: Node): void => { | ||
traverseElements(rootNode, (element) => { | ||
export function cleanEmptyParagraphs(rootNode: Node): void { | ||
return traverseElements(rootNode, (element) => { | ||
if (element.tagName === 'P' && isEmpty(element)) { | ||
@@ -24,4 +28,2 @@ element.innerHTML = ''; | ||
}); | ||
}; | ||
export default cleanEmptyParagraphs; | ||
} |
@@ -1,5 +0,5 @@ | ||
import changeTagName from './changeTagName'; | ||
import traverseElements from './traverseElements'; | ||
import { changeTagName } from './changeTagName'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanFontElements = (rootNode: Node): void => { | ||
export function cleanFontElements(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -16,4 +16,2 @@ if (element.tagName === 'FONT') { | ||
}); | ||
}; | ||
export default cleanFontElements; | ||
} |
@@ -1,3 +0,3 @@ | ||
import isFootnote from './isFootnote'; | ||
import traverseElements from './traverseElements'; | ||
import { isFootnote } from './isFootnote'; | ||
import { traverseElements } from './traverseElements'; | ||
@@ -7,7 +7,7 @@ /** | ||
*/ | ||
const extractFootnoteNumber = (footnote: Element): string => { | ||
function extractFootnoteNumber(footnote: Element): string { | ||
return (footnote.textContent || '').trim().replace(/[[\]]/g, ''); | ||
}; | ||
} | ||
const cleanFootnotes = (rootNode: Node): void => { | ||
export function cleanFootnotes(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -27,4 +27,2 @@ if (isFootnote(element)) { | ||
}); | ||
}; | ||
export default cleanFootnotes; | ||
} |
import isURL from 'validator/lib/isURL'; | ||
import getRtfImagesMap from './getRtfImagesMap'; | ||
import getVShapeSpid from './getVShapeSpid'; | ||
import hexToBase64 from './hexToBase64'; | ||
import traverseElements from './traverseElements'; | ||
import { getRtfImagesMap } from './getRtfImagesMap'; | ||
import { getVShapeSpid } from './getVShapeSpid'; | ||
import { hexToBase64 } from './hexToBase64'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanImageElements = (document: Document, rtf: string, rootNode: Node): void => { | ||
export function cleanImageElements(document: Document, rtf: string, rootNode: Node): void { | ||
if (!rtf) { | ||
@@ -60,4 +60,2 @@ return; | ||
}); | ||
}; | ||
export default cleanImageElements; | ||
} |
@@ -1,6 +0,6 @@ | ||
import isFragmentHref from './isFragmentHref'; | ||
import traverseElements from './traverseElements'; | ||
import unwrapElement from './unwrapElement'; | ||
import { isFragmentHref } from './isFragmentHref'; | ||
import { traverseElements } from './traverseElements'; | ||
import { unwrapElement } from './unwrapElement'; | ||
const cleanLinkElements = (rootNode: Node): void => { | ||
export function cleanLinkElements(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -27,4 +27,2 @@ if (element.tagName !== 'A') { | ||
}); | ||
}; | ||
export default cleanLinkElements; | ||
} |
@@ -1,6 +0,6 @@ | ||
import buildList from './buildList'; | ||
import isList from './isList'; | ||
import traverseElements from './traverseElements'; | ||
import { buildList } from './buildList'; | ||
import { isList } from './isList'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanListElements = (rootNode: Node): void => { | ||
export function cleanListElements(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -48,4 +48,2 @@ const styleAttribute = element.getAttribute('style'); | ||
}); | ||
}; | ||
export default cleanListElements; | ||
} |
/* eslint-disable no-param-reassign */ | ||
import changeTagName from './changeTagName'; | ||
import traverseElements from './traverseElements'; | ||
import { changeTagName } from './changeTagName'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanQuotes = (rootNode: Node): void => { | ||
export function cleanQuotes(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -18,4 +18,2 @@ if ( | ||
}); | ||
}; | ||
export default cleanQuotes; | ||
} |
@@ -1,4 +0,4 @@ | ||
import generateSpaces from './generateSpaces'; | ||
import { generateSpaces } from './generateSpaces'; | ||
const cleanSpacerun = (element: Element): void => { | ||
export function cleanSpacerun(element: Element): void { | ||
const styleAttribute = element.getAttribute('style'); | ||
@@ -16,4 +16,2 @@ | ||
} | ||
}; | ||
export default cleanSpacerun; | ||
} |
@@ -1,6 +0,6 @@ | ||
import cleanSpacerun from './cleanSpacerun'; | ||
import cleanTabCount from './cleanTabCount'; | ||
import traverseElements from './traverseElements'; | ||
import { cleanSpacerun } from './cleanSpacerun'; | ||
import { cleanTabCount } from './cleanTabCount'; | ||
import { traverseElements } from './traverseElements'; | ||
const cleanSpans = (rootNode: Node): void => { | ||
export function cleanSpans(rootNode: Node): void { | ||
traverseElements(rootNode, (element) => { | ||
@@ -16,4 +16,2 @@ if (element.nodeName !== 'SPAN') { | ||
}); | ||
}; | ||
export default cleanSpans; | ||
} |
@@ -1,4 +0,4 @@ | ||
import generateSpaces from './generateSpaces'; | ||
import { generateSpaces } from './generateSpaces'; | ||
const cleanTabCount = (element: Element): void => { | ||
export function cleanTabCount(element: Element): void { | ||
const styleAttribute = element.getAttribute('style') || ''; | ||
@@ -17,4 +17,2 @@ | ||
} | ||
}; | ||
export default cleanTabCount; | ||
} |
@@ -5,5 +5,5 @@ /* eslint-disable no-param-reassign */ | ||
import traverseTexts from './traverseTexts'; | ||
import { traverseTexts } from './traverseTexts'; | ||
const cleanTextNodes = (rootNode: Node): void => { | ||
export function cleanTextNodes(rootNode: Node): void { | ||
traverseTexts(rootNode, (textNode) => { | ||
@@ -65,4 +65,2 @@ if ( | ||
}); | ||
}; | ||
export default cleanTextNodes; | ||
} |
import { SPACE } from '../constants'; | ||
const generateSpaces = (count: number): string => | ||
Array.from({ length: count }, () => SPACE).join(''); | ||
export default generateSpaces; | ||
export function generateSpaces(count: number): string { | ||
return Array.from({ length: count }, () => SPACE).join(''); | ||
} |
@@ -1,4 +0,6 @@ | ||
const acceptNode = () => NodeFilter.FILTER_ACCEPT; | ||
function acceptNode() { | ||
return NodeFilter.FILTER_ACCEPT; | ||
} | ||
const getComments = (node: Node): string[] => { | ||
export function getComments(node: Node): string[] { | ||
const comments: string[] = []; | ||
@@ -17,4 +19,2 @@ const iterator = document.createNodeIterator(node, NodeFilter.SHOW_COMMENT, { acceptNode }); | ||
return comments; | ||
}; | ||
export default getComments; | ||
} |
@@ -1,7 +0,7 @@ | ||
import removeNodesBetweenComments from './removeNodesBetweenComments'; | ||
import traverseElements from './traverseElements'; | ||
import { removeNodesBetweenComments } from './removeNodesBetweenComments'; | ||
import { traverseElements } from './traverseElements'; | ||
const HEADINGS_TAG_NAMES = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6']; | ||
const getListContentHtml = (rootElement: Element): string => { | ||
export function getListContentHtml(rootElement: Element): string { | ||
const clonedElement = rootElement.cloneNode(true) as Element; | ||
@@ -28,4 +28,2 @@ | ||
return clonedElement.innerHTML; | ||
}; | ||
export default getListContentHtml; | ||
} |
@@ -1,2 +0,2 @@ | ||
const getListLevel = (element: Element): number => { | ||
export function getListLevel(element: Element): number { | ||
const styleAttribute = element.getAttribute('style') || ''; | ||
@@ -11,4 +11,2 @@ const matches = styleAttribute.match(/level(\d+)/im); | ||
return 1; | ||
}; | ||
export default getListLevel; | ||
} |
@@ -1,7 +0,5 @@ | ||
const getListTypeNode = (element: Element): Node | null => { | ||
export function getListTypeNode(element: Element): Node | null { | ||
return ( | ||
element.querySelector('[style="mso-list:Ignore"]') || element.querySelector('span[lang]') | ||
); | ||
}; | ||
export default getListTypeNode; | ||
} |
import { SPACE } from '../constants'; | ||
const getRtfImageHex = (imageData: string): string | null => { | ||
export function getRtfImageHex(imageData: string): string | null { | ||
const [, bliptagData = ''] = imageData.split('bliptag'); | ||
@@ -24,4 +24,2 @@ const bracketSplit = bliptagData.split('}'); | ||
return spaceSplit.slice(1).join(''); | ||
}; | ||
export default getRtfImageHex; | ||
} |
@@ -1,2 +0,2 @@ | ||
const getRtfImageMimeType = (imageData: string): string | null => { | ||
export function getRtfImageMimeType(imageData: string): string | null { | ||
const [bliptagMeta] = imageData.split('bliptag'); | ||
@@ -13,4 +13,2 @@ | ||
return null; | ||
}; | ||
export default getRtfImageMimeType; | ||
} |
import { RtfImage } from '../types'; | ||
import getRtfImageHex from './getRtfImageHex'; | ||
import getRtfImageMimeType from './getRtfImageMimeType'; | ||
import getRtfImageSpid from './getRtfImageSpid'; | ||
import { getRtfImageHex } from './getRtfImageHex'; | ||
import { getRtfImageMimeType } from './getRtfImageMimeType'; | ||
import { getRtfImageSpid } from './getRtfImageSpid'; | ||
const getRtfImagesByType = (rtf: string, spidPrefix: string, type: string): RtfImage[] => { | ||
export function getRtfImagesByType(rtf: string, spidPrefix: string, type: string): RtfImage[] { | ||
const [, ...images] = rtf.split(type); | ||
@@ -22,4 +22,2 @@ | ||
}, []); | ||
}; | ||
export default getRtfImagesByType; | ||
} |
import { RtfImagesMap } from '../types'; | ||
import getRtfImagesByType from './getRtfImagesByType'; | ||
import { getRtfImagesByType } from './getRtfImagesByType'; | ||
const getRtfImagesMap = (rtf: string): RtfImagesMap => { | ||
export function getRtfImagesMap(rtf: string): RtfImagesMap { | ||
const rtfImagesMap: RtfImagesMap = {}; | ||
@@ -19,4 +19,2 @@ | ||
return rtfImagesMap; | ||
}; | ||
export default getRtfImagesMap; | ||
} |
@@ -5,3 +5,3 @@ import { CARRIAGE_RETURN, LINE_FEED, SPACE } from '../constants'; | ||
const getRtfImageSpid = (imageData: string, spidPrefix: string): string | null => { | ||
export function getRtfImageSpid(imageData: string, spidPrefix: string): string | null { | ||
const indexes = END_OF_ID_SEQUENCE_CHARACTERS.map((character) => imageData.indexOf(character)); | ||
@@ -12,4 +12,2 @@ const foundIndexes = indexes.filter((index) => index !== -1); | ||
return id ? `${spidPrefix}${id}` : null; | ||
}; | ||
export default getRtfImageSpid; | ||
} |
import { readTestFile } from '../test-utils'; | ||
import getVShapes from './getVShapes'; | ||
import { getVShapes } from './getVShapes'; | ||
@@ -5,0 +5,0 @@ const parser = new DOMParser(); |
@@ -1,6 +0,6 @@ | ||
import getComments from './getComments'; | ||
import { getComments } from './getComments'; | ||
const parser = new DOMParser(); | ||
const getVShapes = (document: Document): Record<string, string> => { | ||
export function getVShapes(document: Document): Record<string, string> { | ||
const comments = getComments(document); | ||
@@ -28,4 +28,2 @@ | ||
}, {}); | ||
}; | ||
export default getVShapes; | ||
} |
@@ -1,9 +0,9 @@ | ||
import getVShapes from './getVShapes'; | ||
import { getVShapes } from './getVShapes'; | ||
const normalizeSpid = (spid: string): string => { | ||
function normalizeSpid(spid: string): string { | ||
const [, , id] = spid.split('_'); | ||
return id; | ||
}; | ||
} | ||
const getVShapeSpid = (document: Document, element: Element): string | null => { | ||
export function getVShapeSpid(document: Document, element: Element): string | null { | ||
if (element.tagName === 'IMG') { | ||
@@ -45,4 +45,2 @@ const vShapeId = element.getAttribute('v:shapes'); | ||
return spid; | ||
}; | ||
export default getVShapeSpid; | ||
} |
@@ -1,7 +0,5 @@ | ||
const hexToBase64 = (hex: string): string => { | ||
export function hexToBase64(hex: string): string { | ||
const hexPairs = hex.match(/\w{2}/g) || []; | ||
const binary = hexPairs.map((hexPair) => String.fromCharCode(parseInt(hexPair, 16))); | ||
return btoa(binary.join('')); | ||
}; | ||
export default hexToBase64; | ||
} |
@@ -1,49 +0,49 @@ | ||
export { default as buildList } from './buildList'; | ||
export { default as changeTagName } from './changeTagName'; | ||
export { default as cleanBrElements } from './cleanBrElements'; | ||
export { default as cleanCrLf } from './cleanCrLf'; | ||
export { default as cleanEmptyElements } from './cleanEmptyElements'; | ||
export { default as cleanEmptyParagraphs } from './cleanEmptyParagraphs'; | ||
export { default as cleanFontElements } from './cleanFontElements'; | ||
export { default as cleanFootnotes } from './cleanFootnotes'; | ||
export { default as cleanImageElements } from './cleanImageElements'; | ||
export { default as cleanLinkElements } from './cleanLinkElements'; | ||
export { default as cleanListElements } from './cleanListElements'; | ||
export { default as cleanQuotes } from './cleanQuotes'; | ||
export { default as cleanSpacerun } from './cleanSpacerun'; | ||
export { default as cleanSpans } from './cleanSpans'; | ||
export { default as cleanTabCount } from './cleanTabCount'; | ||
export { default as cleanTextNodes } from './cleanTextNodes'; | ||
export { default as generateSpaces } from './generateSpaces'; | ||
export { default as getComments } from './getComments'; | ||
export { default as getListContentHtml } from './getListContentHtml'; | ||
export { default as getListLevel } from './getListLevel'; | ||
export { default as getListTypeNode } from './getListTypeNode'; | ||
export { default as getRtfImageHex } from './getRtfImageHex'; | ||
export { default as getRtfImageMimeType } from './getRtfImageMimeType'; | ||
export { default as getRtfImagesByType } from './getRtfImagesByType'; | ||
export { default as getRtfImagesMap } from './getRtfImagesMap'; | ||
export { default as getRtfImageSpid } from './getRtfImageSpid'; | ||
export { default as getVShapeSpid } from './getVShapeSpid'; | ||
export { default as getVShapes } from './getVShapes'; | ||
export { default as hexToBase64 } from './hexToBase64'; | ||
export { default as isBookmark } from './isBookmark'; | ||
export { default as isComment } from './isComment'; | ||
export { default as isDocxContent } from './isDocxContent'; | ||
export { default as isElement } from './isElement'; | ||
export { default as isFootnote } from './isFootnote'; | ||
export { default as isFragmentHref } from './isFragmentHref'; | ||
export { default as isList } from './isList'; | ||
export { default as isOrderedListSymbol } from './isOrderedListSymbol'; | ||
export { default as isOrderedList } from './isOrderedList'; | ||
export { default as isText } from './isText'; | ||
export { default as parseHtmlElement } from './parseHtmlElement'; | ||
export { default as postCleanHtml } from './postCleanHtml'; | ||
export { default as preCleanHtml } from './preCleanHtml'; | ||
export { default as removeHtmlSurroundings } from './removeHtmlSurroundings'; | ||
export { default as removeNodesBetweenComments } from './removeNodesBetweenComments'; | ||
export { default as traverseComments } from './traverseComments'; | ||
export { default as traverseElements } from './traverseElements'; | ||
export { default as traverseTexts } from './traverseTexts'; | ||
export { default as traverse } from './traverse'; | ||
export { default as unwrapElement } from './unwrapElement'; | ||
export { buildList } from './buildList'; | ||
export { changeTagName } from './changeTagName'; | ||
export { cleanBrElements } from './cleanBrElements'; | ||
export { cleanCrLf } from './cleanCrLf'; | ||
export { cleanEmptyElements } from './cleanEmptyElements'; | ||
export { cleanEmptyParagraphs } from './cleanEmptyParagraphs'; | ||
export { cleanFontElements } from './cleanFontElements'; | ||
export { cleanFootnotes } from './cleanFootnotes'; | ||
export { cleanImageElements } from './cleanImageElements'; | ||
export { cleanLinkElements } from './cleanLinkElements'; | ||
export { cleanListElements } from './cleanListElements'; | ||
export { cleanQuotes } from './cleanQuotes'; | ||
export { cleanSpacerun } from './cleanSpacerun'; | ||
export { cleanSpans } from './cleanSpans'; | ||
export { cleanTabCount } from './cleanTabCount'; | ||
export { cleanTextNodes } from './cleanTextNodes'; | ||
export { generateSpaces } from './generateSpaces'; | ||
export { getComments } from './getComments'; | ||
export { getListContentHtml } from './getListContentHtml'; | ||
export { getListLevel } from './getListLevel'; | ||
export { getListTypeNode } from './getListTypeNode'; | ||
export { getRtfImageHex } from './getRtfImageHex'; | ||
export { getRtfImageMimeType } from './getRtfImageMimeType'; | ||
export { getRtfImagesByType } from './getRtfImagesByType'; | ||
export { getRtfImagesMap } from './getRtfImagesMap'; | ||
export { getRtfImageSpid } from './getRtfImageSpid'; | ||
export { getVShapeSpid } from './getVShapeSpid'; | ||
export { getVShapes } from './getVShapes'; | ||
export { hexToBase64 } from './hexToBase64'; | ||
export { isBookmark } from './isBookmark'; | ||
export { isComment } from './isComment'; | ||
export { isDocxContent } from './isDocxContent'; | ||
export { isElement } from './isElement'; | ||
export { isFootnote } from './isFootnote'; | ||
export { isFragmentHref } from './isFragmentHref'; | ||
export { isList } from './isList'; | ||
export { isOrderedListSymbol } from './isOrderedListSymbol'; | ||
export { isOrderedList } from './isOrderedList'; | ||
export { isText } from './isText'; | ||
export { parseHtmlElement } from './parseHtmlElement'; | ||
export { postCleanHtml } from './postCleanHtml'; | ||
export { preCleanHtml } from './preCleanHtml'; | ||
export { removeHtmlSurroundings } from './removeHtmlSurroundings'; | ||
export { removeNodesBetweenComments } from './removeNodesBetweenComments'; | ||
export { traverseComments } from './traverseComments'; | ||
export { traverseElements } from './traverseElements'; | ||
export { traverseTexts } from './traverseTexts'; | ||
export { traverse } from './traverse'; | ||
export { unwrapElement } from './unwrapElement'; |
@@ -1,6 +0,4 @@ | ||
const isBookmark = (element: Element): boolean => { | ||
export function isBookmark(element: Element): boolean { | ||
const styleAttribute = element.getAttribute('style'); | ||
return (styleAttribute || '').startsWith('mso-bookmark') && !element.textContent; | ||
}; | ||
export default isBookmark; | ||
} |
@@ -1,3 +0,3 @@ | ||
const isComment = (node: Node): node is Comment => node.nodeType === Node.COMMENT_NODE; | ||
export default isComment; | ||
export function isComment(node: Node): node is Comment { | ||
return node.nodeType === Node.COMMENT_NODE; | ||
} |
@@ -1,4 +0,4 @@ | ||
import traverseElements from './traverseElements'; | ||
import { traverseElements } from './traverseElements'; | ||
const isDocxContent = (body: HTMLElement): boolean => { | ||
export function isDocxContent(body: HTMLElement): boolean { | ||
let result = false; | ||
@@ -20,4 +20,2 @@ | ||
return result; | ||
}; | ||
export default isDocxContent; | ||
} |
@@ -1,3 +0,3 @@ | ||
const isElement = (node: Node): node is Element => node.nodeType === Node.ELEMENT_NODE; | ||
export default isElement; | ||
export function isElement(node: Node): node is Element { | ||
return node.nodeType === Node.ELEMENT_NODE; | ||
} |
@@ -1,5 +0,3 @@ | ||
const isFootnote = (element: Element): boolean => { | ||
export function isFootnote(element: Element): boolean { | ||
return element.tagName === 'SPAN' && element.classList.contains('MsoFootnoteReference'); | ||
}; | ||
export default isFootnote; | ||
} |
@@ -1,3 +0,3 @@ | ||
const isFragmentHref = (href: string): boolean => href.startsWith('#'); | ||
export default isFragmentHref; | ||
export function isFragmentHref(href: string): boolean { | ||
return href.startsWith('#'); | ||
} |
@@ -1,2 +0,2 @@ | ||
const isList = (element: Element): boolean => { | ||
export function isList(element: Element): boolean { | ||
const styleAttribute = element.getAttribute('style'); | ||
@@ -21,4 +21,2 @@ | ||
return element.outerHTML.includes('<!--[if !supportLists]-->'); | ||
}; | ||
export default isList; | ||
} |
@@ -1,5 +0,5 @@ | ||
import getListTypeNode from './getListTypeNode'; | ||
import isOrderedListSymbol from './isOrderedListSymbol'; | ||
import { getListTypeNode } from './getListTypeNode'; | ||
import { isOrderedListSymbol } from './isOrderedListSymbol'; | ||
const isOrderedList = (element: Element): boolean => { | ||
export function isOrderedList(element: Element): boolean { | ||
const listTypeNode = getListTypeNode(element); | ||
@@ -12,4 +12,2 @@ | ||
return isOrderedListSymbol(listTypeNode.textContent || ''); | ||
}; | ||
export default isOrderedList; | ||
} |
import { NO_BREAK_SPACE, SPACE } from '../constants'; | ||
import isOrderedListSymbol from './isOrderedListSymbol'; | ||
import { isOrderedListSymbol } from './isOrderedListSymbol'; | ||
@@ -5,0 +5,0 @@ describe('isOrderedListSymbol', () => { |
@@ -1,5 +0,3 @@ | ||
const isOrderedListSymbol = (symbol: string): boolean => { | ||
export function isOrderedListSymbol(symbol: string): boolean { | ||
return /[0-9a-np-z]\S/g.test(symbol.toLowerCase()); | ||
}; | ||
export default isOrderedListSymbol; | ||
} |
@@ -1,3 +0,3 @@ | ||
const isText = (node: Node): node is Text => node.nodeType === Node.TEXT_NODE; | ||
export default isText; | ||
export function isText(node: Node): node is Text { | ||
return node.nodeType === Node.TEXT_NODE; | ||
} |
@@ -1,7 +0,5 @@ | ||
const parseHtmlElement = (html: string): Element | null => { | ||
export function parseHtmlElement(html: string): Element | null { | ||
const div = document.createElement('div'); | ||
div.innerHTML = html; | ||
return div.firstElementChild; | ||
}; | ||
export default parseHtmlElement; | ||
} |
import { ZERO_WIDTH_SPACE } from '../constants'; | ||
const postCleanHtml = (html: string): string => { | ||
export function postCleanHtml(html: string): string { | ||
const cleanHtml = html.trim().replace(new RegExp(ZERO_WIDTH_SPACE, 'g'), ''); | ||
return `<body>${cleanHtml}</body>`; | ||
}; | ||
export default postCleanHtml; | ||
} |
@@ -1,10 +0,8 @@ | ||
import cleanCrLf from './cleanCrLf'; | ||
import removeHtmlSurroundings from './removeHtmlSurroundings'; | ||
import { cleanCrLf } from './cleanCrLf'; | ||
import { removeHtmlSurroundings } from './removeHtmlSurroundings'; | ||
const cleaners = [removeHtmlSurroundings, cleanCrLf]; | ||
const preCleanHtml = (html: string): string => { | ||
export function preCleanHtml(html: string): string { | ||
return cleaners.reduce((result, clean) => clean(result), html); | ||
}; | ||
export default preCleanHtml; | ||
} |
@@ -1,2 +0,2 @@ | ||
import removeHtmlSurroundings from './removeHtmlSurroundings'; | ||
import { removeHtmlSurroundings } from './removeHtmlSurroundings'; | ||
@@ -3,0 +3,0 @@ describe('removeHtmlSurroundings', () => { |
@@ -1,2 +0,2 @@ | ||
const removeBeforeHtml = (html: string): string => { | ||
function removeBeforeHtml(html: string): string { | ||
const index = html.indexOf('<html'); | ||
@@ -7,5 +7,5 @@ if (index === -1) { | ||
return html.substring(index); | ||
}; | ||
} | ||
const removeAfterHtml = (html: string): string => { | ||
function removeAfterHtml(html: string): string { | ||
const index = html.lastIndexOf('</html>'); | ||
@@ -16,8 +16,6 @@ if (index === -1) { | ||
return html.substring(0, index + '</html>'.length); | ||
}; | ||
} | ||
const removeHtmlSurroundings = (html: string): string => { | ||
export function removeHtmlSurroundings(html: string): string { | ||
return removeBeforeHtml(removeAfterHtml(html)); | ||
}; | ||
export default removeHtmlSurroundings; | ||
} |
@@ -1,6 +0,8 @@ | ||
import isComment from './isComment'; | ||
import traverseComments from './traverseComments'; | ||
import { isComment } from './isComment'; | ||
import { traverseComments } from './traverseComments'; | ||
const removeNodesBetweenComments = (rootNode: Node, start: string, end: string): void => { | ||
const isClosingComment = (node: Node) => isComment(node) && node.data === end; | ||
export function removeNodesBetweenComments(rootNode: Node, start: string, end: string): void { | ||
function isClosingComment(node: Node): boolean { | ||
return isComment(node) && node.data === end; | ||
} | ||
@@ -26,4 +28,2 @@ traverseComments(rootNode, (comment) => { | ||
}); | ||
}; | ||
export default removeNodesBetweenComments; | ||
} |
@@ -9,3 +9,3 @@ type Callback = (node: Node) => boolean; | ||
*/ | ||
const traverse = (node: Node, callback: Callback): void => { | ||
export function traverse(node: Node, callback: Callback): void { | ||
const keepTraversing = callback(node); | ||
@@ -61,4 +61,2 @@ | ||
} | ||
}; | ||
export default traverse; | ||
} |
@@ -1,7 +0,7 @@ | ||
import isComment from './isComment'; | ||
import traverse from './traverse'; | ||
import { isComment } from './isComment'; | ||
import { traverse } from './traverse'; | ||
type Callback = (node: Comment) => boolean; | ||
const traverseComments = (rootNode: Node, callback: Callback): void => { | ||
export function traverseComments(rootNode: Node, callback: Callback): void { | ||
traverse(rootNode, (node) => { | ||
@@ -14,4 +14,2 @@ if (!isComment(node)) { | ||
}); | ||
}; | ||
export default traverseComments; | ||
} |
@@ -1,7 +0,7 @@ | ||
import isElement from './isElement'; | ||
import traverse from './traverse'; | ||
import { isElement } from './isElement'; | ||
import { traverse } from './traverse'; | ||
type Callback = (node: Element) => boolean; | ||
const traverseElements = (rootNode: Node, callback: Callback): void => { | ||
export function traverseElements(rootNode: Node, callback: Callback): void { | ||
traverse(rootNode, (node) => { | ||
@@ -14,4 +14,2 @@ if (!isElement(node)) { | ||
}); | ||
}; | ||
export default traverseElements; | ||
} |
@@ -1,7 +0,7 @@ | ||
import isText from './isText'; | ||
import traverse from './traverse'; | ||
import { isText } from './isText'; | ||
import { traverse } from './traverse'; | ||
type Callback = (node: Text) => boolean; | ||
const traverseTexts = (rootNode: Node, callback: Callback): void => { | ||
export function traverseTexts(rootNode: Node, callback: Callback): void { | ||
traverse(rootNode, (node) => { | ||
@@ -14,4 +14,2 @@ if (!isText(node)) { | ||
}); | ||
}; | ||
export default traverseTexts; | ||
} |
@@ -1,6 +0,4 @@ | ||
const unwrapElement = (element: Element): void => { | ||
export function unwrapElement(element: Element): void { | ||
// eslint-disable-next-line no-param-reassign | ||
element.outerHTML = element.innerHTML; | ||
}; | ||
export default unwrapElement; | ||
} |
import fs from 'fs'; | ||
import path from 'path'; | ||
export const readTestFile = (filepath: string): string => { | ||
export function readTestFile(filepath: string): string { | ||
const absoluteFilepath = path.resolve(__dirname, '__tests__', filepath); | ||
return fs.readFileSync(absoluteFilepath, 'utf-8'); | ||
}; | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
161454
3707
Yes
21
2
1