• Stars
    star
    145
  • Rank 254,144 (Top 6 %)
  • Language
    JavaScript
  • Created about 12 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

javascript implementation of edn

jsedn

A javascript implementation of edn. To see it in action checkout the edn playground. If you open your browser console you will have access to a global jsedn object with which you can try things beside JSON encoding. I recommend jsedn.unify("[?x was always better than ?y]", {x: "sonic", y: "mario"}).jsEncode().

Build Status npm version Coverage Status

Getting Started

Install

npm install jsedn

Use in a web page directly

Use jsedn.js, which is a standalone version that will provide a global "jsedn".

Code

var edn = require("jsedn");
var map = edn.parse("{:a 5 [1 2] {:name :mike :age 40}}");
console.log(map.at(new edn.Vector([1, 2])).at(edn.kw(":name")));

Will output "mike".

Now the other way:

edn.encode({a: 1, "id": 333});

Will output:

{"a" 1 "id" 333}

Finally lets encode js into edn then back to js:

edn.parse(edn.encode({
	a: 1, 
	b: {
		age: 30, 
		feeling: ["electric", "pink"]
	}
})).at("b").at("feeling").at(0)

Will output "electric". Definitely working in both directions.

###Command Line If you have installed via npm you will have a jsedn script that accepts input via pipe/stdin. Currently takes:

  • -s flag for "select" which you pass a path separated by space
  • -j encodes input as JSON
  • -p indicates pretty print for json output
> echo "{:a first-item :b [{:name :walter :age 50 :kids [:A :B :C]}]}" | jsedn -s ":b 0 :kids 2"
outputs: :b 0 :kids 2 => :C

Testing

I have developed this in a very test driven manner e.g. each test written before the next feature is implemented. Baring that in mind it means any bugs you find it would be awesome if you could edit the tests adding one which clearly indicates the bug/feature request.

npm install
git submodule update --init
npm test

API

#####parse (ednString) Will turn a valid edn string into a js object structure based upon the classes details below.

edn.parse("{:a-keyword! [1 2 -3.4]}");

#####encode (jsObj) Will encode both native JS and any object providing a ednEncode method.

edn.encode({"a-keyword!": [1,2,-3.4]});

#####setTagAction (tag, action) Will add the tag action to be performed on any data prepended by said tag.

edn.setTagAction(new edn.Tag('myApp', 'tagName'), function(obj) {
	//do stuff with obj here and then return it
	var mutatedObj = thingsHandlerDoes(obj);
	return mutatedObj;
});

#####setTokenPattern (tokenName, pattern) If for some reason you would like to over-ride or add a new token pattern.

edn.setTokenPattern()))

#####setTokenAction (tokenName, actionCallback) Allows for customization of token handling upon match. For instance if you decided you would prefer nil to be represented by undefined instead of null (default).

edn.setTokenAction('nil', function(token) { return undefined;});

#####setTypeClass (type, class) This is useful if you want to over-ride the naive implementations of Map etc.

edn.setTypeClass('List', MyListClass));
atPath (obj, path)

Simple way to lookup a value in elements returned from parse.

var parsed = edn.parse("[[{:name :frank :kids [{:eye-color :red} {:eye-color :blue}]}]]");
edn.atPath(parsed, "0 0 :kids 1 :eye-color");

path is a space separated string which consists of index (remember Array/Set/Vector are all 0 indexed) and key locations.

encodeJson

Provides a json encoding including type information e.g. Vector, List, Set etc.

console.log(edn.encodeJson(edn.parse("[1 2 3 {:x 5 :y 6}]")));

yields:

{"Vector":[1,2,3,{"Map":[{"Keyword": ":x"},5,{"Keyword":":y"},6]}]}
toJS

Attempts to return a "plain" js object. Bear in mind this will yield poor results if you have any Map objects which utilize composite objects as keys. If an object has a hashId method it will use that when building the js dict.

var jsobj = edn.toJS(edn.parse("[1 2 {:name {:first :ray :last :cappo}}]"));

yields:

[1, 2, {":name": {":first": ":ray", ":last": ":cappo"}}]

Notice that you can not always go back the other direction. In the example above if you were to edn.parse it you would end up with:

[1 2 {":name" {":first" ":ray" ":last" ":cappo"}}]

