├── _config.yml ├── .travis.yml ├── .releaserc.json ├── tsconfig.json ├── .github └── workflows │ └── release.yml ├── cli.ts ├── LICENSE ├── package.json ├── document.md ├── .gitignore ├── index.ts ├── README.md └── document.json /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | script: 5 | - "npm run build" 6 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "semantic-release-gitmoji", 5 | { 6 | "releaseRules": { 7 | "patch": { 8 | "include": [":bento:", ":recycle:"] 9 | } 10 | } 11 | } 12 | ], 13 | "@semantic-release/github", 14 | "@semantic-release/npm", 15 | [ 16 | "@semantic-release/git", 17 | { 18 | "message": ":bookmark: v${nextRelease.version} [skip ci]\n\nhttps://github.com/AnandChowdhary/docs-markdown/releases/tag/${nextRelease.gitTag}" 19 | } 20 | ] 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es6", 5 | "module": "commonjs", 6 | "lib": ["dom", "esnext"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "declarationDir": "./dist", 15 | "outDir": "./dist", 16 | "typeRoots": ["node_modules/@types", "@types"] 17 | }, 18 | "include": ["index.ts", "cli.ts"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release: 8 | name: Build, test, and release 9 | runs-on: ubuntu-18.04 10 | if: "!contains(github.event.head_commit.message, '[skip ci]')" 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v1 14 | - name: Setup Node.js 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | - name: Install dependencies 19 | run: npm ci 20 | - name: Build TypeScript 21 | run: npm run build 22 | - name: Release 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 26 | run: npx semantic-release 27 | -------------------------------------------------------------------------------- /cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { fetchGoogleDocsFiles, googleDocsToMarkdown } from "./index"; 4 | import { readFileSync, writeFileSync } from "fs"; 5 | import { join } from "path"; 6 | 7 | const command = process.argv[2]; 8 | if (!command) throw new Error("Command required: 'docs-markdown fetch'"); 9 | 10 | if (command === "fetch") { 11 | const files: string[] = (process.argv.length > 3 12 | ? process.argv[3] 13 | : process.env.FILES || "" 14 | ) 15 | .split(",") 16 | .map((i) => i.trim()); 17 | fetchGoogleDocsFiles(files); 18 | } 19 | 20 | if (command === "convert") { 21 | const files: string[] = (process.argv.length > 3 22 | ? process.argv[3] 23 | : process.env.FILES || "" 24 | ) 25 | .split(",") 26 | .map((i) => i.trim()); 27 | files.forEach((file) => { 28 | const fileContents = JSON.parse(readFileSync(join(".", file)).toString()); 29 | const markdown = googleDocsToMarkdown(fileContents); 30 | writeFileSync(join(".", `${file.replace(".json", "")}.md`), markdown); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Anand Chowdhary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs-markdown", 3 | "version": "1.3.0", 4 | "description": "Opinionated starter for Node.js + TypeScript libraries", 5 | "main": "dist/index.js", 6 | "bin": "dist/cli.js", 7 | "types": "dist/index.d.ts", 8 | "files": [ 9 | "dist" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "jest", 14 | "test-report": "jest --coverage --coverageReporters=text-lcov | coveralls", 15 | "test-without-reporting": "jest --coverage", 16 | "semantic-release": "semantic-release" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/AnandChowdhary/docs-markdown.git" 21 | }, 22 | "keywords": [ 23 | "node.js", 24 | "typescript", 25 | "javascript", 26 | "library" 27 | ], 28 | "author": "Anand Chowdhary ", 29 | "engines": { 30 | "node": ">=10.0.0" 31 | }, 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/AnandChowdhary/docs-markdown/issues" 35 | }, 36 | "homepage": "https://anandchowdhary.github.io/docs-markdown/", 37 | "dependencies": { 38 | "dotenv": "^8.2.0", 39 | "googleapis": "^49.0.0" 40 | }, 41 | "devDependencies": { 42 | "@semantic-release/git": "^9.0.0", 43 | "@types/jest": "^25.2.1", 44 | "@types/node": "^13.13.4", 45 | "coveralls": "^3.1.0", 46 | "jest": "^25.4.0", 47 | "semantic-release": "^17.0.7", 48 | "semantic-release-gitmoji": "^1.3.3", 49 | "ts-jest": "^25.4.0", 50 | "typescript": "^3.8.3" 51 | }, 52 | "jest": { 53 | "roots": [ 54 | "" 55 | ], 56 | "transform": { 57 | "^.+\\.tsx?$": "ts-jest" 58 | }, 59 | "moduleFileExtensions": [ 60 | "js", 61 | "ts", 62 | "json" 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /document.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Google Docs Formatting Test 3 | documentId: 1LP_eAz_bPaBCLKWr2kGX4TEWC_Oonf3Yiz8VnfqFbng 4 | revisionId: AEUikct9XzFMG_UqPLYnqJAuFrCJMt7PHLUVmm28GVsR8L_Zi39maUDqJmqPuYsZc_eYF7_OqdRya2I_UJyror0 5 | --- 6 | 7 | # Google Docs Formatting Test (title) 8 | 9 | _This is the subtitle_ 10 | 11 | This is a normal paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae viverra est, vitae maximus massa. Nunc bibendum lectus erat, accumsan porta dolor dictum vel. Fusce vitae nisi at ligula imperdiet congue vitae non turpis. Nam in dolor at turpis rhoncus semper. Pellentesque venenatis at enim vel viverra. Sed iaculis id mauris sit amet rutrum. 12 | 13 | ## First Heading One 14 | 15 | This is a normal paragraph but has extra features, like this **bold** word and this _italic_ word. This work is underlined and these ones are **_all three_**. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae viverra est, vitae maximus massa. This text has a different color, it’s red and this one is dark green. This one is highlighted. So many styles. 16 | 17 | ### The second heading 18 | 19 | This is a paragraph after the H2. This is a [link](https://anandchowdhary.com) to my website. 20 | 21 | 1. This is a numbered list counting items 22 | 1. The second item has a **bold** word 23 | 1. The third one is right aligned 24 | 25 | Suspendisse at magna nec sapien consectetur interdum ac ac felis. Sed maximus felis leo, vitae gravida tortor molestie eget. Aliquam vehicula magna ipsum, ac tristique erat accumsan sit amet. Ut porta magna nulla, sed iaculis ex vestibulum in. 26 | 27 | - This is a normal list with hyphens 28 | - It has levels 29 | - Many levels 30 | - Not that many 31 | - Levels 32 | 33 | Integer elementum massa elit, eu gravida orci sodales eget. Mauris vestibulum libero a ex cursus gravida. Praesent auctor finibus sem, sed lobortis arcu. Aliquam vitae varius dui. Donec vitae massa pellentesque, imperdiet dolor in, tincidunt ipsum. Donec viverra, diam at tincidunt suscipit, libero dolor maximus quam, eu bibendum magna massa at quam. In non urna ipsum. 34 | 35 | #### This is H3, with a table below 36 | 37 | _That’s all, folks!_ 38 | 39 | 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Built files 107 | dist/ 108 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { google, docs_v1 } from "googleapis"; 2 | import { join } from "path"; 3 | import { config } from "dotenv"; 4 | import { promises as fs } from "fs"; 5 | config(); 6 | 7 | const oauth2Client = new google.auth.OAuth2( 8 | process.env.GOOGLE_DOCS_CLIENT_ID, 9 | process.env.GOOGLE_DOCS_CLIENT_SECRET, 10 | "https://developers.google.com/oauthplayground" 11 | ); 12 | oauth2Client.setCredentials({ 13 | access_token: process.env.GOOGLE_DOCS_ACCESS, 14 | refresh_token: process.env.GOOGLE_DOCS_REFRESH, 15 | }); 16 | const docs = google.docs("v1"); 17 | 18 | export const fetchGoogleDocsFiles = async (files: string[]) => { 19 | for await (const documentId of files) { 20 | console.log("\nDownloading document", documentId); 21 | try { 22 | const result = await docs.documents.get({ 23 | documentId: documentId.split(":")[0], 24 | auth: oauth2Client, 25 | }); 26 | const title = documentId.includes(":") 27 | ? documentId.split(":")[1] 28 | : `${result.data.title}.md`; 29 | if (!title) throw new Error("Title not found"); 30 | await fs.writeFile(join(".", title), googleDocsToMarkdown(result.data)); 31 | console.log("Downloaded document", result.data.title); 32 | } catch (error) { 33 | console.log("Got an error", error); 34 | } 35 | } 36 | }; 37 | 38 | export const googleDocsToMarkdown = (file: docs_v1.Schema$Document) => { 39 | let text = `--- 40 | title: ${file.title} 41 | documentId: ${file.documentId} 42 | revisionId: ${file.revisionId} 43 | --- 44 | 45 | `; 46 | file.body?.content?.forEach((item) => { 47 | /** 48 | * Tables 49 | */ 50 | if (item.table?.tableRows) { 51 | // Make a blank header 52 | const cells = item.table.tableRows[0]?.tableCells; 53 | // Make a blank header 54 | text += `|${cells?.map(() => "").join("|")}|\n|${cells 55 | ?.map(() => "-") 56 | .join("|")}|\n`; 57 | item.table.tableRows.forEach(({ tableCells }) => { 58 | const textRows: any[] = []; 59 | tableCells?.forEach(({ content }) => { 60 | content?.forEach(({ paragraph }) => { 61 | const styleType = 62 | paragraph?.paragraphStyle?.namedStyleType || undefined; 63 | 64 | textRows.push( 65 | paragraph?.elements?.map((element) => 66 | styleElement(element, styleType)?.replace(/\s+/g, "").trim() 67 | ) 68 | ); 69 | }); 70 | }); 71 | text += `| ${textRows.join(" | ")} |\n`; 72 | }); 73 | } 74 | 75 | /** 76 | * Paragraphs and lists 77 | */ 78 | if (item.paragraph && item.paragraph.elements) { 79 | const styleType = 80 | item?.paragraph?.paragraphStyle?.namedStyleType || undefined; 81 | const bullet = item.paragraph?.bullet; 82 | if (bullet?.listId) { 83 | const listDetails = file.lists?.[bullet.listId]; 84 | const glyphFormat = 85 | listDetails?.listProperties?.nestingLevels?.[0].glyphFormat || ""; 86 | const padding = " ".repeat(bullet.nestingLevel || 0); 87 | if (["[%0]", "%0."].includes(glyphFormat)) { 88 | text += `${padding}1. `; 89 | } else { 90 | text += `${padding}- `; 91 | } 92 | } 93 | item.paragraph.elements.forEach((element) => { 94 | if (element.textRun && content(element) && content(element) !== "\n") { 95 | text += styleElement(element, styleType); 96 | } 97 | }); 98 | text += bullet?.listId 99 | ? (text.split("\n").pop() || "").trim().endsWith("\n") 100 | ? "" 101 | : "\n" 102 | : "\n\n"; 103 | } 104 | }); 105 | 106 | const lines = text.split("\n"); 107 | const linesToDelete: number[] = []; 108 | lines.forEach((line, index) => { 109 | if (index > 2) { 110 | if ( 111 | !line.trim() && 112 | ((lines[index - 1] || "").trim().startsWith("1. ") || 113 | (lines[index - 1] || "").trim().startsWith("- ")) && 114 | ((lines[index + 1] || "").trim().startsWith("1. ") || 115 | (lines[index + 1] || "").trim().startsWith("- ")) 116 | ) 117 | linesToDelete.push(index); 118 | } 119 | }); 120 | text = text 121 | .split("\n") 122 | .filter((_, i) => !linesToDelete.includes(i)) 123 | .join("\n"); 124 | return text.replace(/\n\s*\n\s*\n/g, "\n\n") + "\n"; 125 | }; 126 | 127 | const styleElement = ( 128 | element: docs_v1.Schema$ParagraphElement, 129 | styleType?: string 130 | ): string | undefined => { 131 | if (styleType === "TITLE") { 132 | return `# ${content(element)}`; 133 | } else if (styleType === "SUBTITLE") { 134 | return `_${(content(element) || "").trim()}_`; 135 | } else if (styleType === "HEADING_1") { 136 | return `## ${content(element)}`; 137 | } else if (styleType === "HEADING_2") { 138 | return `### ${content(element)}`; 139 | } else if (styleType === "HEADING_3") { 140 | return `#### ${content(element)}`; 141 | } else if (styleType === "HEADING_4") { 142 | return `##### ${content(element)}`; 143 | } else if (styleType === "HEADING_5") { 144 | return `###### ${content(element)}`; 145 | } else if (styleType === "HEADING_6") { 146 | return `####### ${content(element)}`; 147 | } else if ( 148 | element.textRun?.textStyle?.bold && 149 | element.textRun?.textStyle?.italic 150 | ) { 151 | return `**_${content(element)}_**`; 152 | } else if (element.textRun?.textStyle?.italic) { 153 | return `_${content(element)}_`; 154 | } else if (element.textRun?.textStyle?.bold) { 155 | return `**${content(element)}**`; 156 | } 157 | 158 | return content(element); 159 | }; 160 | 161 | const content = ( 162 | element: docs_v1.Schema$ParagraphElement 163 | ): string | undefined => { 164 | const textRun = element?.textRun; 165 | const text = textRun?.content; 166 | if (textRun?.textStyle?.link?.url) 167 | return `[${text}]${textRun.textStyle.link.url}`; 168 | return text || undefined; 169 | }; 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📝 Docs Markdown 2 | 3 | Convert a Google Docs file (API response) to Markdown 4 | 5 | [![Node CI](https://img.shields.io/github/workflow/status/AnandChowdhary/docs-markdown/Node%20CI?label=GitHub%20CI&logo=github)](https://github.com/AnandChowdhary/docs-markdown/actions) 6 | [![Travis CI](https://img.shields.io/travis/AnandChowdhary/docs-markdown?label=Travis%20CI&logo=travis%20ci&logoColor=%23fff)](https://travis-ci.org/AnandChowdhary/docs-markdown) 7 | [![Coverage](https://coveralls.io/repos/github/AnandChowdhary/docs-markdown/badge.svg?branch=master&v=2)](https://coveralls.io/github/AnandChowdhary/docs-markdown?branch=master) 8 | [![Dependencies](https://img.shields.io/librariesio/release/npm/docs-markdown)](https://libraries.io/npm/docs-markdown) 9 | [![License](https://img.shields.io/npm/l/docs-markdown)](https://github.com/AnandChowdhary/docs-markdown/blob/master/LICENSE) 10 | [![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/docs-markdown.svg)](https://snyk.io/test/npm/docs-markdown) 11 | [![Based on Node.ts](https://img.shields.io/badge/based%20on-node.ts-brightgreen)](https://github.com/AnandChowdhary/node.ts) 12 | [![npm type definitions](https://img.shields.io/npm/types/docs-markdown.svg)](https://unpkg.com/browse/docs-markdown/dist/index.d.ts) 13 | [![npm package](https://img.shields.io/npm/v/docs-markdown.svg)](https://www.npmjs.com/package/node.ts) 14 | [![npm downloads](https://img.shields.io/npm/dw/docs-markdown)](https://www.npmjs.com/package/node.ts) 15 | [![Contributors](https://img.shields.io/github/contributors/AnandChowdhary/docs-markdown)](https://github.com/AnandChowdhary/docs-markdown/graphs/contributors) 16 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) 17 | 18 | [![npm](https://nodei.co/npm/docs-markdown.png)](https://www.npmjs.com/package/docs-markdown) 19 | 20 | ## 💡 Usage 21 | 22 | Install the package from [npm](https://www.npmjs.com/package/docs-markdown): 23 | 24 | ```bash 25 | npm install docs-markdown 26 | ``` 27 | 28 | ### API 29 | 30 | The `fetchGoogleDocsFiles` helper can download a document from Google Docs and save it as a markdown file: 31 | 32 | ```ts 33 | import { fetchGoogleDocsFiles } from "docs-markdown"; 34 | 35 | // Google Docs document ID 36 | await fetchGoogleDocsFiles(["1UEUrJ98RXu9BNcFj3pMgiUALQpjIb8Y-gNu-YhlYvFQ"]); 37 | 38 | // Google Docs document ID and file name 39 | await fetchGoogleDocsFiles(["1UEUrJ98RXu9BNcFj3pMgiUALQpjIb8Y-gNu-YhlYvFQ:filename.md"]); 40 | 41 | // Multiple Google Docs documents (comma-separated string) 42 | await fetchGoogleDocsFiles(["documentId1", "documentId2", "documentId3"]); 43 | ``` 44 | 45 | You can also use the `googleDocsToMarkdown` function to manually convert documents: 46 | 47 | ```ts 48 | import { googleDocsToMarkdown } from "docs-markdown"; 49 | import { google } from "googleapis"; 50 | import { writeFileSync } from "fs"; 51 | const oauth2Client = new google.auth.OAuth2(); // Authenticate 52 | 53 | const docs = google.docs("v1"); 54 | const file = await docs.documents.get({ 55 | documentId: "Google Docs document ID", 56 | auth: oauth2Client, 57 | }); 58 | 59 | const markdown = googleDocsToMarkdown(file.data); 60 | writeFileSync("file.md", markdown); 61 | ``` 62 | 63 | ### CLI 64 | 65 | Fetch files and save them as markdown: 66 | 67 | ```bash 68 | # Google Docs document ID 69 | docs-markdown fetch "1UEUrJ98RXu9BNcFj3pMgiUALQpjIb8Y-gNu-YhlYvFQ" 70 | 71 | # Google Docs document ID with file name 72 | docs-markdown fetch "1UEUrJ98RXu9BNcFj3pMgiUALQpjIb8Y-gNu-YhlYvFQ:filename.md" 73 | 74 | # Multiple Google Docs documents 75 | docs-markdown fetch "documentId1, documentId2, documentId3" 76 | 77 | # Convert a JSON document to markdown 78 | docs-markdown convert "path/to/file.json" 79 | ``` 80 | 81 | ### Authentication 82 | 83 | The following environment variables are required to fetch files from Google Docs. They are not required when converting JSON documents to markdown: 84 | 85 | - `GOOGLE_DOCS_CLIENT_ID` 86 | - `GOOGLE_DOCS_CLIENT_SECRET` 87 | - `GOOGLE_DOCS_ACCESS` 88 | - `GOOGLE_DOCS_REFRESH` 89 | 90 | To learn how to create a client ID and secret, read the article [Using OAuth 2.0 to Access Google APIs](https://developers.google.com/identity/protocols/oauth2). Once you've created them, create an access token and a refresh token, use the [OAuth 2.0 Playground](https://developers.google.com/oauthplayground/) with your client ID and secret. 91 | 92 | ## ⭐️ Features 93 | 94 | - [x] Paragraphs 95 | - [x] Headings, titles, subtitles 96 | - [x] Bold, italic 97 | - [x] Lists 98 | - [x] Links 99 | - [ ] Images 100 | - [x] Tables 101 | - [ ] Header, footer 102 | 103 | ## 🍳 Recipes 104 | 105 | ### GitHub Actions + Google Docs CI 106 | 107 | If you want to sync your Google Docs documents as markdown files to a GitHub repository, you can use this GitHub Actions workflow that runs every day, fetches your documents, and commit them to your repo. Make sure you have all the required environment variables stored as GitHub Secrets: 108 | 109 | ```yml 110 | name: Google Docs 111 | on: 112 | schedule: 113 | - cron: "0 0 * * *" 114 | jobs: 115 | release: 116 | name: Fetch Google Docs 117 | runs-on: ubuntu-18.04 118 | steps: 119 | - name: Checkout 120 | uses: actions/checkout@v2 121 | - name: Setup Node.js 122 | uses: actions/setup-node@v1 123 | with: 124 | node-version: 12 125 | - name: Download files 126 | run: npx docs-markdown fetch "1UEUrJ98RXu9BNcFj3pMgiUALQpjIb8Y-gNu-YhlYvFQ" 127 | env: 128 | GOOGLE_DOCS_ACCESS: ${{ secrets.GOOGLE_DOCS_ACCESS }} 129 | GOOGLE_DOCS_REFRESH: ${{ secrets.GOOGLE_DOCS_REFRESH }} 130 | GOOGLE_DOCS_CLIENT_ID: ${{ secrets.GOOGLE_DOCS_CLIENT_ID }} 131 | GOOGLE_DOCS_CLIENT_SECRET: ${{ secrets.GOOGLE_DOCS_CLIENT_SECRET }} 132 | - name: Commit new data 133 | uses: stefanzweifel/git-auto-commit-action@v4.1.1 134 | with: 135 | commit_message: "Update Google Docs file" 136 | commit_user_name: GitHub Actions 137 | commit_user_email: actions@github.com 138 | commit_author: GitHub Actions 139 | ``` 140 | 141 | ## 👩‍💻 Development 142 | 143 | Build TypeScript: 144 | 145 | ```bash 146 | npm run build 147 | ``` 148 | 149 | ## 📄 License 150 | 151 | [MIT](./LICENSE) © [Anand Chowdhary](https://anandchowdhary.com) 152 | -------------------------------------------------------------------------------- /document.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Google Docs Formatting Test", 3 | "body": { 4 | "content": [ 5 | { 6 | "endIndex": 1, 7 | "sectionBreak": { 8 | "sectionStyle": { 9 | "columnSeparatorStyle": "NONE", 10 | "contentDirection": "LEFT_TO_RIGHT", 11 | "sectionType": "CONTINUOUS" 12 | } 13 | } 14 | }, 15 | { 16 | "startIndex": 1, 17 | "endIndex": 37, 18 | "paragraph": { 19 | "elements": [ 20 | { 21 | "startIndex": 1, 22 | "endIndex": 37, 23 | "textRun": { 24 | "content": "Google Docs Formatting Test (title)\n", 25 | "textStyle": {} 26 | } 27 | } 28 | ], 29 | "paragraphStyle": { 30 | "headingId": "h.nixva0zef6u3", 31 | "namedStyleType": "TITLE", 32 | "direction": "LEFT_TO_RIGHT" 33 | } 34 | } 35 | }, 36 | { 37 | "startIndex": 37, 38 | "endIndex": 58, 39 | "paragraph": { 40 | "elements": [ 41 | { 42 | "startIndex": 37, 43 | "endIndex": 58, 44 | "textRun": { 45 | "content": "This is the subtitle\n", 46 | "textStyle": {} 47 | } 48 | } 49 | ], 50 | "paragraphStyle": { 51 | "headingId": "h.tj3gd1ddfved", 52 | "namedStyleType": "SUBTITLE", 53 | "direction": "LEFT_TO_RIGHT" 54 | } 55 | } 56 | }, 57 | { 58 | "startIndex": 58, 59 | "endIndex": 433, 60 | "paragraph": { 61 | "elements": [ 62 | { 63 | "startIndex": 58, 64 | "endIndex": 433, 65 | "textRun": { 66 | "content": "This is a normal paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae viverra est, vitae maximus massa. Nunc bibendum lectus erat, accumsan porta dolor dictum vel. Fusce vitae nisi at ligula imperdiet congue vitae non turpis. Nam in dolor at turpis rhoncus semper. Pellentesque venenatis at enim vel viverra. Sed iaculis id mauris sit amet rutrum.\n", 67 | "textStyle": {} 68 | } 69 | } 70 | ], 71 | "paragraphStyle": { 72 | "namedStyleType": "NORMAL_TEXT", 73 | "direction": "LEFT_TO_RIGHT" 74 | } 75 | } 76 | }, 77 | { 78 | "startIndex": 433, 79 | "endIndex": 451, 80 | "paragraph": { 81 | "elements": [ 82 | { 83 | "startIndex": 433, 84 | "endIndex": 451, 85 | "textRun": { "content": "First Heading One\n", "textStyle": {} } 86 | } 87 | ], 88 | "paragraphStyle": { 89 | "headingId": "h.gt4fdj731x8e", 90 | "namedStyleType": "HEADING_1", 91 | "direction": "LEFT_TO_RIGHT" 92 | } 93 | } 94 | }, 95 | { 96 | "startIndex": 451, 97 | "endIndex": 812, 98 | "paragraph": { 99 | "elements": [ 100 | { 101 | "startIndex": 451, 102 | "endIndex": 512, 103 | "textRun": { 104 | "content": "This is a normal paragraph but has extra features, like this ", 105 | "textStyle": {} 106 | } 107 | }, 108 | { 109 | "startIndex": 512, 110 | "endIndex": 516, 111 | "textRun": { "content": "bold", "textStyle": { "bold": true } } 112 | }, 113 | { 114 | "startIndex": 516, 115 | "endIndex": 531, 116 | "textRun": { "content": " word and this ", "textStyle": {} } 117 | }, 118 | { 119 | "startIndex": 531, 120 | "endIndex": 537, 121 | "textRun": { 122 | "content": "italic", 123 | "textStyle": { "italic": true } 124 | } 125 | }, 126 | { 127 | "startIndex": 537, 128 | "endIndex": 557, 129 | "textRun": { "content": " word. This work is ", "textStyle": {} } 130 | }, 131 | { 132 | "startIndex": 557, 133 | "endIndex": 567, 134 | "textRun": { 135 | "content": "underlined", 136 | "textStyle": { "underline": true } 137 | } 138 | }, 139 | { 140 | "startIndex": 567, 141 | "endIndex": 587, 142 | "textRun": { "content": " and these ones are ", "textStyle": {} } 143 | }, 144 | { 145 | "startIndex": 587, 146 | "endIndex": 596, 147 | "textRun": { 148 | "content": "all three", 149 | "textStyle": { "bold": true, "italic": true, "underline": true } 150 | } 151 | }, 152 | { 153 | "startIndex": 596, 154 | "endIndex": 739, 155 | "textRun": { 156 | "content": ". Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vitae viverra est, vitae maximus massa. This text has a different color, it’s ", 157 | "textStyle": {} 158 | } 159 | }, 160 | { 161 | "startIndex": 739, 162 | "endIndex": 742, 163 | "textRun": { 164 | "content": "red", 165 | "textStyle": { 166 | "foregroundColor": { "color": { "rgbColor": { "red": 1 } } } 167 | } 168 | } 169 | }, 170 | { 171 | "startIndex": 742, 172 | "endIndex": 759, 173 | "textRun": { "content": " and this one is ", "textStyle": {} } 174 | }, 175 | { 176 | "startIndex": 759, 177 | "endIndex": 769, 178 | "textRun": { 179 | "content": "dark green", 180 | "textStyle": { 181 | "foregroundColor": { 182 | "color": { 183 | "rgbColor": { 184 | "red": 0.21960784, 185 | "green": 0.4627451, 186 | "blue": 0.11372549 187 | } 188 | } 189 | } 190 | } 191 | } 192 | }, 193 | { 194 | "startIndex": 769, 195 | "endIndex": 783, 196 | "textRun": { "content": ". This one is ", "textStyle": {} } 197 | }, 198 | { 199 | "startIndex": 783, 200 | "endIndex": 794, 201 | "textRun": { 202 | "content": "highlighted", 203 | "textStyle": { 204 | "backgroundColor": { 205 | "color": { "rgbColor": { "red": 1, "green": 1 } } 206 | } 207 | } 208 | } 209 | }, 210 | { 211 | "startIndex": 794, 212 | "endIndex": 812, 213 | "textRun": { "content": ". So many styles.\n", "textStyle": {} } 214 | } 215 | ], 216 | "paragraphStyle": { 217 | "namedStyleType": "NORMAL_TEXT", 218 | "direction": "LEFT_TO_RIGHT" 219 | } 220 | } 221 | }, 222 | { 223 | "startIndex": 812, 224 | "endIndex": 831, 225 | "paragraph": { 226 | "elements": [ 227 | { 228 | "startIndex": 812, 229 | "endIndex": 831, 230 | "textRun": { "content": "The second heading\n", "textStyle": {} } 231 | } 232 | ], 233 | "paragraphStyle": { 234 | "headingId": "h.91jfgnif79dy", 235 | "namedStyleType": "HEADING_2", 236 | "direction": "LEFT_TO_RIGHT" 237 | } 238 | } 239 | }, 240 | { 241 | "startIndex": 831, 242 | "endIndex": 895, 243 | "paragraph": { 244 | "elements": [ 245 | { 246 | "startIndex": 831, 247 | "endIndex": 875, 248 | "textRun": { 249 | "content": "This is a paragraph after the H2. This is a ", 250 | "textStyle": {} 251 | } 252 | }, 253 | { 254 | "startIndex": 875, 255 | "endIndex": 879, 256 | "textRun": { 257 | "content": "link", 258 | "textStyle": { 259 | "underline": true, 260 | "foregroundColor": { 261 | "color": { 262 | "rgbColor": { 263 | "red": 0.06666667, 264 | "green": 0.33333334, 265 | "blue": 0.8 266 | } 267 | } 268 | }, 269 | "link": { "url": "https://anandchowdhary.com" } 270 | } 271 | } 272 | }, 273 | { 274 | "startIndex": 879, 275 | "endIndex": 893, 276 | "textRun": { "content": " to my website", "textStyle": {} } 277 | }, 278 | { 279 | "startIndex": 893, 280 | "endIndex": 895, 281 | "textRun": { "content": ".\n", "textStyle": {} } 282 | } 283 | ], 284 | "paragraphStyle": { 285 | "namedStyleType": "NORMAL_TEXT", 286 | "direction": "LEFT_TO_RIGHT" 287 | } 288 | } 289 | }, 290 | { 291 | "startIndex": 895, 292 | "endIndex": 934, 293 | "paragraph": { 294 | "elements": [ 295 | { 296 | "startIndex": 895, 297 | "endIndex": 934, 298 | "textRun": { 299 | "content": "This is a numbered list counting items\n", 300 | "textStyle": {} 301 | } 302 | } 303 | ], 304 | "paragraphStyle": { 305 | "namedStyleType": "NORMAL_TEXT", 306 | "direction": "LEFT_TO_RIGHT", 307 | "spacingMode": "COLLAPSE_LISTS", 308 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 309 | "indentStart": { "magnitude": 36, "unit": "PT" } 310 | }, 311 | "bullet": { 312 | "listId": "kix.b6sdo3eie87", 313 | "textStyle": { "underline": false } 314 | } 315 | } 316 | }, 317 | { 318 | "startIndex": 934, 319 | "endIndex": 966, 320 | "paragraph": { 321 | "elements": [ 322 | { 323 | "startIndex": 934, 324 | "endIndex": 956, 325 | "textRun": { 326 | "content": "The second item has a ", 327 | "textStyle": {} 328 | } 329 | }, 330 | { 331 | "startIndex": 956, 332 | "endIndex": 960, 333 | "textRun": { "content": "bold", "textStyle": { "bold": true } } 334 | }, 335 | { 336 | "startIndex": 960, 337 | "endIndex": 966, 338 | "textRun": { "content": " word\n", "textStyle": {} } 339 | } 340 | ], 341 | "paragraphStyle": { 342 | "namedStyleType": "NORMAL_TEXT", 343 | "direction": "LEFT_TO_RIGHT", 344 | "spacingMode": "COLLAPSE_LISTS", 345 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 346 | "indentStart": { "magnitude": 36, "unit": "PT" } 347 | }, 348 | "bullet": { 349 | "listId": "kix.b6sdo3eie87", 350 | "textStyle": { "underline": false } 351 | } 352 | } 353 | }, 354 | { 355 | "startIndex": 966, 356 | "endIndex": 997, 357 | "paragraph": { 358 | "elements": [ 359 | { 360 | "startIndex": 966, 361 | "endIndex": 997, 362 | "textRun": { 363 | "content": "The third one is right aligned\n", 364 | "textStyle": {} 365 | } 366 | } 367 | ], 368 | "paragraphStyle": { 369 | "namedStyleType": "NORMAL_TEXT", 370 | "alignment": "END", 371 | "direction": "LEFT_TO_RIGHT", 372 | "spacingMode": "COLLAPSE_LISTS", 373 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 374 | "indentStart": { "magnitude": 36, "unit": "PT" } 375 | }, 376 | "bullet": { 377 | "listId": "kix.b6sdo3eie87", 378 | "textStyle": { "underline": false } 379 | } 380 | } 381 | }, 382 | { 383 | "startIndex": 997, 384 | "endIndex": 1241, 385 | "paragraph": { 386 | "elements": [ 387 | { 388 | "startIndex": 997, 389 | "endIndex": 1241, 390 | "textRun": { 391 | "content": "Suspendisse at magna nec sapien consectetur interdum ac ac felis. Sed maximus felis leo, vitae gravida tortor molestie eget. Aliquam vehicula magna ipsum, ac tristique erat accumsan sit amet. Ut porta magna nulla, sed iaculis ex vestibulum in.\n", 392 | "textStyle": {} 393 | } 394 | } 395 | ], 396 | "paragraphStyle": { 397 | "namedStyleType": "NORMAL_TEXT", 398 | "alignment": "START", 399 | "direction": "LEFT_TO_RIGHT" 400 | } 401 | } 402 | }, 403 | { 404 | "startIndex": 1241, 405 | "endIndex": 1276, 406 | "paragraph": { 407 | "elements": [ 408 | { 409 | "startIndex": 1241, 410 | "endIndex": 1276, 411 | "textRun": { 412 | "content": "This is a normal list with hyphens\n", 413 | "textStyle": {} 414 | } 415 | } 416 | ], 417 | "paragraphStyle": { 418 | "namedStyleType": "NORMAL_TEXT", 419 | "alignment": "START", 420 | "direction": "LEFT_TO_RIGHT", 421 | "spacingMode": "COLLAPSE_LISTS", 422 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 423 | "indentStart": { "magnitude": 36, "unit": "PT" } 424 | }, 425 | "bullet": { 426 | "listId": "kix.4zcevdmk74q1", 427 | "textStyle": { "underline": false } 428 | } 429 | } 430 | }, 431 | { 432 | "startIndex": 1276, 433 | "endIndex": 1290, 434 | "paragraph": { 435 | "elements": [ 436 | { 437 | "startIndex": 1276, 438 | "endIndex": 1290, 439 | "textRun": { "content": "It has levels\n", "textStyle": {} } 440 | } 441 | ], 442 | "paragraphStyle": { 443 | "namedStyleType": "NORMAL_TEXT", 444 | "alignment": "START", 445 | "direction": "LEFT_TO_RIGHT", 446 | "spacingMode": "COLLAPSE_LISTS", 447 | "indentFirstLine": { "magnitude": 54, "unit": "PT" }, 448 | "indentStart": { "magnitude": 72, "unit": "PT" } 449 | }, 450 | "bullet": { 451 | "listId": "kix.4zcevdmk74q1", 452 | "nestingLevel": 1, 453 | "textStyle": { "underline": false } 454 | } 455 | } 456 | }, 457 | { 458 | "startIndex": 1290, 459 | "endIndex": 1302, 460 | "paragraph": { 461 | "elements": [ 462 | { 463 | "startIndex": 1290, 464 | "endIndex": 1302, 465 | "textRun": { "content": "Many levels\n", "textStyle": {} } 466 | } 467 | ], 468 | "paragraphStyle": { 469 | "namedStyleType": "NORMAL_TEXT", 470 | "alignment": "START", 471 | "direction": "LEFT_TO_RIGHT", 472 | "spacingMode": "COLLAPSE_LISTS", 473 | "indentFirstLine": { "magnitude": 90, "unit": "PT" }, 474 | "indentStart": { "magnitude": 108, "unit": "PT" } 475 | }, 476 | "bullet": { 477 | "listId": "kix.4zcevdmk74q1", 478 | "nestingLevel": 2, 479 | "textStyle": { "underline": false } 480 | } 481 | } 482 | }, 483 | { 484 | "startIndex": 1302, 485 | "endIndex": 1316, 486 | "paragraph": { 487 | "elements": [ 488 | { 489 | "startIndex": 1302, 490 | "endIndex": 1316, 491 | "textRun": { "content": "Not that many\n", "textStyle": {} } 492 | } 493 | ], 494 | "paragraphStyle": { 495 | "namedStyleType": "NORMAL_TEXT", 496 | "alignment": "START", 497 | "direction": "LEFT_TO_RIGHT", 498 | "spacingMode": "COLLAPSE_LISTS", 499 | "indentFirstLine": { "magnitude": 54, "unit": "PT" }, 500 | "indentStart": { "magnitude": 72, "unit": "PT" } 501 | }, 502 | "bullet": { 503 | "listId": "kix.4zcevdmk74q1", 504 | "nestingLevel": 1, 505 | "textStyle": { "underline": false } 506 | } 507 | } 508 | }, 509 | { 510 | "startIndex": 1316, 511 | "endIndex": 1323, 512 | "paragraph": { 513 | "elements": [ 514 | { 515 | "startIndex": 1316, 516 | "endIndex": 1323, 517 | "textRun": { "content": "Levels\n", "textStyle": {} } 518 | } 519 | ], 520 | "paragraphStyle": { 521 | "namedStyleType": "NORMAL_TEXT", 522 | "alignment": "START", 523 | "direction": "LEFT_TO_RIGHT", 524 | "spacingMode": "COLLAPSE_LISTS", 525 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 526 | "indentStart": { "magnitude": 36, "unit": "PT" } 527 | }, 528 | "bullet": { 529 | "listId": "kix.4zcevdmk74q1", 530 | "textStyle": { "underline": false } 531 | } 532 | } 533 | }, 534 | { 535 | "startIndex": 1323, 536 | "endIndex": 1694, 537 | "paragraph": { 538 | "elements": [ 539 | { 540 | "startIndex": 1323, 541 | "endIndex": 1694, 542 | "textRun": { 543 | "content": "Integer elementum massa elit, eu gravida orci sodales eget. Mauris vestibulum libero a ex cursus gravida. Praesent auctor finibus sem, sed lobortis arcu. Aliquam vitae varius dui. Donec vitae massa pellentesque, imperdiet dolor in, tincidunt ipsum. Donec viverra, diam at tincidunt suscipit, libero dolor maximus quam, eu bibendum magna massa at quam. In non urna ipsum.\n", 544 | "textStyle": {} 545 | } 546 | } 547 | ], 548 | "paragraphStyle": { 549 | "namedStyleType": "NORMAL_TEXT", 550 | "direction": "LEFT_TO_RIGHT" 551 | } 552 | } 553 | }, 554 | { 555 | "startIndex": 1694, 556 | "endIndex": 1725, 557 | "paragraph": { 558 | "elements": [ 559 | { 560 | "startIndex": 1694, 561 | "endIndex": 1724, 562 | "textRun": { 563 | "content": "This is H3, with a table below", 564 | "textStyle": {} 565 | } 566 | }, 567 | { 568 | "startIndex": 1724, 569 | "endIndex": 1725, 570 | "textRun": { "content": "\n", "textStyle": {} } 571 | } 572 | ], 573 | "paragraphStyle": { 574 | "headingId": "h.ij2r1dmmvrgv", 575 | "namedStyleType": "HEADING_3", 576 | "direction": "LEFT_TO_RIGHT" 577 | } 578 | } 579 | }, 580 | { 581 | "startIndex": 1725, 582 | "endIndex": 1834, 583 | "table": { 584 | "rows": 4, 585 | "columns": 2, 586 | "tableRows": [ 587 | { 588 | "startIndex": 1726, 589 | "endIndex": 1741, 590 | "tableCells": [ 591 | { 592 | "startIndex": 1727, 593 | "endIndex": 1735, 594 | "content": [ 595 | { 596 | "startIndex": 1728, 597 | "endIndex": 1735, 598 | "paragraph": { 599 | "elements": [ 600 | { 601 | "startIndex": 1728, 602 | "endIndex": 1735, 603 | "textRun": { 604 | "content": "S. No.\n", 605 | "textStyle": { "bold": true } 606 | } 607 | } 608 | ], 609 | "paragraphStyle": { 610 | "namedStyleType": "NORMAL_TEXT", 611 | "alignment": "START", 612 | "lineSpacing": 100, 613 | "direction": "LEFT_TO_RIGHT", 614 | "spacingMode": "COLLAPSE_LISTS", 615 | "spaceAbove": { "unit": "PT" }, 616 | "spaceBelow": { "unit": "PT" }, 617 | "borderBetween": { 618 | "color": {}, 619 | "width": { "unit": "PT" }, 620 | "padding": { "unit": "PT" }, 621 | "dashStyle": "SOLID" 622 | }, 623 | "borderTop": { 624 | "color": {}, 625 | "width": { "unit": "PT" }, 626 | "padding": { "unit": "PT" }, 627 | "dashStyle": "SOLID" 628 | }, 629 | "borderBottom": { 630 | "color": {}, 631 | "width": { "unit": "PT" }, 632 | "padding": { "unit": "PT" }, 633 | "dashStyle": "SOLID" 634 | }, 635 | "borderLeft": { 636 | "color": {}, 637 | "width": { "unit": "PT" }, 638 | "padding": { "unit": "PT" }, 639 | "dashStyle": "SOLID" 640 | }, 641 | "borderRight": { 642 | "color": {}, 643 | "width": { "unit": "PT" }, 644 | "padding": { "unit": "PT" }, 645 | "dashStyle": "SOLID" 646 | }, 647 | "indentFirstLine": { "unit": "PT" }, 648 | "indentStart": { "unit": "PT" }, 649 | "indentEnd": { "unit": "PT" }, 650 | "keepLinesTogether": false, 651 | "keepWithNext": false, 652 | "avoidWidowAndOrphan": false, 653 | "shading": { "backgroundColor": {} } 654 | } 655 | } 656 | } 657 | ], 658 | "tableCellStyle": { 659 | "rowSpan": 1, 660 | "columnSpan": 1, 661 | "backgroundColor": {}, 662 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 663 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 664 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 665 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 666 | "contentAlignment": "TOP" 667 | } 668 | }, 669 | { 670 | "startIndex": 1735, 671 | "endIndex": 1741, 672 | "content": [ 673 | { 674 | "startIndex": 1736, 675 | "endIndex": 1741, 676 | "paragraph": { 677 | "elements": [ 678 | { 679 | "startIndex": 1736, 680 | "endIndex": 1741, 681 | "textRun": { 682 | "content": "Name\n", 683 | "textStyle": { "bold": true } 684 | } 685 | } 686 | ], 687 | "paragraphStyle": { 688 | "namedStyleType": "NORMAL_TEXT", 689 | "alignment": "START", 690 | "lineSpacing": 100, 691 | "direction": "LEFT_TO_RIGHT", 692 | "spacingMode": "COLLAPSE_LISTS", 693 | "spaceAbove": { "unit": "PT" }, 694 | "spaceBelow": { "unit": "PT" }, 695 | "borderBetween": { 696 | "color": {}, 697 | "width": { "unit": "PT" }, 698 | "padding": { "unit": "PT" }, 699 | "dashStyle": "SOLID" 700 | }, 701 | "borderTop": { 702 | "color": {}, 703 | "width": { "unit": "PT" }, 704 | "padding": { "unit": "PT" }, 705 | "dashStyle": "SOLID" 706 | }, 707 | "borderBottom": { 708 | "color": {}, 709 | "width": { "unit": "PT" }, 710 | "padding": { "unit": "PT" }, 711 | "dashStyle": "SOLID" 712 | }, 713 | "borderLeft": { 714 | "color": {}, 715 | "width": { "unit": "PT" }, 716 | "padding": { "unit": "PT" }, 717 | "dashStyle": "SOLID" 718 | }, 719 | "borderRight": { 720 | "color": {}, 721 | "width": { "unit": "PT" }, 722 | "padding": { "unit": "PT" }, 723 | "dashStyle": "SOLID" 724 | }, 725 | "indentFirstLine": { "unit": "PT" }, 726 | "indentStart": { "unit": "PT" }, 727 | "indentEnd": { "unit": "PT" }, 728 | "keepLinesTogether": false, 729 | "keepWithNext": false, 730 | "avoidWidowAndOrphan": false, 731 | "shading": { "backgroundColor": {} } 732 | } 733 | } 734 | } 735 | ], 736 | "tableCellStyle": { 737 | "rowSpan": 1, 738 | "columnSpan": 1, 739 | "backgroundColor": {}, 740 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 741 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 742 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 743 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 744 | "contentAlignment": "TOP" 745 | } 746 | } 747 | ], 748 | "tableRowStyle": { "minRowHeight": { "unit": "PT" } } 749 | }, 750 | { 751 | "startIndex": 1741, 752 | "endIndex": 1791, 753 | "tableCells": [ 754 | { 755 | "startIndex": 1742, 756 | "endIndex": 1745, 757 | "content": [ 758 | { 759 | "startIndex": 1743, 760 | "endIndex": 1745, 761 | "paragraph": { 762 | "elements": [ 763 | { 764 | "startIndex": 1743, 765 | "endIndex": 1745, 766 | "textRun": { "content": "1\n", "textStyle": {} } 767 | } 768 | ], 769 | "paragraphStyle": { 770 | "namedStyleType": "NORMAL_TEXT", 771 | "alignment": "START", 772 | "lineSpacing": 100, 773 | "direction": "LEFT_TO_RIGHT", 774 | "spacingMode": "COLLAPSE_LISTS", 775 | "spaceAbove": { "unit": "PT" }, 776 | "spaceBelow": { "unit": "PT" }, 777 | "borderBetween": { 778 | "color": {}, 779 | "width": { "unit": "PT" }, 780 | "padding": { "unit": "PT" }, 781 | "dashStyle": "SOLID" 782 | }, 783 | "borderTop": { 784 | "color": {}, 785 | "width": { "unit": "PT" }, 786 | "padding": { "unit": "PT" }, 787 | "dashStyle": "SOLID" 788 | }, 789 | "borderBottom": { 790 | "color": {}, 791 | "width": { "unit": "PT" }, 792 | "padding": { "unit": "PT" }, 793 | "dashStyle": "SOLID" 794 | }, 795 | "borderLeft": { 796 | "color": {}, 797 | "width": { "unit": "PT" }, 798 | "padding": { "unit": "PT" }, 799 | "dashStyle": "SOLID" 800 | }, 801 | "borderRight": { 802 | "color": {}, 803 | "width": { "unit": "PT" }, 804 | "padding": { "unit": "PT" }, 805 | "dashStyle": "SOLID" 806 | }, 807 | "indentFirstLine": { "unit": "PT" }, 808 | "indentStart": { "unit": "PT" }, 809 | "indentEnd": { "unit": "PT" }, 810 | "keepLinesTogether": false, 811 | "keepWithNext": false, 812 | "avoidWidowAndOrphan": false, 813 | "shading": { "backgroundColor": {} } 814 | } 815 | } 816 | } 817 | ], 818 | "tableCellStyle": { 819 | "rowSpan": 1, 820 | "columnSpan": 1, 821 | "backgroundColor": {}, 822 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 823 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 824 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 825 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 826 | "contentAlignment": "TOP" 827 | } 828 | }, 829 | { 830 | "startIndex": 1745, 831 | "endIndex": 1791, 832 | "content": [ 833 | { 834 | "startIndex": 1746, 835 | "endIndex": 1791, 836 | "paragraph": { 837 | "elements": [ 838 | { 839 | "startIndex": 1746, 840 | "endIndex": 1791, 841 | "textRun": { 842 | "content": "This column is much wider than the first one\n", 843 | "textStyle": {} 844 | } 845 | } 846 | ], 847 | "paragraphStyle": { 848 | "namedStyleType": "NORMAL_TEXT", 849 | "alignment": "START", 850 | "lineSpacing": 100, 851 | "direction": "LEFT_TO_RIGHT", 852 | "spacingMode": "COLLAPSE_LISTS", 853 | "spaceAbove": { "unit": "PT" }, 854 | "spaceBelow": { "unit": "PT" }, 855 | "borderBetween": { 856 | "color": {}, 857 | "width": { "unit": "PT" }, 858 | "padding": { "unit": "PT" }, 859 | "dashStyle": "SOLID" 860 | }, 861 | "borderTop": { 862 | "color": {}, 863 | "width": { "unit": "PT" }, 864 | "padding": { "unit": "PT" }, 865 | "dashStyle": "SOLID" 866 | }, 867 | "borderBottom": { 868 | "color": {}, 869 | "width": { "unit": "PT" }, 870 | "padding": { "unit": "PT" }, 871 | "dashStyle": "SOLID" 872 | }, 873 | "borderLeft": { 874 | "color": {}, 875 | "width": { "unit": "PT" }, 876 | "padding": { "unit": "PT" }, 877 | "dashStyle": "SOLID" 878 | }, 879 | "borderRight": { 880 | "color": {}, 881 | "width": { "unit": "PT" }, 882 | "padding": { "unit": "PT" }, 883 | "dashStyle": "SOLID" 884 | }, 885 | "indentFirstLine": { "unit": "PT" }, 886 | "indentStart": { "unit": "PT" }, 887 | "indentEnd": { "unit": "PT" }, 888 | "keepLinesTogether": false, 889 | "keepWithNext": false, 890 | "avoidWidowAndOrphan": false, 891 | "shading": { "backgroundColor": {} } 892 | } 893 | } 894 | } 895 | ], 896 | "tableCellStyle": { 897 | "rowSpan": 1, 898 | "columnSpan": 1, 899 | "backgroundColor": {}, 900 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 901 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 902 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 903 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 904 | "contentAlignment": "TOP" 905 | } 906 | } 907 | ], 908 | "tableRowStyle": { "minRowHeight": { "unit": "PT" } } 909 | }, 910 | { 911 | "startIndex": 1791, 912 | "endIndex": 1827, 913 | "tableCells": [ 914 | { 915 | "startIndex": 1792, 916 | "endIndex": 1795, 917 | "content": [ 918 | { 919 | "startIndex": 1793, 920 | "endIndex": 1795, 921 | "paragraph": { 922 | "elements": [ 923 | { 924 | "startIndex": 1793, 925 | "endIndex": 1795, 926 | "textRun": { "content": "2\n", "textStyle": {} } 927 | } 928 | ], 929 | "paragraphStyle": { 930 | "namedStyleType": "NORMAL_TEXT", 931 | "alignment": "START", 932 | "lineSpacing": 100, 933 | "direction": "LEFT_TO_RIGHT", 934 | "spacingMode": "COLLAPSE_LISTS", 935 | "spaceAbove": { "unit": "PT" }, 936 | "spaceBelow": { "unit": "PT" }, 937 | "borderBetween": { 938 | "color": {}, 939 | "width": { "unit": "PT" }, 940 | "padding": { "unit": "PT" }, 941 | "dashStyle": "SOLID" 942 | }, 943 | "borderTop": { 944 | "color": {}, 945 | "width": { "unit": "PT" }, 946 | "padding": { "unit": "PT" }, 947 | "dashStyle": "SOLID" 948 | }, 949 | "borderBottom": { 950 | "color": {}, 951 | "width": { "unit": "PT" }, 952 | "padding": { "unit": "PT" }, 953 | "dashStyle": "SOLID" 954 | }, 955 | "borderLeft": { 956 | "color": {}, 957 | "width": { "unit": "PT" }, 958 | "padding": { "unit": "PT" }, 959 | "dashStyle": "SOLID" 960 | }, 961 | "borderRight": { 962 | "color": {}, 963 | "width": { "unit": "PT" }, 964 | "padding": { "unit": "PT" }, 965 | "dashStyle": "SOLID" 966 | }, 967 | "indentFirstLine": { "unit": "PT" }, 968 | "indentStart": { "unit": "PT" }, 969 | "indentEnd": { "unit": "PT" }, 970 | "keepLinesTogether": false, 971 | "keepWithNext": false, 972 | "avoidWidowAndOrphan": false, 973 | "shading": { "backgroundColor": {} } 974 | } 975 | } 976 | } 977 | ], 978 | "tableCellStyle": { 979 | "rowSpan": 1, 980 | "columnSpan": 1, 981 | "backgroundColor": {}, 982 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 983 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 984 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 985 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 986 | "contentAlignment": "TOP" 987 | } 988 | }, 989 | { 990 | "startIndex": 1795, 991 | "endIndex": 1827, 992 | "content": [ 993 | { 994 | "startIndex": 1796, 995 | "endIndex": 1827, 996 | "paragraph": { 997 | "elements": [ 998 | { 999 | "startIndex": 1796, 1000 | "endIndex": 1827, 1001 | "textRun": { 1002 | "content": "The column below this is empty\n", 1003 | "textStyle": {} 1004 | } 1005 | } 1006 | ], 1007 | "paragraphStyle": { 1008 | "namedStyleType": "NORMAL_TEXT", 1009 | "alignment": "START", 1010 | "lineSpacing": 100, 1011 | "direction": "LEFT_TO_RIGHT", 1012 | "spacingMode": "COLLAPSE_LISTS", 1013 | "spaceAbove": { "unit": "PT" }, 1014 | "spaceBelow": { "unit": "PT" }, 1015 | "borderBetween": { 1016 | "color": {}, 1017 | "width": { "unit": "PT" }, 1018 | "padding": { "unit": "PT" }, 1019 | "dashStyle": "SOLID" 1020 | }, 1021 | "borderTop": { 1022 | "color": {}, 1023 | "width": { "unit": "PT" }, 1024 | "padding": { "unit": "PT" }, 1025 | "dashStyle": "SOLID" 1026 | }, 1027 | "borderBottom": { 1028 | "color": {}, 1029 | "width": { "unit": "PT" }, 1030 | "padding": { "unit": "PT" }, 1031 | "dashStyle": "SOLID" 1032 | }, 1033 | "borderLeft": { 1034 | "color": {}, 1035 | "width": { "unit": "PT" }, 1036 | "padding": { "unit": "PT" }, 1037 | "dashStyle": "SOLID" 1038 | }, 1039 | "borderRight": { 1040 | "color": {}, 1041 | "width": { "unit": "PT" }, 1042 | "padding": { "unit": "PT" }, 1043 | "dashStyle": "SOLID" 1044 | }, 1045 | "indentFirstLine": { "unit": "PT" }, 1046 | "indentStart": { "unit": "PT" }, 1047 | "indentEnd": { "unit": "PT" }, 1048 | "keepLinesTogether": false, 1049 | "keepWithNext": false, 1050 | "avoidWidowAndOrphan": false, 1051 | "shading": { "backgroundColor": {} } 1052 | } 1053 | } 1054 | } 1055 | ], 1056 | "tableCellStyle": { 1057 | "rowSpan": 1, 1058 | "columnSpan": 1, 1059 | "backgroundColor": {}, 1060 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 1061 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 1062 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 1063 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 1064 | "contentAlignment": "TOP" 1065 | } 1066 | } 1067 | ], 1068 | "tableRowStyle": { "minRowHeight": { "unit": "PT" } } 1069 | }, 1070 | { 1071 | "startIndex": 1827, 1072 | "endIndex": 1833, 1073 | "tableCells": [ 1074 | { 1075 | "startIndex": 1828, 1076 | "endIndex": 1831, 1077 | "content": [ 1078 | { 1079 | "startIndex": 1829, 1080 | "endIndex": 1831, 1081 | "paragraph": { 1082 | "elements": [ 1083 | { 1084 | "startIndex": 1829, 1085 | "endIndex": 1831, 1086 | "textRun": { "content": "3\n", "textStyle": {} } 1087 | } 1088 | ], 1089 | "paragraphStyle": { 1090 | "namedStyleType": "NORMAL_TEXT", 1091 | "alignment": "START", 1092 | "lineSpacing": 100, 1093 | "direction": "LEFT_TO_RIGHT", 1094 | "spacingMode": "COLLAPSE_LISTS", 1095 | "spaceAbove": { "unit": "PT" }, 1096 | "spaceBelow": { "unit": "PT" }, 1097 | "borderBetween": { 1098 | "color": {}, 1099 | "width": { "unit": "PT" }, 1100 | "padding": { "unit": "PT" }, 1101 | "dashStyle": "SOLID" 1102 | }, 1103 | "borderTop": { 1104 | "color": {}, 1105 | "width": { "unit": "PT" }, 1106 | "padding": { "unit": "PT" }, 1107 | "dashStyle": "SOLID" 1108 | }, 1109 | "borderBottom": { 1110 | "color": {}, 1111 | "width": { "unit": "PT" }, 1112 | "padding": { "unit": "PT" }, 1113 | "dashStyle": "SOLID" 1114 | }, 1115 | "borderLeft": { 1116 | "color": {}, 1117 | "width": { "unit": "PT" }, 1118 | "padding": { "unit": "PT" }, 1119 | "dashStyle": "SOLID" 1120 | }, 1121 | "borderRight": { 1122 | "color": {}, 1123 | "width": { "unit": "PT" }, 1124 | "padding": { "unit": "PT" }, 1125 | "dashStyle": "SOLID" 1126 | }, 1127 | "indentFirstLine": { "unit": "PT" }, 1128 | "indentStart": { "unit": "PT" }, 1129 | "indentEnd": { "unit": "PT" }, 1130 | "keepLinesTogether": false, 1131 | "keepWithNext": false, 1132 | "avoidWidowAndOrphan": false, 1133 | "shading": { "backgroundColor": {} } 1134 | } 1135 | } 1136 | } 1137 | ], 1138 | "tableCellStyle": { 1139 | "rowSpan": 1, 1140 | "columnSpan": 1, 1141 | "backgroundColor": {}, 1142 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 1143 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 1144 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 1145 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 1146 | "contentAlignment": "TOP" 1147 | } 1148 | }, 1149 | { 1150 | "startIndex": 1831, 1151 | "endIndex": 1833, 1152 | "content": [ 1153 | { 1154 | "startIndex": 1832, 1155 | "endIndex": 1833, 1156 | "paragraph": { 1157 | "elements": [ 1158 | { 1159 | "startIndex": 1832, 1160 | "endIndex": 1833, 1161 | "textRun": { "content": "\n", "textStyle": {} } 1162 | } 1163 | ], 1164 | "paragraphStyle": { 1165 | "namedStyleType": "NORMAL_TEXT", 1166 | "alignment": "START", 1167 | "lineSpacing": 100, 1168 | "direction": "LEFT_TO_RIGHT", 1169 | "spacingMode": "COLLAPSE_LISTS", 1170 | "spaceAbove": { "unit": "PT" }, 1171 | "spaceBelow": { "unit": "PT" }, 1172 | "borderBetween": { 1173 | "color": {}, 1174 | "width": { "unit": "PT" }, 1175 | "padding": { "unit": "PT" }, 1176 | "dashStyle": "SOLID" 1177 | }, 1178 | "borderTop": { 1179 | "color": {}, 1180 | "width": { "unit": "PT" }, 1181 | "padding": { "unit": "PT" }, 1182 | "dashStyle": "SOLID" 1183 | }, 1184 | "borderBottom": { 1185 | "color": {}, 1186 | "width": { "unit": "PT" }, 1187 | "padding": { "unit": "PT" }, 1188 | "dashStyle": "SOLID" 1189 | }, 1190 | "borderLeft": { 1191 | "color": {}, 1192 | "width": { "unit": "PT" }, 1193 | "padding": { "unit": "PT" }, 1194 | "dashStyle": "SOLID" 1195 | }, 1196 | "borderRight": { 1197 | "color": {}, 1198 | "width": { "unit": "PT" }, 1199 | "padding": { "unit": "PT" }, 1200 | "dashStyle": "SOLID" 1201 | }, 1202 | "indentFirstLine": { "unit": "PT" }, 1203 | "indentStart": { "unit": "PT" }, 1204 | "indentEnd": { "unit": "PT" }, 1205 | "keepLinesTogether": false, 1206 | "keepWithNext": false, 1207 | "avoidWidowAndOrphan": false, 1208 | "shading": { "backgroundColor": {} } 1209 | } 1210 | } 1211 | } 1212 | ], 1213 | "tableCellStyle": { 1214 | "rowSpan": 1, 1215 | "columnSpan": 1, 1216 | "backgroundColor": {}, 1217 | "paddingLeft": { "magnitude": 5, "unit": "PT" }, 1218 | "paddingRight": { "magnitude": 5, "unit": "PT" }, 1219 | "paddingTop": { "magnitude": 5, "unit": "PT" }, 1220 | "paddingBottom": { "magnitude": 5, "unit": "PT" }, 1221 | "contentAlignment": "TOP" 1222 | } 1223 | } 1224 | ], 1225 | "tableRowStyle": { "minRowHeight": { "unit": "PT" } } 1226 | } 1227 | ], 1228 | "tableStyle": { 1229 | "tableColumnProperties": [ 1230 | { 1231 | "widthType": "FIXED_WIDTH", 1232 | "width": { "magnitude": 79.5, "unit": "PT" } 1233 | }, 1234 | { 1235 | "widthType": "FIXED_WIDTH", 1236 | "width": { "magnitude": 388.5, "unit": "PT" } 1237 | } 1238 | ] 1239 | } 1240 | } 1241 | }, 1242 | { 1243 | "startIndex": 1834, 1244 | "endIndex": 1853, 1245 | "paragraph": { 1246 | "elements": [ 1247 | { 1248 | "startIndex": 1834, 1249 | "endIndex": 1852, 1250 | "textRun": { 1251 | "content": "That’s all, folks!", 1252 | "textStyle": { "italic": true } 1253 | } 1254 | }, 1255 | { 1256 | "startIndex": 1852, 1257 | "endIndex": 1853, 1258 | "textRun": { "content": "\n", "textStyle": { "italic": true } } 1259 | } 1260 | ], 1261 | "paragraphStyle": { 1262 | "namedStyleType": "NORMAL_TEXT", 1263 | "direction": "LEFT_TO_RIGHT" 1264 | } 1265 | } 1266 | }, 1267 | { 1268 | "startIndex": 1853, 1269 | "endIndex": 1854, 1270 | "paragraph": { 1271 | "elements": [ 1272 | { 1273 | "startIndex": 1853, 1274 | "endIndex": 1854, 1275 | "textRun": { "content": "\n", "textStyle": {} } 1276 | } 1277 | ], 1278 | "paragraphStyle": { 1279 | "namedStyleType": "NORMAL_TEXT", 1280 | "alignment": "START", 1281 | "direction": "LEFT_TO_RIGHT" 1282 | } 1283 | } 1284 | } 1285 | ] 1286 | }, 1287 | "documentStyle": { 1288 | "background": { "color": {} }, 1289 | "pageNumberStart": 1, 1290 | "marginTop": { "magnitude": 72, "unit": "PT" }, 1291 | "marginBottom": { "magnitude": 72, "unit": "PT" }, 1292 | "marginRight": { "magnitude": 72, "unit": "PT" }, 1293 | "marginLeft": { "magnitude": 72, "unit": "PT" }, 1294 | "pageSize": { 1295 | "height": { "magnitude": 792, "unit": "PT" }, 1296 | "width": { "magnitude": 612, "unit": "PT" } 1297 | }, 1298 | "marginHeader": { "magnitude": 36, "unit": "PT" }, 1299 | "marginFooter": { "magnitude": 36, "unit": "PT" }, 1300 | "useCustomHeaderFooterMargins": true 1301 | }, 1302 | "namedStyles": { 1303 | "styles": [ 1304 | { 1305 | "namedStyleType": "NORMAL_TEXT", 1306 | "textStyle": { 1307 | "bold": false, 1308 | "italic": false, 1309 | "underline": false, 1310 | "strikethrough": false, 1311 | "smallCaps": false, 1312 | "backgroundColor": {}, 1313 | "foregroundColor": { "color": { "rgbColor": {} } }, 1314 | "fontSize": { "magnitude": 12, "unit": "PT" }, 1315 | "weightedFontFamily": { "fontFamily": "Proxima Nova", "weight": 400 }, 1316 | "baselineOffset": "NONE" 1317 | }, 1318 | "paragraphStyle": { 1319 | "namedStyleType": "NORMAL_TEXT", 1320 | "alignment": "START", 1321 | "lineSpacing": 130, 1322 | "direction": "LEFT_TO_RIGHT", 1323 | "spacingMode": "NEVER_COLLAPSE", 1324 | "spaceAbove": { "magnitude": 10, "unit": "PT" }, 1325 | "spaceBelow": { "unit": "PT" }, 1326 | "borderBetween": { 1327 | "color": {}, 1328 | "width": { "unit": "PT" }, 1329 | "padding": { "unit": "PT" }, 1330 | "dashStyle": "SOLID" 1331 | }, 1332 | "borderTop": { 1333 | "color": {}, 1334 | "width": { "unit": "PT" }, 1335 | "padding": { "unit": "PT" }, 1336 | "dashStyle": "SOLID" 1337 | }, 1338 | "borderBottom": { 1339 | "color": {}, 1340 | "width": { "unit": "PT" }, 1341 | "padding": { "unit": "PT" }, 1342 | "dashStyle": "SOLID" 1343 | }, 1344 | "borderLeft": { 1345 | "color": {}, 1346 | "width": { "unit": "PT" }, 1347 | "padding": { "unit": "PT" }, 1348 | "dashStyle": "SOLID" 1349 | }, 1350 | "borderRight": { 1351 | "color": {}, 1352 | "width": { "unit": "PT" }, 1353 | "padding": { "unit": "PT" }, 1354 | "dashStyle": "SOLID" 1355 | }, 1356 | "indentFirstLine": { "unit": "PT" }, 1357 | "indentStart": { "unit": "PT" }, 1358 | "indentEnd": { "unit": "PT" }, 1359 | "keepLinesTogether": false, 1360 | "keepWithNext": false, 1361 | "avoidWidowAndOrphan": true, 1362 | "shading": { "backgroundColor": {} } 1363 | } 1364 | }, 1365 | { 1366 | "namedStyleType": "HEADING_1", 1367 | "textStyle": { "fontSize": { "magnitude": 18, "unit": "PT" } }, 1368 | "paragraphStyle": { 1369 | "headingId": "h.wb48ixm84oyf", 1370 | "namedStyleType": "HEADING_1", 1371 | "direction": "LEFT_TO_RIGHT" 1372 | } 1373 | }, 1374 | { 1375 | "namedStyleType": "HEADING_2", 1376 | "textStyle": { 1377 | "bold": true, 1378 | "fontSize": { "magnitude": 13, "unit": "PT" } 1379 | }, 1380 | "paragraphStyle": { 1381 | "headingId": "h.dvt9xtq0xyj9", 1382 | "namedStyleType": "HEADING_2", 1383 | "lineSpacing": 115, 1384 | "direction": "LEFT_TO_RIGHT", 1385 | "spaceAbove": { "magnitude": 20, "unit": "PT" } 1386 | } 1387 | }, 1388 | { 1389 | "namedStyleType": "HEADING_3", 1390 | "textStyle": { 1391 | "bold": true, 1392 | "foregroundColor": { 1393 | "color": { 1394 | "rgbColor": { 1395 | "red": 0.54901963, 1396 | "green": 0.44705883, 1397 | "blue": 0.32156864 1398 | } 1399 | } 1400 | }, 1401 | "fontSize": { "magnitude": 12, "unit": "PT" } 1402 | }, 1403 | "paragraphStyle": { 1404 | "headingId": "h.pclrljc3kfrk", 1405 | "namedStyleType": "HEADING_3", 1406 | "direction": "LEFT_TO_RIGHT", 1407 | "indentFirstLine": { "magnitude": -0.75, "unit": "PT" }, 1408 | "indentStart": { "magnitude": -0.75, "unit": "PT" } 1409 | } 1410 | }, 1411 | { 1412 | "namedStyleType": "HEADING_4", 1413 | "textStyle": { 1414 | "underline": true, 1415 | "foregroundColor": { 1416 | "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } 1417 | }, 1418 | "fontSize": { "magnitude": 11, "unit": "PT" }, 1419 | "weightedFontFamily": { "fontFamily": "Trebuchet MS", "weight": 400 } 1420 | }, 1421 | "paragraphStyle": { 1422 | "namedStyleType": "NORMAL_TEXT", 1423 | "direction": "LEFT_TO_RIGHT", 1424 | "spaceAbove": { "magnitude": 8, "unit": "PT" }, 1425 | "spaceBelow": { "unit": "PT" }, 1426 | "keepLinesTogether": true, 1427 | "keepWithNext": true 1428 | } 1429 | }, 1430 | { 1431 | "namedStyleType": "HEADING_5", 1432 | "textStyle": { 1433 | "foregroundColor": { 1434 | "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } 1435 | }, 1436 | "fontSize": { "magnitude": 11, "unit": "PT" }, 1437 | "weightedFontFamily": { "fontFamily": "Trebuchet MS", "weight": 400 } 1438 | }, 1439 | "paragraphStyle": { 1440 | "namedStyleType": "NORMAL_TEXT", 1441 | "direction": "LEFT_TO_RIGHT", 1442 | "spaceAbove": { "magnitude": 8, "unit": "PT" }, 1443 | "spaceBelow": { "unit": "PT" }, 1444 | "keepLinesTogether": true, 1445 | "keepWithNext": true 1446 | } 1447 | }, 1448 | { 1449 | "namedStyleType": "HEADING_6", 1450 | "textStyle": { 1451 | "italic": true, 1452 | "foregroundColor": { 1453 | "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } 1454 | }, 1455 | "fontSize": { "magnitude": 11, "unit": "PT" }, 1456 | "weightedFontFamily": { "fontFamily": "Trebuchet MS", "weight": 400 } 1457 | }, 1458 | "paragraphStyle": { 1459 | "namedStyleType": "NORMAL_TEXT", 1460 | "direction": "LEFT_TO_RIGHT", 1461 | "spaceAbove": { "magnitude": 8, "unit": "PT" }, 1462 | "spaceBelow": { "unit": "PT" }, 1463 | "keepLinesTogether": true, 1464 | "keepWithNext": true 1465 | } 1466 | }, 1467 | { 1468 | "namedStyleType": "TITLE", 1469 | "textStyle": { "fontSize": { "magnitude": 24, "unit": "PT" } }, 1470 | "paragraphStyle": { 1471 | "headingId": "h.bud8aattcpbp", 1472 | "namedStyleType": "TITLE", 1473 | "lineSpacing": 100, 1474 | "direction": "LEFT_TO_RIGHT", 1475 | "spaceAbove": { "unit": "PT" }, 1476 | "spaceBelow": { "magnitude": 25, "unit": "PT" } 1477 | } 1478 | }, 1479 | { 1480 | "namedStyleType": "SUBTITLE", 1481 | "textStyle": { 1482 | "foregroundColor": { 1483 | "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } 1484 | }, 1485 | "fontSize": { "magnitude": 14, "unit": "PT" } 1486 | }, 1487 | "paragraphStyle": { 1488 | "headingId": "h.enxdv5p1e3a7", 1489 | "namedStyleType": "SUBTITLE", 1490 | "lineSpacing": 100, 1491 | "direction": "LEFT_TO_RIGHT" 1492 | } 1493 | } 1494 | ] 1495 | }, 1496 | "lists": { 1497 | "kix.4zcevdmk74q1": { 1498 | "listProperties": { 1499 | "nestingLevels": [ 1500 | { 1501 | "bulletAlignment": "START", 1502 | "glyphSymbol": "-", 1503 | "glyphFormat": "%0", 1504 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 1505 | "indentStart": { "magnitude": 36, "unit": "PT" }, 1506 | "textStyle": { "underline": false }, 1507 | "startNumber": 1 1508 | }, 1509 | { 1510 | "bulletAlignment": "START", 1511 | "glyphSymbol": "-", 1512 | "glyphFormat": "%1", 1513 | "indentFirstLine": { "magnitude": 54, "unit": "PT" }, 1514 | "indentStart": { "magnitude": 72, "unit": "PT" }, 1515 | "textStyle": { "underline": false }, 1516 | "startNumber": 1 1517 | }, 1518 | { 1519 | "bulletAlignment": "START", 1520 | "glyphSymbol": "-", 1521 | "glyphFormat": "%2", 1522 | "indentFirstLine": { "magnitude": 90, "unit": "PT" }, 1523 | "indentStart": { "magnitude": 108, "unit": "PT" }, 1524 | "textStyle": { "underline": false }, 1525 | "startNumber": 1 1526 | }, 1527 | { 1528 | "bulletAlignment": "START", 1529 | "glyphSymbol": "-", 1530 | "glyphFormat": "%3", 1531 | "indentFirstLine": { "magnitude": 126, "unit": "PT" }, 1532 | "indentStart": { "magnitude": 144, "unit": "PT" }, 1533 | "textStyle": { "underline": false }, 1534 | "startNumber": 1 1535 | }, 1536 | { 1537 | "bulletAlignment": "START", 1538 | "glyphSymbol": "-", 1539 | "glyphFormat": "%4", 1540 | "indentFirstLine": { "magnitude": 162, "unit": "PT" }, 1541 | "indentStart": { "magnitude": 180, "unit": "PT" }, 1542 | "textStyle": { "underline": false }, 1543 | "startNumber": 1 1544 | }, 1545 | { 1546 | "bulletAlignment": "START", 1547 | "glyphSymbol": "-", 1548 | "glyphFormat": "%5", 1549 | "indentFirstLine": { "magnitude": 198, "unit": "PT" }, 1550 | "indentStart": { "magnitude": 216, "unit": "PT" }, 1551 | "textStyle": { "underline": false }, 1552 | "startNumber": 1 1553 | }, 1554 | { 1555 | "bulletAlignment": "START", 1556 | "glyphSymbol": "-", 1557 | "glyphFormat": "%6", 1558 | "indentFirstLine": { "magnitude": 234, "unit": "PT" }, 1559 | "indentStart": { "magnitude": 252, "unit": "PT" }, 1560 | "textStyle": { "underline": false }, 1561 | "startNumber": 1 1562 | }, 1563 | { 1564 | "bulletAlignment": "START", 1565 | "glyphSymbol": "-", 1566 | "glyphFormat": "%7", 1567 | "indentFirstLine": { "magnitude": 270, "unit": "PT" }, 1568 | "indentStart": { "magnitude": 288, "unit": "PT" }, 1569 | "textStyle": { "underline": false }, 1570 | "startNumber": 1 1571 | }, 1572 | { 1573 | "bulletAlignment": "START", 1574 | "glyphSymbol": "-", 1575 | "glyphFormat": "%8", 1576 | "indentFirstLine": { "magnitude": 306, "unit": "PT" }, 1577 | "indentStart": { "magnitude": 324, "unit": "PT" }, 1578 | "textStyle": { "underline": false }, 1579 | "startNumber": 1 1580 | } 1581 | ] 1582 | } 1583 | }, 1584 | "kix.b6sdo3eie87": { 1585 | "listProperties": { 1586 | "nestingLevels": [ 1587 | { 1588 | "bulletAlignment": "START", 1589 | "glyphType": "DECIMAL", 1590 | "glyphFormat": "%0.", 1591 | "indentFirstLine": { "magnitude": 18, "unit": "PT" }, 1592 | "indentStart": { "magnitude": 36, "unit": "PT" }, 1593 | "textStyle": { "underline": false }, 1594 | "startNumber": 1 1595 | }, 1596 | { 1597 | "bulletAlignment": "START", 1598 | "glyphType": "ALPHA", 1599 | "glyphFormat": "%1.", 1600 | "indentFirstLine": { "magnitude": 54, "unit": "PT" }, 1601 | "indentStart": { "magnitude": 72, "unit": "PT" }, 1602 | "textStyle": { "underline": false }, 1603 | "startNumber": 1 1604 | }, 1605 | { 1606 | "bulletAlignment": "END", 1607 | "glyphType": "ROMAN", 1608 | "glyphFormat": "%2.", 1609 | "indentFirstLine": { "magnitude": 90, "unit": "PT" }, 1610 | "indentStart": { "magnitude": 108, "unit": "PT" }, 1611 | "textStyle": { "underline": false }, 1612 | "startNumber": 1 1613 | }, 1614 | { 1615 | "bulletAlignment": "START", 1616 | "glyphType": "DECIMAL", 1617 | "glyphFormat": "%3.", 1618 | "indentFirstLine": { "magnitude": 126, "unit": "PT" }, 1619 | "indentStart": { "magnitude": 144, "unit": "PT" }, 1620 | "textStyle": { "underline": false }, 1621 | "startNumber": 1 1622 | }, 1623 | { 1624 | "bulletAlignment": "START", 1625 | "glyphType": "ALPHA", 1626 | "glyphFormat": "%4.", 1627 | "indentFirstLine": { "magnitude": 162, "unit": "PT" }, 1628 | "indentStart": { "magnitude": 180, "unit": "PT" }, 1629 | "textStyle": { "underline": false }, 1630 | "startNumber": 1 1631 | }, 1632 | { 1633 | "bulletAlignment": "END", 1634 | "glyphType": "ROMAN", 1635 | "glyphFormat": "%5.", 1636 | "indentFirstLine": { "magnitude": 198, "unit": "PT" }, 1637 | "indentStart": { "magnitude": 216, "unit": "PT" }, 1638 | "textStyle": { "underline": false }, 1639 | "startNumber": 1 1640 | }, 1641 | { 1642 | "bulletAlignment": "START", 1643 | "glyphType": "DECIMAL", 1644 | "glyphFormat": "%6.", 1645 | "indentFirstLine": { "magnitude": 234, "unit": "PT" }, 1646 | "indentStart": { "magnitude": 252, "unit": "PT" }, 1647 | "textStyle": { "underline": false }, 1648 | "startNumber": 1 1649 | }, 1650 | { 1651 | "bulletAlignment": "START", 1652 | "glyphType": "ALPHA", 1653 | "glyphFormat": "%7.", 1654 | "indentFirstLine": { "magnitude": 270, "unit": "PT" }, 1655 | "indentStart": { "magnitude": 288, "unit": "PT" }, 1656 | "textStyle": { "underline": false }, 1657 | "startNumber": 1 1658 | }, 1659 | { 1660 | "bulletAlignment": "END", 1661 | "glyphType": "ROMAN", 1662 | "glyphFormat": "%8.", 1663 | "indentFirstLine": { "magnitude": 306, "unit": "PT" }, 1664 | "indentStart": { "magnitude": 324, "unit": "PT" }, 1665 | "textStyle": { "underline": false }, 1666 | "startNumber": 1 1667 | } 1668 | ] 1669 | } 1670 | } 1671 | }, 1672 | "revisionId": "AEUikct9XzFMG_UqPLYnqJAuFrCJMt7PHLUVmm28GVsR8L_Zi39maUDqJmqPuYsZc_eYF7_OqdRya2I_UJyror0", 1673 | "suggestionsViewMode": "SUGGESTIONS_INLINE", 1674 | "documentId": "1LP_eAz_bPaBCLKWr2kGX4TEWC_Oonf3Yiz8VnfqFbng" 1675 | } 1676 | --------------------------------------------------------------------------------