This article describes the development of GoogPress, a platform created using Google Apps Script that enables conversion of Google Docs into web pages, allowing for the publication of articles and papers online.
Introduction
In my spare time, I work on the production team of the Young Scientists’ Journal. We oversee the journal’s distribution in both digital and print forms. When we took over from the previous team, we were tasked with moving the site away from the (now deprecated) WordPress Annotum and onto something more current, user-friendly and less prone to XML errors. Following much deliberation, we decided to move things onto Google Docs. This was super intuitive with unlimited (document) storage and people approved of it very much (Google Docs is basically MS Word) but did present one problem – how were we going to get all our articles and papers from documents into webpages?
We thus decided to build GoogPress – like WordPress, but using Google as a backend.
You can find our website (built with GoogPress, with more thorough documentation) here and all our code on GitHub.
General Workings
We used Google Apps Script as a means of grabbing all the docs. This meant that they didn’t have to be shared publicly and could all be stored in a Posts folder.
The script is stored somewhere on the user’s Google Drive (doesn’t particularly matter where) and is called using POST
requests from the client. The developer then sticks GoogPress.js into their website and calls it with the gp_Init
function.
gp_Init ("https://your-script-url-here");
gp_loadPosts($("#post-container"),"postClass", "<hr/>", 1, 3);
Once that’s done, the HTML that comes out looks a bit like this:
<div id="post-container">
<div class="postClass">
I am the latest post
</div>
<hr/>
<div class="postClass">
I am not the latest post
</div>
<hr/>
<div class="postClass">
I am also not the latest post
</div>
<hr/>
</div>
You can also load individual posts using:
gp_loadPost ("Hi World", $("#post"));
which returns something like this:
<div id="post">
Content of 'Hi World'
</div>
or simply by using Google the data-googpress
attribute:
<div data-googpress="postName"></div>
which loads the posts into the <div>
on initialisation.
A Closer Look at the Server Side
The back-end is all Google Apps Script. It's basically JavaScript with some exiting Google-related integrations.
To start with, we check the parameters passed in the POST
request. If they’re invalid, we return an error. Otherwise, we look for the post. We do this in the doPost
method (which runs whenever we receive a POST
request).
function doPost(e) {
var requestType = e.parameters.type;
var id = e.parameters.id;
var asHtml = e.parameters.asHtml;
var start = e.parameters.start;
var end = e.parameters.end;
if (requestType == undefined){
return ContentService.createTextOutput("Failed to specify request type");
}
*OTHER STUFF GOES HERE*
}
We search for the doc using the openDoc
function.
function openDoc(docName, containerFolder) {
var file, files = (containerFolder == undefined) ?
DriveApp.getFilesByName(docName) :
openFolder(containerFolder).getFilesByName(docName);
if (files.hasNext ()){
file = files.next();
} else {
return "Not Found";
}
return DocumentApp.openById(file.getId());
}
We then convert the doc into HTML using a modified version of this snippet by Omar Al Zabir (he explains how it works on his blog). This essentially allows us to turn stuff like this:
into stuff like this:
As you can see, Google Apps Script allows easy interaction with Google Products with their DocumentApp
and DriveApp
classes.
Building an Installer
The basic request-making interface was pretty easy to build and was implemented over a few afternoons after school. What was surprisingly difficult, however, was building an installer. We first considered deploying on the Chrome Web Store but that seemed like too much effort (and not particularly prototype-friendly). We tried to write a script that would create a script file in the user’s drive and then copy over the code but that didn’t work either (and indeed for good reason).
In the end, after a day's pondering and a few beers, we settled on the devilishly convoluted system described below.
- The user runs a script which they must authorise. In this way, we are given permission to access the user’s drive.
- The script then sends a request to a script running on our end.
- The script on our end creates a copy of the
GoogPress
script and shares it with the user. - The script on the user’s end adds the shared script to its own drive and then makes a copy of it. This ensures that the user is the owner of the file (and not us).
- There’s then some copying and pasting and arranging of files which means the installation is tidy and kept in a dedicated GoogPress folder. We also create a “
Hello World
” post. - Once this is all done, we delete the shared file off of our drive.
(The scripts of interest are Distributor.gs which runs on our side and Installer.gs which runs on the user's)
What are we Working on Now? (Current Challenges)
A cache system. If you send too many requests per second, Google thinks you’re trying to DDOS them (or something along those lines). While this won’t be a problem for smaller sites, it’s a problem and we’re going to try and fix it.
Dealing with images. Images load pretty slowly on GoogPress because the Google Doc to HTML converter converts them to Base64
before sending them over. There’s probably a faster way of doing it and, with some time, we’ll find it.
Demo
This below demo code loads a sample post onto a very basic HTML page. Copy the below markup into your favourite text editor.
<html>
<head>
<title> GoogPress Demo </title>
</head>
<body>
<h1> This is GoogPress </h1>
<div data-googpress="TestPost2"></div>
<!--
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
<script type="text/javascript"
src="https://cdn.googpress.org/0.1/GoogPress.min.js"> </script>
<script>
gp_Init ("https://script.google.com/macros/s/AKfycbxunMflwCcd5lPoS1SEDTEIeIOjAuj9QnLon9czPFN5lfV2dtXt/exec");
</script>
</body>
</html>
Open it up in your browser and it should look like this:
And yes, they're notes from RS GCSE.