In which you have strings for keys instead of keywords. At one point I would "infer" that if a string started with a ":" it would be treated as a keyword. This caused more problems than it resolved which brings us to our next methods.

kw (string)

Interns a valid keyword into an edn.Keyword object e.g:

edn.kw(":myns/kw")
sym (string)

Interns a valid symbol into an edn.Symbol object e.g:

edn.sym("?name")
unify (data, values, [tokenStart])

Unifies the first form with the second. Useful for populating a "data template". It accepts either edn objects or strings as arguments.

edn.unify("{?key1 ?key1-val ?key2 ?key2-val :all [?key1-val ?key2-val]}", "{key1 :x key1-val 200 key2 :y key2-val 300}");

yields:

{:x 200 :y 300 :all [200 300]}

A third argument is expected which can be used to indicate the "tokenStart" first character for unify tokens. This defaults to "?".

An example with Map as data and js obj as values and changing the tokenStart to $

edn.unify(new edn.Map([edn.kw(":place"), edn.sym("$place")]), {place: "salt lake city"}, "$");

yields:

{:place "salt lake city"}

Classes/Interfaces

Symbol

Used to create symbols from with in js for encoding into edn.

Keyword

As above but for keywords. Note that the constructor enforced that keywords start with a ":" character.

####Iterable [List Vector Set] List, Vector and Set all implement the following methods:

  • exists (key) -> boolean indicating existance of key
  • at (key) -> value at key in collection
  • set (key, val) -> sets key/index to given value
  • each (iter) -> iterate overa all members calling iter on each, returns results
  • map (iter) -> iterate over all members calling iter on each and returning a new instace of self
  • walk (iter) -> recursively walk the data returning a new instance of self

####Map Supports any type of object as key. Supports all of the methods listed for Iterable plus indexOf which returns the index of the item, which can be 0 and thus non-truthy.

each, map and walk all accept a callback which takes the value as the first argument and the key as the second. In the case of map and walk if you want to modify the key you must return a Pair object e.g.

edn.parse("{:x 300 y: 800}").map(function(val, key){
	return new edn.Pair(edn.kw("#{key}-squared"), val * val);
});

yields:

{:x-squared 90000 :y-squared 640000}

####Tag Used for defining Tag Actions. Has a constructor which accepts 2..n args where the first arg is your a namespace and the rest are used to categorize the tag. Tag provides two methods ns and dn:

var tag = new edn.Tag('myApp', 'people', 'special', 'stuff');
console.log(tag.ns()); => myApp
console.log(tag.dn()); => myApp/people/special/stuff

Constructor also supports being passed single argument delimited by / e.g:

new edn.Tag('myApp/people/special/stuff')

####Tagged If you do not have tag handlers specified for a given tag you will end up with Tagged items in your result which have two methods:

tag() -> Tag object found
obj() -> Object to be tagged

Tagged pairs can also be used when you want to serialize a js obj into edn w/ said tagging e.g.

edn.encode(new edn.Tagged(new edn.Tag("myApp", "Person"), {name: "walter", age: 300}));

outputs:

#myApp/person {"name" "walter" "age" 300}

##Conversion Table

element edn jsedn js
nil nil null null
boolean true false true false true false
character \c "c" "c"
string "some string" "some string" "some string"
symbol ?sym~b~o!ol edn.sym "?sym~b~o!ol" "?sym~b~o!ol"
keywords :keyword edn.kw ":keyword" ":keyword"
integer 666 666 666
floating point -6.66 -6.66 -6.66
list (a b (c d)) new edn.List([edn.sym("a"), edn.sym("b"), new edn.List([edn.sym("c"), edn.sym("d")])]) ["a", "b", ["c", "d"]]
vector [a b c] new edn.Vector([edn.sym("a"), edn.sym("b"), edn.sym("c")]) ["a", "b", "c"]
map {:a 1 :b 2} new edn.Map([edn.kw(":a"), 1, edn.kw(":b"), 2]) {a: 1, b: 2}
set #{1 2 3} new edn.Set([1, 2, 3]) [1 2 3]
tagged elements #tagName [1 2] new edn.Tagged(new edn.Tag("tagName"), new edn.Vector([1, 2])) n/a

More Repositories

1

datomicism

interface for visualizing datomic schemas and queries
JavaScript
81
star
2

