Building a DSL for the indieweb

mf-obj is a library I created while writing skein. I'm also using it in thready. It's an object oriented abstraction on top of the MF2 parser that understands things like posts and authors. Some of the functions it provides are: parsing comments and reply contexts, implementing the authorship algorithm, and determining post types.

A cool trick I discovered is that I can use the node REPL to create an admin console by leveraging terse mf-obj expressions. Instead of designing a whole UI, this took just 1 line of code. Below are some example use cases.

The getAll() method returns an array of all the posts on my blog.

> var entries = site.getAll();

Here's what one of these posts looks like:

> entries[] Entry { name: 'But at least you own your jokes now!', published: Wed Oct 15 2014 12:43:37 GMT-0700 (PDT), content: { value: 'But at least you own your jokes now!', html: 'But at least you own your jokes now!' }, summary: null, url: 'http://notenoughneon.com/2014/10/15/1', author: Card { name: 'Emma Kuo', photo: 'http://notenoughneon.com/m/emma-tw-73.jpeg', url: 'http://notenoughneon.com', uid: null }, category: [], syndication: [], syndicateTo: [], replyTo: Entry { name: 'Surprisingly neither having my own website, nor POSSE have elevated the quality of my content above dumb jokes', published: Wed Oct 15 2014 11:50:43 GMT-0700 (PDT), content: { value: 'Surprisingly neither having my own website, nor POSSE have elevated the quality of my content above dumb jokes', html: 'Surprisingly neither having my own website, nor POSSE have elevated the quality of my content above dumb jokes\n ' }, summary: null, url: 'https://kylewm.com/note/2014/10/15/1/surprisingly-neither-having-my-own', author: Card { name: 'Kyle Mahan', photo: 'https://kylewm.com/static/img/users/kyle.jpg', url: 'https://kylewm.com', uid: null }, category: [], syndication: [ 'https://twitter.com/kyle_wm/status/522459586221993985' ], syndicateTo: [], replyTo: null, likeOf: null, repostOf: null, embed: null, children: Map {} }, likeOf: null, repostOf: null, embed: null, children: Map {} }

I can get statistics such as post count:

> entries.length
112

Using filter(), I can count just the articles:

> entries.filter(e => e.isArticle()).length
4

Or replies:

> entries.filter(e => e.isReply()).length
18

Using map(), I can list just the URL of the replies:

> entries.filter(e => e.isReply()).map(e => e.url)
[ 'http://notenoughneon.com/2014/10/15/1',
'http://notenoughneon.com/2014/11/15/1',
'http://notenoughneon.com/2014/11/16/1',
'http://notenoughneon.com/2014/7/27/1',
'http://notenoughneon.com/2014/8/28/1', ...

Here's a more complex query. This is the URLs and reply count, sorted by descending reply count:

> entries.map(e => [e.getChildren().length, e.url]).sort((a,b) => b[] - a[])
[ [ 14, 'http://notenoughneon.com/2016/6/7/2' ],
[ 11, 'http://notenoughneon.com/2016/6/4/1' ],
[ 11, 'http://notenoughneon.com/2016/5/29/purl-a-portable-content-store' ],
[ 9, 'http://notenoughneon.com/2015/1/16/1' ],
[ 8, 'http://notenoughneon.com/2015/5/15/1' ], ...

I can also search using regex, then list the names of those posts:

> entries.filter(e => e.name.match(/indieweb/)).map(e => e.name)
[ 'Got an #indieweb feed reader running: http://notenoughneon.com/feed.php Its still pretty buggy.',
'Adding neonblog documentation on indiewebcamp.com',
'I have published mf-obj, a set of utility classes for working with #indieweb posts: https://www.npmjs.com/package/mf-obj',
'I\'m demoing skein at #indieweb summit 2016!',
'Forgot to mention my #indieweb site is powered by skein. It\'s open source: https://github.com/notenoughneon/skein', ...

This style of programming should look familiar if you've used jQuery or LINQ. But the admin console isn't just for querying. I can also update posts. Suppose there is a post that needs the "indieweb" tag added:

> var entry = site.get('http://notenoughneon.com/2014/7/26/1');
> entry.category.push('indieweb');
> site.update(entry);

This is still a work in progress, and the last example would be better if it could be expressed as a one-liner. But this demonstrates a principle I call "building for hackability." In the early stages of a project, you need to rapidly prototype and can't afford full fledged UIs. Having a good foundation that lends itself to DSLs will open up the opportunity for quick REPL based interfaces.

 #indieweb#node
Building a DSL for the indieweb - Not Enough Neon notenoughneon.com/2016/6/13/buil…
 
Building a DSL for the indieweb - Not Enough Neon notenoughneon.com/2016/6/13/buil…
 
Kevin Marks Building a DSL for the indieweb - Not Enough Neon Kevin Markspublished this 14 Jun 2016 0 stars 0 comments
 
Shane Becker liked this.
Jeena liked this.
Greg liked this.