We’ve had a lot of requests for us to open source the WP Browser, the final piece of getting a post from Google Docs to WordPress and into Indesign. We hadn’t up till this point because it was a plugin that only worked on Windows and, well, was pretty bad.
6 p.m.: Finished writing new WordPress Browser for Indesign 6:30 p.m.: Deployed new WP Browser to the newsroom. 8 p.m.: Open Sourced it.
— William P. Davis (@williampd) March 21, 2014
If you want to skip to the end, you can download the Indesign plugin as well as an associated WordPress plugin at https://github.com/bangordailynews/WordPress-to-InDesign.
Also, shameless plug: If this looks cool and you want to build more things like it, we’re hiring.
We’ve been using the WordPress plugin for quite a while now, and testing the Indesign plugin for a little while. They work pretty well.
The WordPress plugin allows you to map various HTML tags to Indesign paragraph and character tags. The easiest way to start would be to create a text box with all the styles you want to map in Indesign, then export the text in that box as Indesign Tagged Text (File -> Export, then select Indesign Tagged Text. Abbreviated is fine.)
Tagged text is just a super easy way to tell Indesign what paragraph style each block of text should appear as. Generally it appears as <pstyle:Paragraph Style Name>. Things like bolding and italics generally appear like <ct:Bold> and <ct:Italic>. A really simple tagged text export looks like this (I deleted the paragraph style definitions at the top for clarity):
<ASCII-MAC> <pstyle:Body Text>This is some test text <pstyle:Article Subheading>This is an article heading <pstyle:Article Subheading>Still an article heading <pstyle:Body Text>Some test text with <ct:Bold>some bolding<ct:> and <ct:Italic>italics<ct:>.
Pretty simple, right?
By default, the WordPress plugin will save off each post as tagged text in /wp-content/uploads/indesign/. The files are named post_id.txt, and you can use rsync and a cron job to sync them locally if you wish. The tagged text is also available through a simple JSON api that will be used in the Indesign plugin.
The thing I keep calling an Indesign plugin is, as I mentioned, actually an Indesign script. To install, open up the scripts pane in Indesign. (If it’s hidden you can show it by going to Window -> Utilities -> Scripts.) Right click on the Application folder, then click Reveal in Finder and navigate into the Scripts Panel folder in the window that opens up. Then drag and drop WP Browser.jsx into the folder. When you go back to Indesign, WP Browser will show up under the Application folder in the scripts pane. Double click to open the browser.
The WP Browser pretty simply allows you to perform a fulltext search on your WordPress install. You can modify the script to either read the post_id.txt files we talked about above from a local location or to dynamically create a local file with the tagged text each time we hit import.
By default, the filter list is populated by categories. I’ll tell you how to modify it below (we’ve modified it to populate from a list of the paper’s sections, and the stories are categories to go into each section).
Before you click import, you must have a text box selected. If you have the entire text box selected, the story will replace everything in that box. If you have a selection of text selected, it will replace that selection. Else it will insert the text where your cursor is.
Both the WordPress plugin and Indesign script require a bit of modification:
- WordPress plugin
- Set an API key at the top of the file. This will be used in the Indesign script and ensures no unauthorized access to all your unpublished posts.
- in function do_tagged_text:
- You can set “formats” for the story to decide which paragraph styles stories are generated with. By default, the post meta key for that format is _format. You can change that if you want.
- We also use a post meta field to override the author attached to the post (for example, for one-time contributors). By default, that field is _byline.
- The plugin integrates with Co-Authors Plus. It also allows you to identify a meta entry for the user that will display as their “title” (ours is BDN Staff, by default).
- We strip out all HTML that’s not a heading, a paragraph tag, a list, or text styling. You can be more or less strict.
- Where we start replacing p, b, em, etc tags, the plugin by default maps the character style to <ct:Bold> and <ct:Italic>. If you use custom fonts, you might have to change this.
- We also strip the state out of datelines if it’s local. (See line ~180)
- Around line 200, we start converting headings to paragraph styles. After we’re done with that style, you need to change back to the default style.
- Then, around line 275, you’ll want to set the paragraph styles for byline and the default paragraph style. There’s also an example of how to change the styles based on format. (This could be coded better.)
- in function wp_browser_search
- By default, you can filter posts in the WP Browser based on category. To change this to a different taxonomy, you’ll need to change the get_categories() call ~310 as well as the category_name arg in get_posts ~335.
- By default, we only query for posts with status publish, draft and pending. If you want to expand or limit that, you can do so ~330.
- WP Browser
- On line 3, set the API key you set in the WordPress plugin
- On line 4, set the domain of your website, no leading http:// (just example.com). The plugin doesn’t currently query over https.
- On line 8, decide whether you want to import from post_id.txt files saved locally or from a file created dynamically.
- On lines 13 and 15, set the path to the files above on Mac and Windows, respectively.
One last thing:
When InDesign makes a call to the server, it does so by creating a socket connection and then requesting the path, or something.
In short, your server will see a request come in for localhost/wp-admin/admin-ajax.php?etc
So, especially on multisite and possible on regular WordPress, you’ll need to set the host for it to work.
I did this by adding the following line to wp-config.php. There’s probably a better way to do it:
if( ( $_SERVER[ 'HTTP_HOST' ] == 'localhost' || empty( $_SERVER[ 'HTTP_HOST' ] ) ) && !empty( $_GET[ 'action' ] ) && ( $_GET[ 'action' ] == 'wp-browser-search' || $_GET[ 'action' ] == 'wp-browser-notify' ) ) $_SERVER[ 'HTTP_HOST' ] = 'mysite.com';
I just ripped a lot of this out of the BDN site and took a lot of our customization out. It will definitely require customization. It might break. Leave a comment below if you have a question. Email me at firstname.lastname@example.org if I did something really stupid.