clojurescript-ecosystem

an index of clojurescript libraries
67
star
3

edn-cpp

experimental edn lib for c++
C++
21
star
4

php-trampoline

php trampoline library for tail call optimization
PHP
20
star
5

transmogrifier

php macro expansion for situationists
PHP
5
star
6

ouija

component for planchette indicated select/combo inputs ala ouija board
JavaScript
5
star
7

coffeetalk

smalltalk esque class browser/editor for coffeescript
JavaScript
4
star
8

pathcomics

path comics
CoffeeScript
4
star
9

phlisp

lisp written for php
JavaScript
4
star
10

edn-tests

common set of edn tests/large files for testing performance
PHP
4
star
11

soy

lisp for php and javascript
CoffeeScript
4
star
12

Voltron

Voltron is a modern mvc framework for php
PHP
3
star
13

bling

string prototype approach to rapidly creating jquery dom chunks
CoffeeScript
3
star
14

elements-overlap

component to determine if two dom elements overlap
JavaScript
3
star
15

sentencediagrammer

a sentence diagramming system
JavaScript
3
star
16

MA

minimal a-priori lisp
2
star
17

phutility

php utilities
PHP
2
star
18

chain-of-strength

chain-of-strength npm package for building method chain strings from array based dsl - useful for passing in functions to phantom js
2
star
19

PHOS

php meta-object system inspired by clos and smalltalk
JavaScript
2
star
20

swedn

sweet expression edn
CoffeeScript
2
star
21

taskshuffle

task shuffle app
JavaScript
2
star
22

tofu

Tofu is a smalltalk dialect for vegans
2
star
23

phmop

php metaobject protocol
PHP
2
star
24

AmberMixins

mixin system for smalltalk, specifically targetting amberjs
Smalltalk
2
star
25

pieshares

pieshares
Shell
2
star
26

chet

Chet is a light weight, experimental, pre-production-ready, appositive expression friendly, REST oriented php 5.3+ web framework
PHP
2
star
27

monsterworld

monsterworld forum
PHP
2
star
28

kip

ki for php
2
star
29

rightactionfood

right action food
CoffeeScript
2
star
30

blocks

sifteo-esque block emulation
JavaScript
2
star
31

draggable

component to make an element draggable
CoffeeScript
2
star
32

resizable

resize element component
CoffeeScript
1
star
33

Covenants

alternative query builder for doctrine
PHP
1
star
34

el-edn

elisp edn
Emacs Lisp
1
star
35

multi

multi function utlity for coffee/js
JavaScript
1
star
36

a-pattern-in-the-primes

pattern in the primes
Mathematica
1
star
37

ingen

js code browser
1
star
38

viable-system-model

an implementation of the viable system model for the web
1
star
39

soy-boat

soy (on a) boat is a full stack soy based web framework
1
star
40

CodeChat

experimental repl chat for javascript - only play with people you trust. hah.
JavaScript
1
star
41

fractal-realms

API specification and implementation for fractal realms
Clojure
1
star
42

comicengine

path comics
PHP
1
star
43

metaobjects

meta objects website
1
star
44

php-quasiquote-preprocessor

php quasiquote preprocessor PQP
PHP
1
star
45

anuhmate

animation framework and toolkit for sprite based games
JavaScript
1
star
46

apl-to-clojure

apl to clojure transpiler
1
star
47

BackTalk

backbone for amberjs smalltalk
1
star
48

bubblegraph

bubble chart tool
JavaScript
1
star
49

persysiphus

persistent editing environment
1
star
50

JQueryTalk

Alternative amber js jquery integration
JavaScript
1
star
51

MC

Minimal Content Management System - php 5, no db, single developer, static content management system
JavaScript
1
star
52

marquee

marquee selection component
CoffeeScript
1
star
53

live-love-reload

basic framework for rapid love2d development
1
star
54

schematic.io

schematic.io site
JavaScript
1
star
55

dtm

command line datomic query/transact bin that plays nice with unix
C++
1
star
56

semblance

self hosted reflective clojurescript programming environment
1
star
57

codemirror-apl-mode

apl mode for codemirror
CoffeeScript
1
star
58

gherkin-barrel

a node js stand along feature editor for bdd development
CoffeeScript
1
star