diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index 2159364..0000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -engines: - duplication: - enabled: true - config: - languages: - - ruby - - javascript - - python - - php - eslint: - enabled: true - fixme: - enabled: true -ratings: - paths: - - "**.inc" - - "**.js" - - "**.jsx" - - "**.module" - - "**.php" - - "**.py" - - "**.rb" -exclude_paths: -- "tests/" -- "spec/" -- "**/vendor/" diff --git a/.github/workflows/npm_deploy.yml b/.github/workflows/npm_deploy.yml new file mode 100644 index 0000000..9a2d058 --- /dev/null +++ b/.github/workflows/npm_deploy.yml @@ -0,0 +1,26 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: NPM PUBLISH + +on: + release: + types: [published] + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: "16.x" + registry-url: https://npm.pkg.github.com + scope: "@scriptaddicts" + - run: npm ci + - run: npm run build + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/README.md b/README.md index 0fde246..da43238 100644 --- a/README.md +++ b/README.md @@ -58,28 +58,11 @@ In the current stage, there are not methods for directly parsing Microsoft Docs There are no methods yet. -# Library's project key - -``` -108j6x_ZX544wEhGkgddFYM6Ie09edDqXaFwnW3RVFQCLHw_mEueqUHTW -``` - # How to install ## Install this library -- Open Script Editor. Click as follows: -- -> Resource -- -> Library -- -> Input the Script ID in the text box. The Script ID is **`108j6x_ZX544wEhGkgddFYM6Ie09edDqXaFwnW3RVFQCLHw_mEueqUHTW`**. -- -> Add library -- -> Please select the latest version -- -> Developer mode ON (Or select others if you don't want to use the latest version) -- -> The identifier is "**`DocsServiceApp`**". This is set under the default. - -[You can read more about libraries in Apps Script here](https://developers.google.com/apps-script/guide_libraries). - -Please use this library with enabling V8 runtime. +TODO: STEPS TO INSTALL THE LIBRARY FROM NPM ## About Google APIs @@ -113,539 +96,12 @@ This library uses the following Google Apps Script library. # Methods -In the current stage, there are the following methods in this library. - - - -## For Google Document - -### 1. `getTableColumnWidth()` - -Retrieve the column width of the table in the Google Document. For example, when a new table, which has 1 row and 2 columns, is manually inserted to the Document body as the default format, the table width and column width retrieved by `getColumnWidth()` return `null`. By this, in the current stage, the table width and column width cannot be retrieved. This method achieves this. - -#### Sample script - -```javascript -const documentId = "###"; // Google Document ID -const res = DocsServiceApp.openByDocumentId(documentId).getTableColumnWidth(); -console.log(res); -``` - -#### Result - -```json -[ - { - "tableIndex": 0, // 0 means the 1st table in Google Document. - "unit": "pt", - "tableWidth": 451.3, // Table width - "tebleColumnWidth": [225.65, 225.65] // Column width of each column. Array index is the column index. - }, - , - , - , -] -``` - -- For example, when the table which has the columns "A" and "B" of 100 pt and 200 pt are checked by above script, the same values of 100 and 200 for the columns "A" and "B" could be confirmed. So from this result, it is found that the column width of DOCX data and Google Document is the same. - - - -## For Google Spreadsheet - -### 1. `getImages()` - -Retrieve images in and over the cell from Google Spreadsheet as blob. In the current stage, there are no methods for retrieving the images over the cells and inner the cells in the existing Google Spreadsheet service and Sheets API. This method achieves this. - -#### Sample script - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId) - .getSheetByName("Sheet1") - .getImages(); -console.log(res); -``` - -In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. - -And - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getImages(); -console.log(res); -``` - -In this script, the images are retrieved from all sheets of `spreadsheetId`. - -When you want to save all images in the Spreadsheet as the files, you can use the following script. - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getImages(); -const folder = DriveApp.getFolderById("### folderId ###"); -res.forEach(({ images }) => - images.forEach((e) => { - if (e.image) folder.createFile(e.image.blob); - }) -); -``` - -#### Result - -```json -[ - { - "range": { "col": 3, "row": 8, "a1Notation": "C8" }, - "image": { - "description": "sample description", - "title": "sample title", - "blob": BLOB, - "innerCell": false // "false" means that the image is over a cell. - } - }, - { - "range": { "col": 2, "row": 2, "a1Notation": "B2" }, - "image": { - "description": "sample description", - "title": "sample title", - "blob": BLOB, - "innerCell": true // "true" means that the image is in a cell. - } - }, - , - , - , -] -``` - -- You can create the image file from `BLOB`. - -- When `getSheetByName()` is not used, above array is put in each sheet as follows. - - ```json - [ - { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, - { "sheetName": "Sheet2", "images": [] }, - { "sheetName": "Sheet3", "images": [[Object], [Object]] } - ] - ``` - -#### Limitation - -- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. -- In the current stage, the drawings cannot be retrieved yet. I apologize for this. - -### 2. `getComments()` - -Retrieve comments in Google Spreadsheet. In the current stage, there are no methods for retrieving the comments with the cell coordinate in the existing Google Spreadsheet service and Sheets API. This method achieves this. - -#### Sample script - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId) - .getSheetByName("Sheet1") - .getComments(); -console.log(res); -``` - -In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. - -And - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getComments(); -console.log(res); -``` - -In this script, the images are retrieved from all sheets of `spreadsheetId`. - -#### Result - -```json -[ - { - "range": { - "col": 2, - "row": 11, - "a1Notation": "B11" - }, - "comment": [ - { - "user": "user name", - "comment": "comment" - }, - , - , - , - ] - }, - , - , - , -] -``` - -- When `getSheetByName()` is not used, above array is put in each sheet as follows. - - ```json - [ - { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, - { "sheetName": "Sheet2", "images": [] }, - { "sheetName": "Sheet3", "images": [[Object], [Object]] } - ] - ``` - -### 3. `insertImage()` - -Insert images in and over the cell from Google Spreadsheet from the image blob. In the current stage, there are no methods for directly inserting an image in a cell in the existing Google Spreadsheet service and Sheets API. For example, when the user wants to insert an image on own Google Drive in a cell, the image is required to be publicly shared for using `=IMAGE(URL)`. In this method, the image can be put without publicly sharing the image and using `=IMAGE(URL)`. - -#### Sample script - -```javascript -const spreadsheetId = "###"; // Google Spreadsheet ID -const blob1 = DriveApp.getFileById("###fileId###").getBlob(); -const blob2 = UrlFetchApp.fetch("###URL###").getBlob(); -const object = [ - { blob: blob1, range: { row: 1, column: 1 } }, // Image is inserted in a cell "A1". - { blob: blob2, range: { row: 5, column: 2 } }, // Image is inserted in a cell "B5". -]; -DocsServiceApp.openBySpreadsheetId(spreadsheetId) - .getSheetByName("Sheet1") - .insertImage(object); -``` - -- **In this method, no values are returned.** -- In above sample script, 2 images are inserted into the cells "A1" and "B5" in "Sheet1", respectively. - -#### Result - -![](images/fig1.png) - -- The sample image of cell "A1" is from [https://www.deviantart.com/k3-studio/art/Rainbow-painting-281090729](https://www.deviantart.com/k3-studio/art/Rainbow-painting-281090729) -- The sample image of cell "B5" is from [https://www.deviantart.com/k3-studio/art/Chromatic-lituus-415318548](https://www.deviantart.com/k3-studio/art/Chromatic-lituus-415318548) - -#### Limitation - -- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. -- In the current stage, the drawings cannot be retrieved yet. I apologize for this. - -### 4. `createNewSpreadsheetWithCustomHeaderFooter()` - -Create new Google Spreadsheet by setting the header and footer. In the current stage, there are no methods for setting the header and footer for Google Spreadsheet in the existing Google Spreadsheet service and Sheets API. This method achieves this. - -#### Sample script - -```javascript -const object = { - title: "sample title", // Title of created Spreadsheet. - parent: "###", // folder ID - header: { l: "left header", c: "center header", r: "right header" }, - footer: { l: "left footer", c: "center footer", r: "right footer" }, -}; -const res = DocsServiceApp.createNewSpreadsheetWithCustomHeaderFooter(object); -console.log(res); -``` - -- In this method, the spreadsheet ID of created Spreadsheet is returned. - -#### Result - -![](images/fig2.png) - - - -## For Google Slides - -### 1. `createNewSlidesWithPageSize()` - -Create new Google Slides by setting the page size. In the current stage, there are no methods for setting the page size for Google Slides in the existing Google Slides service and Slides API, although Slides API has the method of "presentations.create". This method achieves this. - -#### Sample script - -```javascript -const object = { - title: "sample title", // Title of created Slides. - parent: "###", // folder ID - width: { unit: "pixel", size: 200 }, - height: { unit: "pixel", size: 300 }, -}; -const res = DocsServiceApp.createNewSlidesWithPageSize(object); -console.log(res); -``` - -- In this method, the presentation ID of created Slides is returned. -- "pixel" and "point" can be used for `unit` in above object. - -#### Sample situations - -When this method is used, the following application can be created. - -1. [Inserting Text on Image using Google Apps Script](https://gist.github.com/tanaikech/835642df109731a559e52d831bd3342d) : This is a sample script for inserting a text on an image using Google Apps Script. - - - -## For Microsoft Word - -### 1. `getTableColumnWidth()` - -Retrieve the column width of the table in the Microsoft Word. In this case, the column width of the table are directly retrieved from Microsoft Word. - -#### Sample script - -```javascript -const blob = "BLOB"; // Blob of Microsoft Word file. -const res = DocsServiceApp.openByWordFileBlob(blob).getTableColumnWidth(); -console.log(res); -``` - -#### Result - -```json -[ - { - "tableIndex": 0, // 0 means the 1st table in Google Document. - "unit": "pt", - "tableWidth": 451.3, // Table width - "tebleColumnWidth": [225.65, 225.65] // Column width of each column. Array index is the column index. - }, - , - , - , -] -``` - - - -## For Microsoft Excel - -![](images/fig3.png) - -> IMPORTANT: About `getValues()` and `getFormulas()` methods, in the current stage, the process costs of them is much higher than those of Google Spreadsheet service. So when you want to retrieve the values and formulas from XLSX data, I would like to recommend to use Google Spreadsheet service by converting XSLX data to Google Spreadsheet. - -### 1. `getImages()` - -Retrieve images in and over the cell from Microsoft Excel as blob. In this case, the images are directly retrieved from Microsoft Excel. - -#### Sample script - -```javascript -const blob = "BLOB"; // Blob of Microsoft Excel file. -const res = DocsServiceApp.openByExcelFileBlob(blob) - .getSheetByName("Sheet1") - .getImages(); -console.log(res); -``` - -In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. - -And - -```javascript -const blob = "BLOB"; // Blob of Microsoft Excel file. -const res = DocsServiceApp.openByExcelFileBlob(blob).getImages(); -console.log(res); -``` - -In this script, the images are retrieved from all sheets of `spreadsheetId`. - -- **`blob`** : Blob of XLSX file. -- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. - -#### Result - -```json -[ - { - "range": { "col": 3, "row": 8, "a1Notation": "C8" }, - "image": { - "description": "sample description", - "title": "sample title", - "blob": BLOB, - "innerCell": false // "false" means that the image is over a cell. - } - }, - { - "range": { "col": 2, "row": 2, "a1Notation": "B2" }, - "image": { - "description": "sample description", - "title": "sample title", - "blob": BLOB, - "innerCell": true // "true" means that the image is in a cell. - } - }, - , - , - , -] -``` - -- When `getSheetByName()` is not used, above array is put in each sheet as follows. - - ```json - [ - { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, - { "sheetName": "Sheet2", "images": [] }, - { "sheetName": "Sheet3", "images": [[Object], [Object]] } - ] - ``` - -#### Limitation - -- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. -- In the current stage, the drawings cannot be retrieved yet. I apologize for this. - -### 2. `getComments()` - -Retrieve comments in Microsoft Excel. In this case, the comments are directly retrieved from Microsoft Excel. - -#### Sample script - -```javascript -const blob = "BLOB"; // Blob of Microsoft Excel file. -const res = DocsServiceApp.openByExcelFileBlob(blob) - .getSheetByName("Sheet1") - .getComments(); -console.log(res); -``` - -In this script, the comments are retrieved from "Sheet1" of Blob of Microsoft Excel file. - -- **`blob`** : Blob of XLSX file. -- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. - -#### Result - -```json -[ - { - "range": { - "col": 2, - "row": 11, - "a1Notation": "B11" - }, - "comment": [ - { - "user": "user name", - "comment": "comment" - }, - , - , - , - ] - }, - , - , - , -] -``` - -### 3. `getAll()` - -This method is used for retrieving all values (in the current stage, those are values, formulas, images and comments.) from all sheets of XLSX data. The returned value is JSON object. - -#### Sample script - -```javascript -function myFunction() { - const fileId = "###"; // Please set the file ID of XLSX file. - const blob = DriveApp.getFileById(fileId).getBlob(); - - const res = DocsServiceApp.openByExcelFileBlob(blob).getAll(); - console.log(res); -} -``` - -- **`blob`** : Blob of XLSX file. -- The values are returned as JSON object. The returned values include the values, formulas, images and comments of all sheets in the XLSX data. - -### 4. `getSheets()` - -This method is used for retrieving the sheet list from XLSX data. - -#### Sample script - -```javascript -function myFunction() { - const fileId = "###"; // Please set the file ID of XLSX file. - const blob = DriveApp.getFileById(fileId).getBlob(); - - const res = DocsServiceApp.openByExcelFileBlob(blob).getSheets(); - console.log(res); -} -``` - -- **`blob`** : Blob of XLSX file. - -### 5. `getValues()` - -This method is used for updating the values from a sheet of XLSX data. - -#### Sample script - -```javascript -function myFunction() { - const fileId = "###"; // Please set the file ID of XLSX file. - const sheetName = "###"; // Please set the sheet name. - const blob = DriveApp.getFileById(fileId).getBlob(); - - const res = DocsServiceApp.openByExcelFileBlob(blob) - .getSheetByName(sheetName) - .getValues(); - console.log(res); -} -``` - -- **`blob`** : Blob of XLSX file. -- **`sheetName`** : Sheet name in XLSX file. The values are retrieved from the sheet. - -Sample result value is as follows. The values are returned as 2 dimensional array. - -```json -[ - ["a1", "b1", "c1"], - ["", "b2", "c2"], - ["a3", "b3", "c3"], - ["a4", "b4", "c4"], - ["a5", "b5", "c5"] -] -``` - - - -### 6. `getFormulas()` - -This method is used for updating the formulas from a sheet of XLSX data. - -### Sample script - -```javascript -function myFunction() { - const fileId = "###"; // Please set the file ID of XLSX file. - const sheetName = "###"; // Please set the sheet name. - const blob = DriveApp.getFileById(fileId).getBlob(); - - const res = DocsServiceApp.openByExcelFileBlob(blob) - .getSheetByName(sheetName) - .getFormulas(); - console.log(res); -} -``` - -- **`blob`** : Blob of XLSX file. -- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. -- The values are returned as 2 dimensional array. - - - -## For Microsoft Powerpoint - -There are no methods yet. - ---- +- [DocumentApp](src/apps/DocumentApp/README.md) +- [SpreadsheetApp](src/apps/DocumentApp/README.md) +- [SlidesApp](src/apps/SlidesApp/README.md) +- [ExcelApp](src/apps/ExcelApp/README.md) +- [WordApp](src/apps/WordApp/README.md) +- PowerPointApp (does not exist yet) diff --git a/appsscript.json b/appsscript.json deleted file mode 100644 index 1814e95..0000000 --- a/appsscript.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "timeZone": "Asia/Tokyo", - "dependencies": { - "enabledAdvancedServices": [{ - "userSymbol": "Docs", - "serviceId": "docs", - "version": "v1" - }, { - "userSymbol": "Drive", - "serviceId": "drive", - "version": "v2" - }, { - "userSymbol": "Slides", - "serviceId": "slides", - "version": "v1" - }, { - "userSymbol": "Sheets", - "serviceId": "sheets", - "version": "v4" - }], - "libraries": [{ - "userSymbol": "ImgApp", - "libraryId": "1T03nYHRho6XMWYcaumClcWr6ble65mAT8OLJqRFJ5lukPVogAN2NDl-y", - "version": "8", - "developmentMode": true - }] - }, - "exceptionLogging": "STACKDRIVER", - "runtimeVersion": "V8" -} diff --git a/images/demo1.png b/images/demo1.png deleted file mode 100644 index b26b8bf..0000000 Binary files a/images/demo1.png and /dev/null differ diff --git a/images/fig1.png b/images/fig1.png deleted file mode 100644 index a10d3a0..0000000 Binary files a/images/fig1.png and /dev/null differ diff --git a/images/fig2.png b/images/fig2.png deleted file mode 100644 index 3cea713..0000000 Binary files a/images/fig2.png and /dev/null differ diff --git a/images/fig3.png b/images/fig3.png deleted file mode 100644 index 0307fbb..0000000 Binary files a/images/fig3.png and /dev/null differ diff --git a/mainMethods.js b/mainMethods.js deleted file mode 100644 index 41e3c1b..0000000 --- a/mainMethods.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * GitHub https://github.com/tanaikech/DocsServiceApp
- * Library name - * @type {string} - * @const {string} - * @readonly - */ -const appName = "DocsServiceApp"; - -/** - * @param {String} id Spreasheet ID. - * @return {DocsServiceApp} - */ -function openBySpreadsheetId(id) { - return new SpreadsheetAppp(id); -} - -/** - * @param {Object} blob Blob of Excel file (XLSX file). - * @return {DocsServiceApp} - */ -function openByExcelFileBlob(blob) { - return new ExcelApp(blob); -} - -/** - * @param {String} id Document ID. - * @return {DocsServiceApp} - */ -function openByDocumentId(id) { - return new DocumentAppp(id); -} - -/** - * @param {Object} blob Blob of Word file (DOCX file). - * @return {DocsServiceApp} - */ -function openByWordFileBlob(blob) { - return new WordApp(blob); -} - -/** - * @param {object} object Object including parameter for createing new Google Spreadsheet. - * @return {string} Presentation ID of cerated Google Slides. - */ -function createNewSpreadsheetWithCustomHeaderFooter(object) { - return new SpreadsheetAppp("create").createNewSpreadsheetWithCustomHeaderFooter(object); -} - -/** - * @param {object} object Object including parameter for createing new Google Slides. - * @return {string} Presentation ID of cerated Google Slides. - */ -function createNewSlidesWithPageSize(object) { - return new SlidesAppp("create").createNewSlidesWithPageSize(object); -} - -// DriveApp.createFile() // This is used for automatically detected the scope of "https://www.googleapis.com/auth/drive" -// SpreadsheetApp.create() // This is used for automatically detected the scope of "https://www.googleapis.com/auth/spreadsheets" -// SlidesApp.create(name) // This is used for automatically detected the scope of "https://www.googleapis.com/auth/presentations" -; - diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..78ec9d0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,789 @@ +{ + "name": "@scriptaddicts/docsserviceapp", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@scriptaddicts/docsserviceapp", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "copyfiles": "^2.4.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "dependencies": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "bin": { + "copyfiles": "copyfiles", + "copyup": "copyfiles" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "requires": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8d8a82d --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "@scriptaddicts/docsserviceapp", + "version": "1.0.4", + "description": "Fork of DocsServiceApp to continue support of the library", + "main": "index.js", + "scripts": { + "clean": "rm -rf dist/*", + "build": "npm run clean && copyfiles src/**/*.js dist" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ScriptAddicts/DocsServiceApp.git" + }, + "keywords": [], + "author": "tanaikech", + "license": "ISC", + "bugs": { + "url": "https://github.com/ScriptAddicts/DocsServiceApp/issues" + }, + "homepage": "https://github.com/ScriptAddicts/DocsServiceApp#readme", + "publishConfig": { + "registry": "https://npm.pkg.github.com/ScriptAddicts" + }, + "devDependencies": { + "copyfiles": "^2.4.1" + } +} diff --git a/DocumentAppp.js b/src/apps/DocumentApp/DocumentAppp.js similarity index 100% rename from DocumentAppp.js rename to src/apps/DocumentApp/DocumentAppp.js diff --git a/src/apps/DocumentApp/README.md b/src/apps/DocumentApp/README.md new file mode 100644 index 0000000..cedc909 --- /dev/null +++ b/src/apps/DocumentApp/README.md @@ -0,0 +1,31 @@ +### Available methods + +### 1. `getTableColumnWidth()` + +Retrieve the column width of the table in the Google Document. For example, when a new table, which has 1 row and 2 columns, is manually inserted to the Document body as the default format, the table width and column width retrieved by `getColumnWidth()` return `null`. By this, in the current stage, the table width and column width cannot be retrieved. This method achieves this. + +#### Sample script + +```javascript +const documentId = "###"; // Google Document ID +const res = DocsServiceApp.openByDocumentId(documentId).getTableColumnWidth(); +console.log(res); +``` + +#### Result + +```json +[ + { + "tableIndex": 0, // 0 means the 1st table in Google Document. + "unit": "pt", + "tableWidth": 451.3, // Table width + "tebleColumnWidth": [225.65, 225.65] // Column width of each column. Array index is the column index. + }, + , + , + , +] +``` + +- For example, when the table which has the columns "A" and "B" of 100 pt and 200 pt are checked by above script, the same values of 100 and 200 for the columns "A" and "B" could be confirmed. So from this result, it is found that the column width of DOCX data and Google Document is the same. \ No newline at end of file diff --git a/ExcelApp.js b/src/apps/ExcelApp/ExcelApp.js similarity index 100% rename from ExcelApp.js rename to src/apps/ExcelApp/ExcelApp.js diff --git a/src/apps/ExcelApp/README.md b/src/apps/ExcelApp/README.md new file mode 100644 index 0000000..448074f --- /dev/null +++ b/src/apps/ExcelApp/README.md @@ -0,0 +1,219 @@ + +## For Microsoft Excel + +![](images/fig3.png) + +> IMPORTANT: About `getValues()` and `getFormulas()` methods, in the current stage, the process costs of them is much higher than those of Google Spreadsheet service. So when you want to retrieve the values and formulas from XLSX data, I would like to recommend to use Google Spreadsheet service by converting XSLX data to Google Spreadsheet. + +### 1. `getImages()` + +Retrieve images in and over the cell from Microsoft Excel as blob. In this case, the images are directly retrieved from Microsoft Excel. + +#### Sample script + +```javascript +const blob = "BLOB"; // Blob of Microsoft Excel file. +const res = DocsServiceApp.openByExcelFileBlob(blob) + .getSheetByName("Sheet1") + .getImages(); +console.log(res); +``` + +In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. + +And + +```javascript +const blob = "BLOB"; // Blob of Microsoft Excel file. +const res = DocsServiceApp.openByExcelFileBlob(blob).getImages(); +console.log(res); +``` + +In this script, the images are retrieved from all sheets of `spreadsheetId`. + +- **`blob`** : Blob of XLSX file. +- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. + +#### Result + +```json +[ + { + "range": { "col": 3, "row": 8, "a1Notation": "C8" }, + "image": { + "description": "sample description", + "title": "sample title", + "blob": BLOB, + "innerCell": false // "false" means that the image is over a cell. + } + }, + { + "range": { "col": 2, "row": 2, "a1Notation": "B2" }, + "image": { + "description": "sample description", + "title": "sample title", + "blob": BLOB, + "innerCell": true // "true" means that the image is in a cell. + } + }, + , + , + , +] +``` + +- When `getSheetByName()` is not used, above array is put in each sheet as follows. + + ```json + [ + { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, + { "sheetName": "Sheet2", "images": [] }, + { "sheetName": "Sheet3", "images": [[Object], [Object]] } + ] + ``` + +#### Limitation + +- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. +- In the current stage, the drawings cannot be retrieved yet. I apologize for this. + +### 2. `getComments()` + +Retrieve comments in Microsoft Excel. In this case, the comments are directly retrieved from Microsoft Excel. + +#### Sample script + +```javascript +const blob = "BLOB"; // Blob of Microsoft Excel file. +const res = DocsServiceApp.openByExcelFileBlob(blob) + .getSheetByName("Sheet1") + .getComments(); +console.log(res); +``` + +In this script, the comments are retrieved from "Sheet1" of Blob of Microsoft Excel file. + +- **`blob`** : Blob of XLSX file. +- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. + +#### Result + +```json +[ + { + "range": { + "col": 2, + "row": 11, + "a1Notation": "B11" + }, + "comment": [ + { + "user": "user name", + "comment": "comment" + }, + , + , + , + ] + }, + , + , + , +] +``` + +### 3. `getAll()` + +This method is used for retrieving all values (in the current stage, those are values, formulas, images and comments.) from all sheets of XLSX data. The returned value is JSON object. + +#### Sample script + +```javascript +function myFunction() { + const fileId = "###"; // Please set the file ID of XLSX file. + const blob = DriveApp.getFileById(fileId).getBlob(); + + const res = DocsServiceApp.openByExcelFileBlob(blob).getAll(); + console.log(res); +} +``` + +- **`blob`** : Blob of XLSX file. +- The values are returned as JSON object. The returned values include the values, formulas, images and comments of all sheets in the XLSX data. + +### 4. `getSheets()` + +This method is used for retrieving the sheet list from XLSX data. + +#### Sample script + +```javascript +function myFunction() { + const fileId = "###"; // Please set the file ID of XLSX file. + const blob = DriveApp.getFileById(fileId).getBlob(); + + const res = DocsServiceApp.openByExcelFileBlob(blob).getSheets(); + console.log(res); +} +``` + +- **`blob`** : Blob of XLSX file. + +### 5. `getValues()` + +This method is used for updating the values from a sheet of XLSX data. + +#### Sample script + +```javascript +function myFunction() { + const fileId = "###"; // Please set the file ID of XLSX file. + const sheetName = "###"; // Please set the sheet name. + const blob = DriveApp.getFileById(fileId).getBlob(); + + const res = DocsServiceApp.openByExcelFileBlob(blob) + .getSheetByName(sheetName) + .getValues(); + console.log(res); +} +``` + +- **`blob`** : Blob of XLSX file. +- **`sheetName`** : Sheet name in XLSX file. The values are retrieved from the sheet. + +Sample result value is as follows. The values are returned as 2 dimensional array. + +```json +[ + ["a1", "b1", "c1"], + ["", "b2", "c2"], + ["a3", "b3", "c3"], + ["a4", "b4", "c4"], + ["a5", "b5", "c5"] +] +``` + + + +### 6. `getFormulas()` + +This method is used for updating the formulas from a sheet of XLSX data. + +### Sample script + +```javascript +function myFunction() { + const fileId = "###"; // Please set the file ID of XLSX file. + const sheetName = "###"; // Please set the sheet name. + const blob = DriveApp.getFileById(fileId).getBlob(); + + const res = DocsServiceApp.openByExcelFileBlob(blob) + .getSheetByName(sheetName) + .getFormulas(); + console.log(res); +} +``` + +- **`blob`** : Blob of XLSX file. +- **`sheetName`** : Sheet name in XLSX file. The formulas are retrieved from the sheet. +- The values are returned as 2 dimensional array. diff --git a/src/apps/ImgApp/ImgApp.js b/src/apps/ImgApp/ImgApp.js new file mode 100644 index 0000000..825cc4b --- /dev/null +++ b/src/apps/ImgApp/ImgApp.js @@ -0,0 +1,671 @@ +class ImgAppp { + /** + * var blob = DriveApp.getFileById(fileId).getBlob(); // Please retrieve file blob like this.
+ * var res = ImgApp.getSize(blob);
+ * @param {Object} blob File blob: png, jpg, gif and bmp + * @return {Object} JSON object {identification: [png, jpg, gif and bmp], width: [pixel], height: [pixel], filesize: [bytes]} + */ + static getSize(blob) { + return new ImgApp().GetSize(blob); + } + /** + * Resize image from inputted width. When the source file is Google Docs (spreadsheet, document and slide),
+ * its thumbnail is created and it is resized.
+ * In order to use this method, please enable Drive API at Google API console.
+ *
+ *

usage

+ * var res = ImgApp.doResize(fileId, width);
+ * DriveApp.createFile(res.blob.setName("filename")); // If you want to save as a file, please use this.
+ *
+ * @param {string} fileId File ID on Google Drive + * @param {integer} width Resized width you want + * @return {Object} JSON object {blob: [blob], originalwidth: ###, originalheight: ###, resizedwidth: ###, resizedheight: ###} + */ + static doResize(fileId, width) { + return new ImgApp().DoResize(fileId, width); + } + + /** + * Update a thumbnail of a file using an image.
+ * There are some limitations for updating thumbnail.
+ * Please confirm the detail information at https://developers.google.com/drive/v3/web/file#uploading_thumbnails.
+ * - If Drive can generate a thumbnail from the file, then it will use the generated one and ignore any you may have uploaded.
+ * - If it cannot generate a thumbnail, it will always use yours if you provided one.
+ *
+ *

usage

+ * ImgApp.updateThumbnail(imgFileId, srcFileId);
+ *
+ * @param {string} imgFileId File ID of new thumbnail image on Google Drive + * @param {string} srcFileId File ID of file, which is updated thumbnail, on Google Drive + * @return {Object} JSON object id,mimeType,name,thumbnailVersion,thumbnailLink + */ + static updateThumbnail(imgFileId, srcFileId) { + return new ImgApp().UpdateThumbnail(imgFileId, srcFileId); + } + + /** + * This method is for editing images. In the current stage, the image can be cropped. And several images can be merged as an image.
+ *
+ *

usage

+ * ImgApp.editImage(object);
+ *
+ * @param {Object} object Object for using this method. + * @return {Object} Blob of result image. + */ + static editImage(object) { + return new ImgApp().EditImage(object); + } +} + +(function (r) { + var ImgApp; + ImgApp = (function () { + var GetImage, + GetResizedSize, + byte2hex, + byte2hexNum, + byte2num, + cropImage, + fetch, + getFormat, + getImageFromSlide, + getInfBMP, + getInfGIF, + getInfJPG, + getInfPNG, + hex2num, + mergeImages, + pixelToEmu, + pixelToPt, + ptToEmu, + ptToPixel; + + ImgApp.name = "ImgApp"; + + function ImgApp(blob) { + this.bytear = []; + } + + ImgApp.prototype.EditImage = function (obj_) { + if ( + obj_.hasOwnProperty("blob") && + obj_.hasOwnProperty("crop") && + obj_.blob.toString() === "Blob" && + typeof obj_.crop === "object" + ) { + return cropImage.call(this, obj_); + } else if ( + obj_.hasOwnProperty("merge") && + Array.isArray(obj_.merge) && + Array.isArray(obj_.merge[0]) + ) { + return mergeImages.call(this, obj_); + } else { + throw new Error("Wrong object. Please confirm it again."); + } + }; + + mergeImages = function (obj_) { + var canvas, croppedBlob, object, presentationId, rs, slide, slides; + canvas = obj_.merge.reduce( + (function (_this) { + return function (o, r) { + var ar, mHeight, mWidth; + mWidth = 0; + mHeight = 0; + ar = []; + r.forEach(function (c) { + var temp; + if (c && c.toString() === "Blob") { + temp = _this.GetSize(c); + if (temp.width * temp.height > 25000000) { + throw new Error( + "The image size is too large. Please check https://gist.github.com/tanaikech/9414d22de2ff30216269ca7be4bce462" + ); + } + ar.push({ + blob: c, + left: mWidth, + top: o.maxHeight, + width: temp.width, + height: temp.height, + }); + mWidth += temp.width; + if (mHeight < temp.height) { + return (mHeight = temp.height); + } + } else { + return ar.push(null); + } + }); + o.images.push(ar); + if (o.maxWidth < mWidth) { + o.maxWidth = mWidth; + } + o.maxHeight += mHeight; + return o; + }; + })(this), + { + maxWidth: 0, + maxHeight: 0, + images: [], + } + ); + object = { + title: "tempForImaApp", + width: { + unit: "pixel", + size: canvas.maxWidth, + }, + height: { + unit: "pixel", + size: canvas.maxHeight, + }, + }; + presentationId = new SlidesAppp("create").createNewSlidesWithPageSize( + object + ); + slides = SlidesApp.openById(presentationId); + slide = slides.getSlides()[0]; + canvas.images.forEach(function (r) { + r.forEach(function (c) { + if (c) { + slide.insertImage( + c.blob, + pixelToPt.call(this, c.left), + pixelToPt.call(this, c.top), + pixelToPt.call(this, c.width), + pixelToPt.call(this, c.height) + ); + } + }); + }); + slides.saveAndClose(); + rs = canvas.maxWidth > 1600 ? 1600 : canvas.maxWidth; + if ( + obj_.hasOwnProperty("outputWidth") && + obj_.outputWidth > 0 && + obj_.outputWidth <= 1600 + ) { + rs = obj_.outputWidth; + } + croppedBlob = getImageFromSlide.call( + this, + presentationId, + slide.getObjectId(), + rs, + obj_.outputFilename + ); + DriveApp.getFileById(presentationId).setTrashed(true); + return croppedBlob; + }; + + cropImage = function (obj_) { + var _, + b, + croppedBlob, + height, + l, + object, + presentationId, + ref, + rs, + setHeight, + setL, + setT, + setWidth, + size, + slide, + slides, + t, + unit, + width; + unit = + obj_.hasOwnProperty("unit") && typeof obj_.unit === "string" + ? obj_.unit + : "pixel"; + size = this.GetSize(obj_.blob); + if (size.width * size.height > 25000000) { + throw new Error( + "The image size is too large. Please check https://gist.github.com/tanaikech/9414d22de2ff30216269ca7be4bce462" + ); + } + width = + obj_.unit === "point" ? pixelToPt.call(this, size.width) : size.width; + height = + obj_.unit === "point" ? pixelToPt.call(this, size.height) : size.height; + (ref = ["t", "b", "l", "r"].map(function (k) { + if (obj_.crop.hasOwnProperty(k)) { + return Number(obj_.crop[k]); + } else { + return 0; + } + })), + (t = ref[0]), + (b = ref[1]), + (l = ref[2]), + (r = ref[3]); + object = { + title: "tempForImaApp", + width: { + unit: obj_.unit, + size: width - r - l, + }, + height: { + unit: obj_.unit, + size: height - b - t, + }, + }; + presentationId = new SlidesAppp("create").createNewSlidesWithPageSize( + object + ); + slides = SlidesApp.openById(presentationId); + slide = slides.getSlides()[0]; + setWidth = obj_.unit === "pixel" ? pixelToPt.call(this, width) : width; + setHeight = obj_.unit === "pixel" ? pixelToPt.call(this, height) : height; + setL = obj_.unit === "pixel" ? pixelToPt.call(this, l) : l; + setT = obj_.unit === "pixel" ? pixelToPt.call(this, t) : t; + _ = slide.insertImage(obj_.blob, -setL, -setT, setWidth, setHeight); + slides.saveAndClose(); + rs = + size.width - + (obj_.unit === "point" ? ptToPixel.call(this, l) : l) - + (obj_.unit === "point" ? ptToPixel.call(this, r) : r); + if ( + obj_.hasOwnProperty("outputWidth") && + obj_.outputWidth > 0 && + obj_.outputWidth <= 1600 + ) { + rs = + obj_.unit === "point" + ? ptToPixel.call(this, obj_.outputWidth) + : obj_.outputWidth; + } + croppedBlob = getImageFromSlide.call( + this, + presentationId, + slide.getObjectId(), + rs, + obj_.blob.getName() + ); + DriveApp.getFileById(presentationId).setTrashed(true); + return croppedBlob; + }; + + ptToPixel = function (pt_) { + return pt_ * 1.33333; + }; + + ptToEmu = function (pt_) { + return pt_ * 12700; + }; + + pixelToPt = function (pixel_) { + return pixel_ * 0.75; + }; + + pixelToEmu = function (pixel_) { + return pixel_ * 0.75 * 12700; + }; + + getImageFromSlide = function (presentationId, slideId, rs, filename) { + var croppedBlob, e, er, resObj, url; + croppedBlob = null; + try { + resObj = Slides.Presentations.Pages.getThumbnail( + presentationId, + slideId, + { + "thumbnailProperties.thumbnailSize": "LARGE", + "thumbnailProperties.mimeType": "PNG", + } + ); + try { + url = resObj.contentUrl.replace(/=s\d+/, "=s" + Math.ceil(rs)); + croppedBlob = UrlFetchApp.fetch(url).getBlob(); + } catch (error) { + er = error; + throw new Error(er.message); + } + croppedBlob = croppedBlob.setName( + filename || "outputImageFromImgApp.png" + ); + } catch (error) { + e = error; + if (e.message === "Slides is not defined") { + throw new Error( + "Please enable Slides API at Advanced Google services, and try again." + ); + } else { + throw new Error(e.message); + } + } + return croppedBlob; + }; + + ImgApp.prototype.UpdateThumbnail = function (imgFileId_, srcFileId_) { + var boundary, + data, + fields, + headers, + img4thumb, + metadata, + method, + mime, + payload, + url; + if (imgFileId_ == null) { + throw new Error("No image file ID."); + } + if (srcFileId_ == null) { + throw new Error("No source file ID."); + } + img4thumb = DriveApp.getFileById(imgFileId_); + mime = img4thumb.getMimeType(); + if ( + mime !== "image/png" && + mime !== "image/gif" && + mime !== "image/hpeg" + ) { + throw new Error( + "The image format (" + mime + ") cannot be used for thumbnail." + ); + } + metadata = { + contentHints: { + thumbnail: { + image: Utilities.base64EncodeWebSafe( + img4thumb.getBlob().getBytes() + ), + mimeType: mime, + }, + }, + }; + fields = "id,mimeType,name,thumbnailVersion,thumbnailLink"; + url = + "https://www.googleapis.com/upload/drive/v3/files/" + + srcFileId_ + + "?uploadType=multipart&fields=" + + encodeURIComponent(fields); + boundary = "xxxxxxxxxx"; + data = "--" + boundary + "\r\n"; + data += 'Content-Disposition: form-data; name="metadata"\r\n'; + data += "Content-Type: application/json; charset=UTF-8\r\n\r\n"; + data += JSON.stringify(metadata) + "\r\n"; + data += "--" + boundary + "--\r\n"; + payload = Utilities.newBlob(data).getBytes(); + headers = { + Authorization: "Bearer " + ScriptApp.getOAuthToken(), + "Content-Type": "multipart/related; boundary=" + boundary, + }; + method = "patch"; + return fetch.call(this, url, method, payload, headers); + }; + + ImgApp.prototype.DoResize = function (fileId, width) { + var blob, + e, + headers, + method, + mimetype, + n, + res, + resized, + rs, + thumbUrl, + turl, + url; + try { + url = + "https://www.googleapis.com/drive/v3/files/" + + fileId + + "?fields=thumbnailLink%2CmimeType"; + method = "get"; + headers = { + Authorization: "Bearer " + ScriptApp.getOAuthToken(), + }; + res = fetch.call(this, url, method, null, headers); + thumbUrl = res.thumbnailLink; + mimetype = res.mimeType; + r = thumbUrl.split("="); + } catch (error) { + e = error; + throw new Error( + "'" + + fileId + + "' is not compatible file. Error message is " + + JSON.stringify(e) + ); + } + width = width > 0 ? width : 100; + n = false; + rs = {}; + if (~mimetype.indexOf("google-apps") || ~mimetype.indexOf("pdf")) { + n = true; + turl = thumbUrl.replace(r[r.length - 1], "s10000"); + rs = GetResizedSize.call(this, GetImage.call(this, turl, "png"), width); + } else if (~mimetype.indexOf("image")) { + rs = GetResizedSize.call( + this, + DriveApp.getFileById(fileId).getBlob(), + width + ); + } else { + turl = thumbUrl.replace(r[r.length - 1], "s10000"); + rs = GetResizedSize.call(this, GetImage.call(this, turl, "png"), width); + } + blob = GetImage.call( + this, + thumbUrl.replace(r[r.length - 1], "s" + (n ? rs.reheight : rs.rewidth)) + ); + resized = this.GetSize(blob); + return { + blob: blob, + identification: resized.identification, + originalwidth: rs.orgwidth, + originalheight: rs.orgheight, + resizedwidth: resized.width, + resizedheight: resized.height, + }; + }; + + GetImage = function (turl) { + return UrlFetchApp.fetch(turl, { + headers: { + Authorization: "Bearer " + ScriptApp.getOAuthToken(), + }, + }).getBlob(); + }; + + GetResizedSize = function (blob, width) { + var oh, ow, rh, rw, size; + size = this.GetSize(blob); + ow = size.width; + oh = size.height; + if (width > ow) { + rw = ow; + rh = oh; + } else { + rw = width; + rh = Math.ceil((width * oh) / ow); + } + return { + orgwidth: ow, + orgheight: oh, + rewidth: rw, + reheight: rh, + }; + }; + + ImgApp.prototype.GetSize = function (blob) { + var res; + this.bytear = (function (blob) { + var e; + try { + return blob.getBytes(); + } catch (error) { + e = error; + throw new Error("Cannot retrieve file blob."); + } + })(blob); + getFormat.call(this); + switch (this.format) { + case "bmp": + res = getInfBMP.call(this); + break; + case "gif": + res = getInfGIF.call(this); + break; + case "png": + res = getInfPNG.call(this); + break; + case "jpg": + res = getInfJPG.call(this); + break; + default: + res = { + Error: this.format, + }; + } + return res; + }; + + getInfBMP = function () { + return { + identification: "BMP", + width: byte2num(this.bytear.slice(18, 22), true), + height: byte2num(this.bytear.slice(22, 26), true), + filesize: this.bytear.length, + }; + }; + + getInfGIF = function () { + return { + identification: "GIF", + width: byte2num(this.bytear.slice(6, 8), true), + height: byte2num(this.bytear.slice(8, 10), true), + filesize: this.bytear.length, + }; + }; + + getInfPNG = function () { + return { + identification: "PNG", + width: byte2num(this.bytear.slice(16, 20), false), + height: byte2num(this.bytear.slice(20, 24), false), + filesize: this.bytear.length, + }; + }; + + getInfJPG = function () { + var i, ma; + i = 0; + while (i < this.bytear.length) { + i += 1; + if (byte2hexNum.call(this, this.bytear[i]) === "ff") { + i += 1; + ma = byte2hexNum.call(this, this.bytear[i]); + if (ma === "c0" || ma === "c1" || ma === "c2") { + break; + } else { + i += hex2num.call( + this, + byte2hex.call(this, this.bytear.slice(i + 1, i + 3)) + ); + } + } + } + return { + identification: "JPG", + width: hex2num.call( + this, + byte2hex.call(this, this.bytear.slice(i + 6, i + 8)) + ), + height: hex2num.call( + this, + byte2hex.call(this, this.bytear.slice(i + 4, i + 6)) + ), + filesize: this.bytear.length, + }; + }; + + getFormat = function () { + var f; + f = byte2hex.call(this, this.bytear.slice(0, 8)).join(""); + this.format = + f.slice(0, 16) === "89504e470d0a1a0a" + ? "png" + : f.slice(0, 4) === "ffd8" + ? "jpg" + : f.slice(0, 6) === "474946" + ? "gif" + : f.slice(0, 4) === "424d" + ? "bmp" + : "Cannot retrieve image size. Now, it can retrive image size from png, jpg, gif and bmp."; + }; + + byte2hexNum = function (data) { + var conv; + conv = (data < 0 ? data + 256 : data).toString(16); + return conv.length === 1 ? "0" + conv : conv; + }; + + byte2hex = function (data) { + return data + .map(function (e) { + return (e < 0 ? e + 256 : e).toString(16); + }) + .map(function (e) { + return e.length === 1 ? "0" + e : e; + }); + }; + + byte2num = function (data, byteorder) { + var conv; + if (byteorder) { + conv = data.reduceRight(function (ar, e) { + var temp; + temp = (e < 0 ? e + 256 : e).toString(16); + if (temp.length === 1) { + temp = "0" + temp; + } + ar.push(temp); + return ar; + }, []); + } else { + conv = byte2hex.call(this, data); + } + return hex2num.call(this, conv); + }; + + hex2num = function (data) { + return parseInt(data.join(""), 16); + }; + + fetch = function (url, method, payload, headers) { + var e, res; + try { + res = UrlFetchApp.fetch(url, { + method: method, + payload: payload, + headers: headers, + muteHttpExceptions: true, + }); + } catch (error) { + e = error; + throw new Error(e); + } + try { + r = JSON.parse(res.getContentText()); + } catch (error) { + e = error; + r = res.getContentText(); + } + return r; + }; + + return ImgApp; + })(); + return (r.ImgApp = ImgApp); +})(this); diff --git a/src/apps/SlidesApp/README.md b/src/apps/SlidesApp/README.md new file mode 100644 index 0000000..5c8ec7d --- /dev/null +++ b/src/apps/SlidesApp/README.md @@ -0,0 +1,26 @@ +### Slides App +### 1. `createNewSlidesWithPageSize()` + +Create new Google Slides by setting the page size. In the current stage, there are no methods for setting the page size for Google Slides in the existing Google Slides service and Slides API, although Slides API has the method of "presentations.create". This method achieves this. + +#### Sample script + +```javascript +const object = { + title: "sample title", // Title of created Slides. + parent: "###", // folder ID + width: { unit: "pixel", size: 200 }, + height: { unit: "pixel", size: 300 }, +}; +const res = DocsServiceApp.createNewSlidesWithPageSize(object); +console.log(res); +``` + +- In this method, the presentation ID of created Slides is returned. +- "pixel" and "point" can be used for `unit` in above object. + +#### Sample situations + +When this method is used, the following application can be created. + +1. [Inserting Text on Image using Google Apps Script](https://gist.github.com/tanaikech/835642df109731a559e52d831bd3342d) : This is a sample script for inserting a text on an image using Google Apps Script. \ No newline at end of file diff --git a/SlidesAppp.js b/src/apps/SlidesApp/SlidesAppp.js similarity index 100% rename from SlidesAppp.js rename to src/apps/SlidesApp/SlidesAppp.js diff --git a/src/apps/SpreadsheetApp/README.md b/src/apps/SpreadsheetApp/README.md new file mode 100644 index 0000000..f6a4dd9 --- /dev/null +++ b/src/apps/SpreadsheetApp/README.md @@ -0,0 +1,200 @@ +## Google Spreadsheet + +### 1. `getImages()` + +Retrieve images in and over the cell from Google Spreadsheet as blob. In the current stage, there are no methods for retrieving the images over the cells and inner the cells in the existing Google Spreadsheet service and Sheets API. This method achieves this. + +#### Sample script + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId) + .getSheetByName("Sheet1") + .getImages(); +console.log(res); +``` + +In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. + +And + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getImages(); +console.log(res); +``` + +In this script, the images are retrieved from all sheets of `spreadsheetId`. + +When you want to save all images in the Spreadsheet as the files, you can use the following script. + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getImages(); +const folder = DriveApp.getFolderById("### folderId ###"); +res.forEach(({ images }) => + images.forEach((e) => { + if (e.image) folder.createFile(e.image.blob); + }) +); +``` + +#### Result + +```json +[ + { + "range": { "col": 3, "row": 8, "a1Notation": "C8" }, + "image": { + "description": "sample description", + "title": "sample title", + "blob": BLOB, + "innerCell": false // "false" means that the image is over a cell. + } + }, + { + "range": { "col": 2, "row": 2, "a1Notation": "B2" }, + "image": { + "description": "sample description", + "title": "sample title", + "blob": BLOB, + "innerCell": true // "true" means that the image is in a cell. + } + }, + , + , + , +] +``` + +- You can create the image file from `BLOB`. + +- When `getSheetByName()` is not used, above array is put in each sheet as follows. + + ```json + [ + { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, + { "sheetName": "Sheet2", "images": [] }, + { "sheetName": "Sheet3", "images": [[Object], [Object]] } + ] + ``` + +#### Limitation + +- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. +- In the current stage, the drawings cannot be retrieved yet. I apologize for this. + +### 2. `getComments()` + +Retrieve comments in Google Spreadsheet. In the current stage, there are no methods for retrieving the comments with the cell coordinate in the existing Google Spreadsheet service and Sheets API. This method achieves this. + +#### Sample script + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId) + .getSheetByName("Sheet1") + .getComments(); +console.log(res); +``` + +In this script, the images are retrieved from "Sheet1" of `spreadsheetId`. + +And + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const res = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getComments(); +console.log(res); +``` + +In this script, the images are retrieved from all sheets of `spreadsheetId`. + +#### Result + +```json +[ + { + "range": { + "col": 2, + "row": 11, + "a1Notation": "B11" + }, + "comment": [ + { + "user": "user name", + "comment": "comment" + }, + , + , + , + ] + }, + , + , + , +] +``` + +- When `getSheetByName()` is not used, above array is put in each sheet as follows. + + ```json + [ + { "sheetName": "Sheet1", "images": [[Object], [Object], [Object]] }, + { "sheetName": "Sheet2", "images": [] }, + { "sheetName": "Sheet3", "images": [[Object], [Object]] } + ] + ``` + +### 3. `insertImage()` + +Insert images in and over the cell from Google Spreadsheet from the image blob. In the current stage, there are no methods for directly inserting an image in a cell in the existing Google Spreadsheet service and Sheets API. For example, when the user wants to insert an image on own Google Drive in a cell, the image is required to be publicly shared for using `=IMAGE(URL)`. In this method, the image can be put without publicly sharing the image and using `=IMAGE(URL)`. + +#### Sample script + +```javascript +const spreadsheetId = "###"; // Google Spreadsheet ID +const blob1 = DriveApp.getFileById("###fileId###").getBlob(); +const blob2 = UrlFetchApp.fetch("###URL###").getBlob(); +const object = [ + { blob: blob1, range: { row: 1, column: 1 } }, // Image is inserted in a cell "A1". + { blob: blob2, range: { row: 5, column: 2 } }, // Image is inserted in a cell "B5". +]; +DocsServiceApp.openBySpreadsheetId(spreadsheetId) + .getSheetByName("Sheet1") + .insertImage(object); +``` + +- **In this method, no values are returned.** +- In above sample script, 2 images are inserted into the cells "A1" and "B5" in "Sheet1", respectively. + +#### Result + +![](images/fig1.png) + +- The sample image of cell "A1" is from [https://www.deviantart.com/k3-studio/art/Rainbow-painting-281090729](https://www.deviantart.com/k3-studio/art/Rainbow-painting-281090729) +- The sample image of cell "B5" is from [https://www.deviantart.com/k3-studio/art/Chromatic-lituus-415318548](https://www.deviantart.com/k3-studio/art/Chromatic-lituus-415318548) + +#### Limitation + +- When the images are retrieved from XLSX data, it seems that the image is a bit different from the original one. The image format is the same. But the data size is smaller than that of the original. When the image size is more than 2048 pixels and 72 dpi, the image is modified to 2048 pixels and 72 dpi. Even when the image size is less than 2048 pixels and 72 dpi, the file size becomes smaller than that of original one. So I think that the image might be compressed. Please be careful this. +- In the current stage, the drawings cannot be retrieved yet. I apologize for this. + +### 4. `createNewSpreadsheetWithCustomHeaderFooter()` + +Create new Google Spreadsheet by setting the header and footer. In the current stage, there are no methods for setting the header and footer for Google Spreadsheet in the existing Google Spreadsheet service and Sheets API. This method achieves this. + +#### Sample script + +```javascript +const object = { + title: "sample title", // Title of created Spreadsheet. + parent: "###", // folder ID + header: { l: "left header", c: "center header", r: "right header" }, + footer: { l: "left footer", c: "center footer", r: "right footer" }, +}; +const res = DocsServiceApp.createNewSpreadsheetWithCustomHeaderFooter(object); +console.log(res); +``` + +- In this method, the spreadsheet ID of created Spreadsheet is returned. \ No newline at end of file diff --git a/SpreadsheetAppp.js b/src/apps/SpreadsheetApp/SpreadsheetAppp.js similarity index 98% rename from SpreadsheetAppp.js rename to src/apps/SpreadsheetApp/SpreadsheetAppp.js index 85ea09c..48d0d56 100644 --- a/SpreadsheetAppp.js +++ b/src/apps/SpreadsheetApp/SpreadsheetAppp.js @@ -59,7 +59,7 @@ if (blob.toString() !== "Blob" || !range.row || !range.column || isNaN(range.row) || isNaN(range.column)) { return true; } - ({width, height, identification} = ImgApp.getSize(blob)); + ({width, height, identification} = ImgAppp.getSize(blob)); if (width * height > 1048576) { return true; } @@ -84,8 +84,10 @@ title: "SpreadsheetAppp_temp", mimeType: MimeType.GOOGLE_SHEETS }, blob).id; + console.log(`LIB`, "TMP ID AFYTER INSER", tmpId); } catch (error) { e = error; + console.log(`ERROR`, error); if (e.message === "Drive is not defined") { putError.call(this, "Please enable Drive API at Advanced Google services, and try again."); } else { @@ -96,7 +98,7 @@ dstSheet = dstSS.getSheetByName(this.obj.sheetName); dstSheetId = dstSheet.getSheetId(); tmpSheet = SpreadsheetApp.openById(tmpId).getSheets()[0].setName(`SpreadsheetAppp_${Utilities.getUuid()}`).copyTo(dstSS); - DriveApp.getFileById(tmpId).setTrashed(true); + Drive.Files.remove(tmpId); tmpSheetId = tmpSheet.getSheetId(); requests = ar.map((e) => { e.from.sheetId = tmpSheetId; @@ -386,6 +388,7 @@ }; putError = function(m) { + console.log(`ERROR WITH LIB`, m); throw new Error(`${m}`); }; diff --git a/src/apps/WordApp/README.md b/src/apps/WordApp/README.md new file mode 100644 index 0000000..4991ee6 --- /dev/null +++ b/src/apps/WordApp/README.md @@ -0,0 +1,30 @@ + +## For Microsoft Word + +### 1. `getTableColumnWidth()` + +Retrieve the column width of the table in the Microsoft Word. In this case, the column width of the table are directly retrieved from Microsoft Word. + +#### Sample script + +```javascript +const blob = "BLOB"; // Blob of Microsoft Word file. +const res = DocsServiceApp.openByWordFileBlob(blob).getTableColumnWidth(); +console.log(res); +``` + +#### Result + +```json +[ + { + "tableIndex": 0, // 0 means the 1st table in Google Document. + "unit": "pt", + "tableWidth": 451.3, // Table width + "tebleColumnWidth": [225.65, 225.65] // Column width of each column. Array index is the column index. + }, + , + , + , +] +``` \ No newline at end of file diff --git a/WordApp.js b/src/apps/WordApp/WordApp.js similarity index 100% rename from WordApp.js rename to src/apps/WordApp/WordApp.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..6fcc10b --- /dev/null +++ b/src/index.js @@ -0,0 +1,49 @@ +class DocsServiceApp { + + /** + * @param {String} id Spreasheet ID. + * @return {DocsServiceApp} + */ + static openBySpreadsheetId(id) { + return new SpreadsheetAppp(id); + } + /** + * @param {Object} blob Blob of Excel file (XLSX file). + * @return {DocsServiceApp} + */ + static openByExcelFileBlob(blob) { + return new ExcelApp(blob); + } + + /** + * @param {String} id Document ID. + * @return {DocsServiceApp} + */ + static openByDocumentId(id) { + return new DocumentAppp(id); + } + + /** + * @param {Object} blob Blob of Word file (DOCX file). + * @return {DocsServiceApp} + */ + static openByWordFileBlob(blob) { + return new WordApp(blob); + } + + /** + * @param {object} object Object including parameter for createing new Google Spreadsheet. + * @return {string} Presentation ID of cerated Google Slides. + */ + static createNewSpreadsheetWithCustomHeaderFooter(object) { + return new SpreadsheetAppp("create").createNewSpreadsheetWithCustomHeaderFooter(object); + } + + /** + * @param {object} object Object including parameter for createing new Google Slides. + * @return {string} Presentation ID of cerated Google Slides. + */ + static createNewSlidesWithPageSize(object) { + return new SlidesAppp("create").createNewSlidesWithPageSize(object); + } +} \ No newline at end of file