5 minute read

Here is a step by step example for building a Google Doc Extension that will convert a well formatted Google Docs to Markdown format, using just a bit of JavaScript, HTML, and CSS. We’ll be working with Google Apps Script, a scripting platform based on JavaScript, to access and manipulate Google Docs.

Here are the steps to create the extension:

Set up your Google Apps Script project:

  • a. Visit the Google Apps Script website (https://script.google.com).
  • b. Click “New project.”
    1. c. Give your project a name, like “Docs to Markdown.”
  • Create the necessary files:
  • a. In the script editor, create an HTML file named “sidebar.html” by clicking “File” > “New” > “HTML file.”
    1. b. Create a JavaScript file named “code.gs” by clicking “File” > “New” > “Script file.”

Build the user interface:

  • a. In the “sidebar.html” file, write the HTML code for the user interface. You’ll need a button to trigger the conversion process, and optionally, some options for the user to customize the output.
    1. b. Use CSS to style the interface as needed.

Write the JavaScript code to interact with Google Docs:

  • a. In the “code.gs” file, write a function to open the sidebar in Google Docs. Use the google.script.run API to call server-side functions from your HTML file.
  • b. Write a function to parse the content of the Google Doc. Use the DocumentApp class to access the document and its elements (e.g., text, headings, lists, tables, images, and links). Process the elements according to their type and apply the corresponding Markdown syntax.
    1. c. If you want to provide customization options, use the HTML form in your sidebar to get the user’s preferences and pass them to your server-side functions.

Convert the document content to Markdown:

  • a. Iterate through the elements of the Google Doc, and for each element, append the appropriate Markdown syntax to a string variable.
  • b. Handle any nested elements, such as lists and tables, by processing them recursively.
    1. c. Once you’ve processed all elements, you’ll have a complete Markdown-formatted text.

Output the Markdown content:

  • a. You can display the Markdown output in a textarea in your sidebar, allowing users to copy and paste the content.
    1. b. Alternatively, you can create a new Google Doc or a text file in Google Drive with the generated Markdown content.

Deploy your extension:

  • a. Test your extension by clicking Run > Test as add-on in the script editor.
    1. b. Once you’re satisfied with your extension, click Publish > Deploy from manifest to deploy it. You can share the extension with others by providing the generated link or submitting it to the Google Workspace Marketplace.

Now you have a custom “Docs to Markdown” Google Extension that can convert formatted Google Docs to Markdown format.


Here’s the hierarchy of the source code files you’ll need for your “Docs to Markdown” Google Extension:

1
2
3
4
5
docs-to-markdown/
│
├── code.gs
│
└── sidebar.html
  • code.gs: This is the main Google Apps Script file, containing the server-side JavaScript code. It includes functions to interact with Google Docs, parse its elements, and convert them to Markdown format. Additionally, it contains code for opening the sidebar.
  • sidebar.html: This HTML file is responsible for the user interface of your extension. It includes the structure and design of the sidebar, which may contain a button to trigger the conversion process and, optionally, customization options for the users. You’ll also need to include JavaScript code within this file to handle user interactions and communicate with the server-side functions in code.gs.

Here’s a basic implementation of sidebar.html for your “Docs to Markdown” Google Extension. This sidebar includes a button to trigger the conversion process and a textarea to display the converted Markdown content.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 10px;
      }
      button {
        margin: 5px 0;
        background-color: #4CAF50;
        color: white;
        padding: 10px;
        border: none;
        cursor: pointer;
      }
      textarea {
        width: 100%;
        min-height: 200px;
        padding: 10px;
        margin: 10px 0;
        box-sizing: border-box;
        resize: vertical;
      }
    </style>
  </head>
  <body>
    <h2>Docs to Markdown</h2>
    <button id="convertButton">Convert to Markdown</button>
    <br>
    <h3>Markdown Output:</h3>
    <textarea id="outputArea" readonly></textarea>

    <script>
      document.getElementById('convertButton').addEventListener('click', convertToMarkdown);

      function convertToMarkdown() {
        google.script.run.withSuccessHandler(showMarkdown).convertDocToMarkdown();
      }

      function showMarkdown(markdown) {
        document.getElementById('outputArea').value = markdown;
      }
    </script>
  </body>
</html>

This implementation consists of three parts:

  1. HTML structure: The structure includes a heading, a button, and a textarea.
  2. CSS styling: The styles define basic formatting for the elements in the sidebar.
  3. JavaScript code: The JavaScript code listens for the button click event and calls the convertToMarkdown() function. This function uses the google.script.run API to call the convertDocToMarkdown() function in the code.gs file (you’ll need to implement this function). When the conversion is successful, it calls the showMarkdown() function to display the Markdown content in the textarea.

Here’s a basic implementation of code.gs for your “Docs to Markdown” Google Extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function onOpen() {
  DocumentApp.getUi()
    .createMenu('Docs to Markdown')
    .addItem('Show sidebar', 'showSidebar')
    .addToUi();
}

function showSidebar() {
  var htmlOutput = HtmlService.createHtmlOutputFromFile('sidebar.html')
    .setTitle('Docs to Markdown');
  DocumentApp.getUi().showSidebar(htmlOutput);
}

function convertDocToMarkdown() {
  var doc = DocumentApp.getActiveDocument();
  var body = doc.getBody();
  var markdown = processElement(body);
  return markdown;
}

function processElement(element) {
  var markdown = '';
  var elementType = element.getType();

  switch (elementType) {
    case DocumentApp.ElementType.TEXT:
      var text = element.getText();
      markdown = text;
      break;

    case DocumentApp.ElementType.PARAGRAPH:
      var paragraph = element.asParagraph();
      var heading = paragraph.getHeading();
      var text = processElement(paragraph.getChild(0).asText());
      if (heading == DocumentApp.ParagraphHeading.NORMAL) {
        markdown = text + '\n\n';
      } else {
        var headingLevel = parseInt(heading.substring(1));
        markdown = '#'.repeat(headingLevel) + ' ' + text + '\n\n';
      }
      break;

    case DocumentApp.ElementType.LIST_ITEM:
      var listItem = element.asListItem();
      var nestingLevel = listItem.getNestingLevel();
      var text = processElement(listItem.getChild(0).asText());
      markdown = '  '.repeat(nestingLevel) + '* ' + text + '\n';
      break;

    // Add more cases for other element types, such as tables, images, etc.

    default:
      break;
  }

  return markdown;
}

The code.gs implementation consists of the following functions:

  1. onOpen(): This function is called when the Google Doc is opened. It creates a menu item named “Docs to Markdown” with an option to show the sidebar.
  2. showSidebar(): This function displays the sidebar using the sidebar.html file you implemented earlier.
  3. convertDocToMarkdown(): This function fetches the active document, processes its elements, and returns the converted Markdown content.
  4. processElement(element): This is a recursive function that processes a given element based on its type. In this basic implementation, it handles text, paragraphs, and list items. You can extend this function to handle other element types such as tables, images, links, etc.

Keep in mind that this is a basic implementation and may not handle all formatting options or element types. You can enhance the processElement() function to handle more complex structures and formatting.

Comments