diff --git a/karma.conf.js b/karma.conf.js index 3ff26d5..f70d0fc 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,16 +1,17 @@ -// const path = require('path') - module.exports = function (config) { config.set({ - frameworks: ['jasmine'], + + frameworks: ['jasmine', 'karma-typescript'], + files: [ - 'test/**/*.spec.js' + { pattern: 'test/**/*.ts' }, + { pattern: 'src/**/*.ts' } ], - exclude: [], + preprocessors: { - 'test/**/*.js': ['webpack', 'sourcemap', 'coverage'] + '**/*.ts': ['karma-typescript', 'sourcemap', 'coverage'] }, - reporters: ['progress', 'coverage'], + reporters: ['dots', 'coverage', 'karma-typescript'], coverageReporter: { dir: 'coverage/', type: 'lcov', diff --git a/package.json b/package.json index 225fb7d..fedd147 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,11 @@ "repository": "https://github.com/crabbly/Print.js", "license": "MIT", "devDependencies": { + "@types/jasmine": "^3.4.0", + "karma": "^6.1.0", + "karma-cli": "^2.0.0", + "karma-typescript": "^5.5.3", + "typescript": "^5.0.2", "@babel/core": "7.11.6", "@babel/preset-env": "7.11.5", "babel-loader": "8.1.0", @@ -15,7 +20,6 @@ "css-loader": "4.2.2", "istanbul-instrumenter-loader": "3.0.1", "jasmine-core": "3.6.0", - "karma": "5.2.1", "karma-chrome-launcher": "3.1.0", "karma-coverage": "2.0.3", "karma-jasmine": "4.0.1", @@ -28,8 +32,10 @@ "sass-loader": "10.0.2", "standard": "14.3.4", "terser-webpack-plugin": "4.1.0", + "ts-loader": "^9.4.2", "webpack": "4.44.1", "webpack-cli": "3.3.12", + "source-map-loader": "^4.0.1", "webpack-dev-server": "3.11.0" }, "scripts": { diff --git a/src/index.js b/src/index.ts similarity index 100% rename from src/index.js rename to src/index.ts diff --git a/src/js/browser.js b/src/js/browser.ts similarity index 95% rename from src/js/browser.js rename to src/js/browser.ts index f600929..8aef10c 100644 --- a/src/js/browser.js +++ b/src/js/browser.ts @@ -3,7 +3,7 @@ const Browser = { isFirefox: () => { return typeof InstallTrigger !== 'undefined' }, - getFirefoxMajorVersion: (userAgent) => { + getFirefoxMajorVersion: (userAgent = null) => { userAgent = userAgent || navigator.userAgent const firefoxVersionRegex = /firefox\/(\S+)/ const match = userAgent.toLowerCase().match(firefoxVersionRegex) diff --git a/src/js/functions.js b/src/js/functions.ts similarity index 95% rename from src/js/functions.js rename to src/js/functions.ts index e8548f4..ed70c3f 100644 --- a/src/js/functions.js +++ b/src/js/functions.ts @@ -64,17 +64,17 @@ export function addHeader (printElement, params) { export function addFooter (printElement, params) { // Create the footer container div - let footerContainer = document.createElement('div') + const footerContainer = document.createElement('div') // Check if the footer is text or raw html if (isRawHTML(params.footer)) { footerContainer.innerHTML = params.footer } else { // Create footer element - let footerElement = document.createElement('h1') + const footerElement = document.createElement('h1') // Create footer text node - let footerNode = document.createTextNode(params.footer) + const footerNode = document.createTextNode(params.footer) // Build and style footerElement.appendChild(footerNode) diff --git a/src/js/html.js b/src/js/html.ts similarity index 100% rename from src/js/html.js rename to src/js/html.ts diff --git a/src/js/image.js b/src/js/image.ts similarity index 100% rename from src/js/image.js rename to src/js/image.ts diff --git a/src/js/init.js b/src/js/init.ts similarity index 92% rename from src/js/init.js rename to src/js/init.ts index 8d2515e..5eedb75 100644 --- a/src/js/init.js +++ b/src/js/init.ts @@ -84,7 +84,7 @@ export default { if (!params.printable) throw new Error('Missing printable information.') // Validate type - if (!params.type || typeof params.type !== 'string' || printTypes.indexOf(params.type.toLowerCase()) === -1) { + if (!params.type || (typeof params.type !== 'string') || printTypes.indexOf(params.type.toLowerCase()) === -1) { throw new Error('Invalid print type. Available types are: pdf, html, image and json.') } @@ -97,7 +97,9 @@ export default { // To prevent duplication and issues, remove any used printFrame from the DOM const usedFrame = document.getElementById(params.frameId) - if (usedFrame) usedFrame.parentNode.removeChild(usedFrame) + if (usedFrame) { + usedFrame.parentNode.removeChild(usedFrame) + } // Create a new iframe for the print job const printFrame = document.createElement('iframe') @@ -122,7 +124,9 @@ export default { // Attach css files if (params.css) { // Add support for single file - if (!Array.isArray(params.css)) params.css = [params.css] + if (!Array.isArray(params.css)) { + params.css = [params.css] + } // Create link tags for each css file params.css.forEach(file => { @@ -147,8 +151,12 @@ export default { params.onError(error) } finally { // Make sure there is no loading modal opened - if (params.showModal) Modal.close() - if (params.onLoadingEnd) params.onLoadingEnd() + if (params.showModal) { + Modal.close() + } + if (params.onLoadingEnd) { + params.onLoadingEnd() + } } } else { Pdf.print(params, printFrame) diff --git a/src/js/json.js b/src/js/json.ts similarity index 100% rename from src/js/json.js rename to src/js/json.ts diff --git a/src/js/modal.js b/src/js/modal.ts similarity index 100% rename from src/js/modal.js rename to src/js/modal.ts diff --git a/src/js/pdf.js b/src/js/pdf.ts similarity index 80% rename from src/js/pdf.js rename to src/js/pdf.ts index 9dc420b..24e5b9f 100644 --- a/src/js/pdf.js +++ b/src/js/pdf.ts @@ -5,10 +5,10 @@ export default { print: (params, printFrame) => { // Check if we have base64 data if (params.base64) { - if (params.printable.indexOf(',') !== -1) { - //If pdf base64 start with `data:application/pdf;base64,`,Excute the atob function will throw an error.So we get the content after `,` - params.printable = params.printable.split(',')[1]; - } + if (params.printable.indexOf(',') !== -1) { + // If pdf base64 start with `data:application/pdf;base64,`,Excute the atob function will throw an error.So we get the content after `,` + params.printable = params.printable.split(',')[1] + } const bytesArray = Uint8Array.from(atob(params.printable), c => c.charCodeAt(0)) createBlobAndPrint(params, printFrame, bytesArray) return @@ -51,8 +51,7 @@ export default { function createBlobAndPrint (params, printFrame, data) { // Pass response or base64 data to a blob and create a local object url - let localPdf = new window.Blob([data], { type: 'application/pdf' }) - localPdf = window.URL.createObjectURL(localPdf) + let localPdf = window.URL.createObjectURL(new window.Blob([data], { type: 'application/pdf' })) // Set iframe src with pdf document url printFrame.setAttribute('src', localPdf) diff --git a/src/js/print.js b/src/js/print.ts similarity index 93% rename from src/js/print.js rename to src/js/print.ts index 40f9629..df27e0d 100644 --- a/src/js/print.js +++ b/src/js/print.ts @@ -59,15 +59,15 @@ function performPrint (iframeElement, params) { try { iframeElement.contentWindow.document.execCommand('print', false, null) } catch (e) { - setTimeout(function(){ + setTimeout(function () { iframeElement.contentWindow.print() - },1000) + }, 1000) } } else { // Other browsers - setTimeout(function(){ + setTimeout(function () { iframeElement.contentWindow.print() - },1000) + }, 1000) } } catch (error) { params.onError(error) @@ -82,7 +82,7 @@ function performPrint (iframeElement, params) { } } -function loadIframeImages (images) { +function loadIframeImages (images){ const promises = images.map(image => { if (image.src && image.src !== window.location.href) { return loadIframeImage(image) @@ -93,11 +93,11 @@ function loadIframeImages (images) { } function loadIframeImage (image) { - return new Promise(resolve => { + return new Promise (resolve => { const pollImage = () => { !image || typeof image.naturalWidth === 'undefined' || image.naturalWidth === 0 || !image.complete ? setTimeout(pollImage, 500) - : resolve() + : resolve(true) } pollImage() }) diff --git a/src/js/raw-html.js b/src/js/raw-html.ts similarity index 100% rename from src/js/raw-html.js rename to src/js/raw-html.ts diff --git a/src/js/types/browser.d.ts b/src/js/types/browser.d.ts new file mode 100644 index 0000000..dd32988 --- /dev/null +++ b/src/js/types/browser.d.ts @@ -0,0 +1 @@ +declare const InstallTrigger: any; \ No newline at end of file diff --git a/src/index.d.ts b/src/js/types/index.d.ts similarity index 84% rename from src/index.d.ts rename to src/js/types/index.d.ts index 5c5d325..fcc27ff 100644 --- a/src/index.d.ts +++ b/src/js/types/index.d.ts @@ -1,6 +1,24 @@ +export {} + declare function printJS(configuration: printJS.Configuration): void; declare function printJS(source: string, type?: printJS.PrintTypes): void; +declare global { + interface Window { + printJS: Function; + StyleMedia: any; + chrome: any; + } + + interface Document { + documentMode: any; + } + + interface HTMLElement { + contentWindow: any; + contentDocument: any; + } +} declare namespace printJS { type PrintTypes = 'pdf' | 'html' | 'image' | 'json' | 'raw-html'; @@ -43,6 +61,4 @@ declare namespace printJS { honorColor?: boolean; imageStyle?: string; } -} - -export = printJS; +} \ No newline at end of file diff --git a/test/unit/browser.spec.js b/test/unit/browser.spec.ts similarity index 93% rename from test/unit/browser.spec.js rename to test/unit/browser.spec.ts index 342a576..bacbeb6 100644 --- a/test/unit/browser.spec.js +++ b/test/unit/browser.spec.ts @@ -35,12 +35,12 @@ describe('Browser', () => { describe('isChrome()', () => { it('returns true for Google Chrome', () => { - const stubbedWindow = { chrome: {} } + const stubbedWindow = { chrome: {} } expect(Browser.isChrome(stubbedWindow)).toBeTruthy() }) it('returns false for non Google Chrome', () => { - const stubbedWindow = {} + const stubbedWindow = {} expect(Browser.isChrome(stubbedWindow)).toBeFalsy() }) }) diff --git a/test/unit/functions.spec.js b/test/unit/functions.spec.ts similarity index 100% rename from test/unit/functions.spec.js rename to test/unit/functions.spec.ts diff --git a/test/unit/html.spec.js b/test/unit/html.spec.ts similarity index 100% rename from test/unit/html.spec.js rename to test/unit/html.spec.ts diff --git a/test/unit/image.spec.js b/test/unit/image.spec.ts similarity index 100% rename from test/unit/image.spec.js rename to test/unit/image.spec.ts diff --git a/test/unit/init.spec.js b/test/unit/init.spec.ts similarity index 100% rename from test/unit/init.spec.js rename to test/unit/init.spec.ts diff --git a/test/unit/json.spec.js b/test/unit/json.spec.ts similarity index 100% rename from test/unit/json.spec.js rename to test/unit/json.spec.ts diff --git a/test/unit/modal.spec.js b/test/unit/modal.spec.ts similarity index 100% rename from test/unit/modal.spec.js rename to test/unit/modal.spec.ts diff --git a/test/unit/pdf.spec.js b/test/unit/pdf.spec.ts similarity index 100% rename from test/unit/pdf.spec.js rename to test/unit/pdf.spec.ts diff --git a/test/unit/print.spec.js b/test/unit/print.spec.ts similarity index 100% rename from test/unit/print.spec.js rename to test/unit/print.spec.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5602ac8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "module": "esnext", + "strict": true, + "noImplicitAny": false, + "outDir": "tmp", + "moduleResolution": "node", + "esModuleInterop": true, + "experimentalDecorators": true, + "target": "es5", + "sourceMap": true, + "baseUrl": ".", + "allowSyntheticDefaultImports": true, + "types" : [ + "jasmine", + "node" + ], + "typeRoots": ["./node_modules/@types", "./src/js/types"], + "paths": { + "@/*": [ + "src/*" + ] + }, + "lib": [ + "esnext", + "dom", + "dom.iterable", + "scripthost" + ] + + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/webpack.config.js b/webpack.config.js index a719b37..41eae9a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,8 +7,11 @@ module.exports = { mode: 'development', devtool: 'source-map', entry: [ - './src/index.js' + './src/index.ts' ], + resolve: { + extensions: ['.ts', '.js', '.json'] + }, output: { library: 'printJS', libraryTarget: 'umd', @@ -23,7 +26,7 @@ module.exports = { test: /\.js$/, exclude: /node_modules/, use: { - loader: 'babel-loader' + loader: 'ts-loader' } }, // TODO: Configure istanbul to interpret how webpack bundles files