--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore Tue Jul 26 18:11:39 2011 -0400
@@ -0,0 +1,2 @@
+*~
+*.sw[op]
--- a/playground/index.html Tue Jul 26 18:11:06 2011 -0400
+++ b/playground/index.html Tue Jul 26 18:11:39 2011 -0400
@@ -47,23 +47,23 @@
<ul id="examples">
<li class="button-list">Simple Examples:</li>
<li class="button">
- <span onmousedown="playground.populate('Person')">Person</span>
- </li>
- <li class="button">
- <span onmousedown="playground.populate('Event')">Event</span>
+ <span onmousedown="playground.populateWithExample('Person')">Person</span>
</li>
<li class="button">
- <span onmousedown="playground.populate('Place')">Place</span>
+ <span onmousedown="playground.populateWithExample('Event')">Event</span>
</li>
<li class="button">
- <span onmousedown="playground.populate('Product')">Product</span>
+ <span onmousedown="playground.populateWithExample('Place')">Place</span>
</li>
<li class="button">
- <span onmousedown="playground.populate('Recipe')">Recipe</span>
+ <span onmousedown="playground.populateWithExample('Product')">Product</span>
+ </li>
+ <li class="button">
+ <span onmousedown="playground.populateWithExample('Recipe')">Recipe</span>
</li>
<li class="button-list">Framing Examples:</li>
<li class="button">
- <span onmousedown="playground.populate('Library')">Library</span>
+ <span onmousedown="playground.populateWithExample('Library')">Library</span>
</li>
</ul><br />
@@ -76,6 +76,8 @@
onkeyup="playground.process()"></textarea>
</div>
+ <div id="permalink"></div>
+
<div id="markup-errors" class="errors"></div>
<div id="frame-errors" class="errors"></div>
--- a/playground/jsonld.js Tue Jul 26 18:11:06 2011 -0400
+++ b/playground/jsonld.js Tue Jul 26 18:11:39 2011 -0400
@@ -100,7 +100,7 @@
for(var key in ctx)
{
// skip special context keys (start with '@')
- if(key.length > 0 && key.indexOf('@') !== 0)
+ if(key.length > 0 && key[0] !== '@')
{
// compact to a term
if(iri === ctx[key])
@@ -127,7 +127,7 @@
for(var key in ctx)
{
// skip special context keys (start with '@')
- if(key.length > 0 && key.indexOf('@') !== 0)
+ if(key.length > 0 && key[0] !== '@')
{
// see if IRI begins with the next IRI from the context
var ctxIri = ctx[key];
@@ -136,7 +136,7 @@
// compact to a CURIE
if(idx === 0 && iri.length > ctxIri.length)
{
- rval = key + ':' + iri.substr(idx + ctxIri.length);
+ rval = key + ':' + iri.substr(ctxIri.length);
if(usedCtx !== null)
{
usedCtx[key] = ctxIri;
@@ -620,7 +620,7 @@
{
_setProperty(rval, key, _clone(value[key]));
}
- else if(key !== '@context' && key !== '@coerce')
+ else if(key !== '@context')
{
// set object to expanded property
_setProperty(
@@ -742,8 +742,8 @@
/**
* Compares two keys in an object. If the key exists in one object
- * and not the other, that object is less. If the key exists in both objects,
- * then the one with the lesser value is less.
+ * and not the other, the object with the key is less. If the key exists in
+ * both objects, then the one with the lesser value is less.
*
* @param o1 the first object.
* @param o2 the second object.
@@ -998,16 +998,6 @@
{
_flatten(parent, parentProperty, value[i], subjects);
}
-
- // if value is a list of objects, sort them
- if(value.length > 0 &&
- (value[0].constructor === String ||
- (value[0].constructor === Object &&
- ('@literal' in value[0] || '@iri' in value[0]))))
- {
- // sort values
- value.sort(_compareObjects);
- }
}
else if(value.constructor === Object)
{
@@ -1342,17 +1332,18 @@
{
var bnode = bnodes[i];
var iri = bnode[__s]['@iri'];
+ if(c14n.inNamespace(iri))
+ {
+ // generate names until one is unique
+ while(ngTmp.next() in subjects);
+ this.renameBlankNode(bnode, ngTmp.current());
+ iri = bnode[__s]['@iri'];
+ }
this.serializations[iri] =
{
'props': null,
'refs': null
};
- if(c14n.inNamespace(iri))
- {
- // generate names until one is unique
- while(ngTmp.next() in subjects);
- this.renameBlankNode(bnode, ngTmp.current());
- }
}
// keep sorting and naming blank nodes until they are all named
@@ -1365,7 +1356,7 @@
});
// name all bnodes according to the first bnode's relation mappings
- var bnode = bnodes.shift(1);
+ var bnode = bnodes.shift();
var iri = bnode[__s]['@iri'];
var dirs = ['props', 'refs'];
for(var d in dirs)
@@ -1394,11 +1385,11 @@
var renamed = [];
for(var i in keys)
{
- var iri = keys[i];
- if(!c14n.inNamespace(iri) && iri in subjects)
+ var iriK = keys[i];
+ if(!c14n.inNamespace(iri) && iriK in subjects)
{
- this.renameBlankNode(subjects[iri], c14n.next());
- renamed.push(iri);
+ this.renameBlankNode(subjects[iriK], c14n.next());
+ renamed.push(iriK);
}
}
@@ -1453,9 +1444,9 @@
};
/**
- * Copies a MappingBuilder.
+ * Copies this MappingBuilder.
*
- * @param mb the MappingBuilder to copy.
+ * @return the MappingBuilder copy.
*/
MappingBuilder.prototype.copy = function()
{
@@ -1519,6 +1510,49 @@
};
/**
+ * Serializes the properties of the given bnode for its relation serialization.
+ *
+ * @param b the blank node.
+ *
+ * @return the serialized properties.
+ */
+var _serializeProperties = function(b)
+{
+ var rval = '';
+
+ for(var p in b)
+ {
+ if(p !== '@subject')
+ {
+ var first = true;
+ var objs = (b[p].constructor === Array) ? b[p] : [b[p]];
+ for(var oi in objs)
+ {
+ if(first)
+ {
+ first = false;
+ }
+ else
+ {
+ rval += '|';
+ }
+ if(objs[oi].constructor === Object &&
+ '@iri' in objs[oi] && _isBlankNodeIri(objs[oi]['@iri']))
+ {
+ rval += '_:';
+ }
+ else
+ {
+ rval += JSON.stringify(objs[oi]);
+ }
+ }
+ }
+ }
+
+ return rval;
+};
+
+/**
* Recursively creates a relation serialization (partial or full).
*
* @param keys the keys to serialize in the current output.
@@ -1527,7 +1561,8 @@
*
* @return the relation serialization.
*/
-var _recursiveSerializeMapping = function(keys, output, done)
+jsonld.Processor.prototype.recursiveSerializeMapping = function(
+ keys, output, done)
{
var rval = '';
for(var i in keys)
@@ -1547,8 +1582,40 @@
{
done[k] = true;
var tmp = output[k];
- rval += k + tmp.join('');
- rval += _recursiveSerializeMapping(tmp, output, done);
+ for(var t in tmp.k)
+ {
+ var s = tmp.k[t];
+ rval += s;
+ var iri = tmp.m[s];
+ if(iri in this.subjects)
+ {
+ var b = this.subjects[iri];
+
+ // serialize properties
+ rval += '<';
+ rval += _serializeProperties(b);
+ rval += '>';
+
+ // serialize references
+ rval += '<';
+ var first = true;
+ var refs = this.edges.refs[iri].all;
+ for(var r in refs)
+ {
+ if(first)
+ {
+ first = false;
+ }
+ else
+ {
+ rval += '|';
+ }
+ rval += _isBlankNodeIri(refs[r].s) ? '_:' : refs[r].s;
+ }
+ rval += '>';
+ }
+ }
+ rval += this.recursiveSerializeMapping(tmp.k, output, done);
}
}
return rval;
@@ -1561,12 +1628,9 @@
*
* @return the relation serialization.
*/
-var _serializeMapping = function(output)
+jsonld.Processor.prototype.serializeMapping = function(output)
{
- // get sorted keys for current output
- var keys = Object.keys(output).sort();
- var done = {};
- return _recursiveSerializeMapping(keys, output, done);
+ return this.recursiveSerializeMapping(['s1'], output, {});
};
/**
@@ -1600,6 +1664,77 @@
};
/**
+ * Recursively serializes adjacent bnode combinations.
+ *
+ * @param s the serialization to update.
+ * @param top the top of the serialization.
+ * @param mb the MappingBuilder to use.
+ * @param dir the edge direction to use ('props' or 'refs').
+ * @param mapped all of the already-mapped adjacent bnodes.
+ * @param notMapped all of the not-yet mapped adjacent bnodes.
+ */
+jsonld.Processor.prototype.serializeCombos = function(
+ s, top, mb, dir, mapped, notMapped)
+{
+ // copy mapped nodes
+ mapped = _clone(mapped);
+
+ // handle recursion
+ if(notMapped.length > 0)
+ {
+ // map first bnode in list
+ mapped[mb.mapNode(notMapped[0].s)] = notMapped[0].s;
+
+ // recurse into remaining possible combinations
+ var original = mb.copy();
+ notMapped = notMapped.slice(1);
+ var rotations = Math.max(1, notMapped.length);
+ for(var r = 0; r < rotations; ++r)
+ {
+ var m = (r === 0) ? mb : original.copy();
+ this.serializeCombos(s, top, m, dir, mapped, notMapped);
+
+ // rotate not-mapped for next combination
+ _rotate(notMapped);
+ }
+ }
+ // handle final adjacent node in current combination
+ else
+ {
+ var keys = Object.keys(mapped).sort();
+ mb.output[top] = { k: keys, m: mapped };
+
+ // optimize away mappings that are already too large
+ var _s = this.serializeMapping(mb.output);
+ if(s[dir] === null || _compareSerializations(_s, s[dir].s) <= 0)
+ {
+ var oldCount = mb.count;
+
+ // recurse into adjacent values
+ for(var i in keys)
+ {
+ var k = keys[i];
+ this.serializeBlankNode(s, mapped[k], mb, dir);
+ }
+
+ // reserialize if more nodes were mapped
+ if(mb.count > oldCount)
+ {
+ _s = this.serializeMapping(mb.output);
+ }
+
+ // update least serialization if new one has been found
+ if(s[dir] === null ||
+ (_compareSerializations(_s, s[dir].s) <= 0 &&
+ _s.length >= s[dir].s.length))
+ {
+ s[dir] = { s: _s, m: mb.mapping };
+ }
+ }
+ }
+};
+
+/**
* Computes the relation serialization for the given blank node IRI.
*
* @param s the serialization to update.
@@ -1616,53 +1751,50 @@
mb.mapped[iri] = true;
var top = mb.mapNode(iri);
- // copy original mapping builder, loop over adjacent values
+ // copy original mapping builder
var original = mb.copy();
- var values = this.edges[dir][iri].bnodes.slice();
- var loop = Math.max(1, values.length);
- for(var i = 0; i < loop; ++i)
+
+ // split adjacent bnodes on mapped and not-mapped
+ var adj = this.edges[dir][iri].bnodes;
+ var mapped = {};
+ var notMapped = [];
+ for(var i in adj)
+ {
+ if(adj[i].s in mb.mapping)
+ {
+ mapped[mb.mapping[adj[i].s]] = adj[i].s;
+ }
+ else
+ {
+ notMapped.push(adj[i]);
+ }
+ }
+
+ // TODO: ensure this optimization does not alter canonical order
+
+ // if the current bnode already has a serialization, reuse it
+ /*var hint = (iri in this.serializations) ?
+ this.serializations[iri][dir] : null;
+ if(hint !== null)
+ {
+ var hm = hint.m;
+ notMapped.sort(function(a, b)
+ {
+ return _compare(hm[a.s], hm[b.s]);
+ });
+ for(var i in notMapped)
+ {
+ mapped[mb.mapNode(notMapped[i].s)] = notMapped[i].s;
+ }
+ notMapped = [];
+ }*/
+
+ // loop over possible combinations
+ var combos = Math.max(1, notMapped.length);
+ for(var i = 0; i < combos; ++i)
{
var m = (i === 0) ? mb : original.copy();
-
- // map all edge nodes
- var tmp = [];
- for(var i2 in values)
- {
- tmp.push(m.mapNode(values[i2].s));
- }
- m.output[top] = tmp.sort();
- var oldCount = m.count;
-
- // optimize away mappings that are already too large
- var _s = _serializeMapping(m.output);
- if(s[dir] === null || _compareSerializations(_s, s[dir].s) <= 0)
- {
- // recurse into adjacent values
- for(var i2 in values)
- {
- // TODO: optimization: for each value, see if the value already
- // has a shortest serialization for the given direction that
- // can be reused
- this.serializeBlankNode(s, values[i2].s, m, dir);
- }
-
- // reserialize if more nodes were mapped
- if(m.count > oldCount)
- {
- _s = _serializeMapping(m.output);
- }
-
- // update least serialization if new one has been found
- if(s[dir] === null ||
- (_compareSerializations(_s, s[dir].s) <= 0 &&
- _s.length >= s[dir].s.length))
- {
- s[dir] = { s: _s, m: m.mapping };
- }
- }
-
- // rotate values
- _rotate(values);
+ this.serializeCombos(s, top, mb, dir, mapped, notMapped);
}
}
};
@@ -1968,7 +2100,11 @@
if(!(type in frame))
{
// get frame properties that must exist on input
- var props = Object.keys(frame);
+ var props = Object.keys(frame).filter(function(e)
+ {
+ // filter non-keywords
+ return e.indexOf('@') !== 0;
+ });
if(props.length === 0)
{
// input always matches if there are no properties
@@ -2014,6 +2150,10 @@
{
rval = [];
frames = frame;
+ if(frames.length === 0)
+ {
+ frames.push({});
+ }
}
else
{
@@ -2030,7 +2170,8 @@
if(frame.constructor !== Object)
{
throw {
- message: 'Invalid JSON-LD frame. Frame type is not a map or array.'
+ message: 'Invalid JSON-LD frame. ' +
+ 'Frame must be an object or an array.'
};
}
@@ -2038,10 +2179,18 @@
values[i] = [];
for(var n = 0; n < input.length && limit !== 0; ++n)
{
+ // dereference input if it refers to a subject
+ var next = input[n];
+ if(next.constructor === Object && '@iri' in next &&
+ next['@iri'] in subjects)
+ {
+ next = subjects[next['@iri']];
+ }
+
// add input to list if it matches frame specific type or duck-type
- if(_isType(input[n], frame) || _isDuckType(input[n], frame))
+ if(_isType(next, frame) || _isDuckType(next, frame))
{
- values[i].push(input[n]);
+ values[i].push(next);
--limit;
}
}
@@ -2073,7 +2222,8 @@
// TODO: possibly support multiple embeds in the future ... and
// instead only prevent cycles?
throw {
- message: 'Multiple embeds of the same subject is not supported.',
+ message: 'More than one embed of the same subject is not ' +
+ 'supported.',
subject: value[__s]['@iri']
};
}
@@ -2463,4 +2613,11 @@
return new jsonld.Processor().frame(input, frame, options);
};
+/**
+ * Creates the JSON-LD default context.
+ *
+ * @return the JSON-LD default context.
+ */
+jsonld.createDefaultContext = _createDefaultContext;
+
})();
--- a/playground/playground.css Tue Jul 26 18:11:06 2011 -0400
+++ b/playground/playground.css Tue Jul 26 18:11:39 2011 -0400
@@ -69,3 +69,6 @@
padding: 6px 0 4px 18px; /* push text down 1px */
}
+#permalink {
+ text-align: right;
+}
--- a/playground/playground.js Tue Jul 26 18:11:06 2011 -0400
+++ b/playground/playground.js Tue Jul 26 18:11:39 2011 -0400
@@ -35,16 +35,110 @@
">": "gt"
}[c] + ";";
});
- }
+ };
+
/**
- * Used to initialize the UI, call once a document load.
+ * Get a query parameter by name.
+ *
+ * Code from:
+ * http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript/5158301#5158301
+ *
+ * @param name a query parameter name.
+ *
+ * @return the value of the parameter or null if it does not exist
+ */
+ function getParameterByName(name) {
+ var match = RegExp('[?&]' + name + '=([^&]*)')
+ .exec(window.location.search);
+ return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
+ };
+
+ /**
+ * Handle URL query parameters.
+ *
+ * Checks "json-ld" and "frame" parameters. If they look like JSON then
+ * interpret as JSON strings else interpret as URLs of remote resources.
+ * Note: URLs must be CORS enabled to load due to browser same origin policy
+ * issues.
+ */
+ playground.processQueryParameters = function()
+ {
+ // data from the query
+ var queryData = {
+ markup: null,
+ frame: null
+ };
+
+ /**
+ * Read a parameter as JSON or created an jQuery AJAX Deferred call
+ * to read the data.
+ *
+ * @param param a query parameter value.
+ * @param fieldName the field name to populate in queryData object.
+ * @param msgName the param name to use in UI messages.
+ *
+ * @return jQuery Deferred or null
+ */
+ function handleParameter(param, fieldName, msgName)
+ {
+ // the ajax deferred or null
+ var rval = null;
+
+ // check "json-ld" parameter
+ if(param !== null)
+ {
+ hasQueryData = true;
+ if(param.length == 0 || param[0] == "{" || param[0] == "[")
+ {
+ // param looks like JSON
+ queryData[fieldName] = param;
+ }
+ else
+ {
+ // treat param as a URL
+ rval = $.ajax({
+ url: param,
+ dataType: 'text',
+ success: function(data, textStatus, jqXHR) {
+ queryData[fieldName] = data;
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ // FIXME: better error handling
+ $("#markup-errors")
+ .text("Error loading " + msgName + " URL: " + param);
+ }
+ });
+ }
+ };
+
+ return rval;
+ };
+
+ // build deferreds
+ var jsonLdDeferred = handleParameter(
+ getParameterByName("json-ld"), "markup", "JSON-LD");
+ var frameDeferred = handleParameter(
+ getParameterByName("frame"), "frame", "frame");
+
+ // wait for ajax if needed
+ // failures handled in AJAX calls
+ $.when(jsonLdDeferred, frameDeferred)
+ .done(function() {
+ // populate UI with data
+ playground.populateWithJSON(queryData);
+ });
+ };
+
+ /**
+ * Used to initialize the UI, call once on document load.
*/
playground.init = function()
{
$("#tabs").tabs();
$("#frame").hide();
$("#tabs").bind("tabsselect", playground.tabSelected);
+ playground.processQueryParameters();
};
/**
@@ -102,7 +196,7 @@
try
{
$("#frame-errors").text("");
- var frame = JSON.parse($("#frame").val());
+ frame = JSON.parse($("#frame").val());
}
catch(e)
{
@@ -143,6 +237,28 @@
var turtle = forge.jsonld.turtle(input);
$("#turtle").html(playground.htmlEscape(turtle));
}
+
+ // generate a link for current data
+ var link = "?json-ld=" + encodeURIComponent(JSON.stringify(input));
+ if($("#frame").val().length > 0)
+ {
+ link += "&frame=" + encodeURIComponent(JSON.stringify(frame));
+ }
+ var permalink = '<a href="' + link + '">permalink</a>';
+ // size warning for huge links
+ if((window.location.protocol.length + 2 +
+ window.location.host.length + window.location.pathname.length +
+ link.length) > 2048)
+ {
+ permalink += " (2KB+)"
+ }
+ $("#permalink")
+ .html(permalink)
+ .show();
+ }
+ else
+ {
+ $("#permalink").hide();
}
// Start the colorization delay
@@ -185,33 +301,74 @@
};
/**
- * Callback when an example button is clicked.
+ * Populate the UI with markup and frame JSON. The data parameter should
+ * have a 'markup' field and optional 'frame' field that contain a
+ * serialized JSON string.
+ *
+ * @param data object with optional 'markup' and 'frame' fields.
+ */
+ playground.populateWithJSON = function(data)
+ {
+ var hasData = false;
+
+ if('markup' in data && data.markup !== null)
+ {
+ hasData = true;
+ // fill the markup box with the example
+ $("#markup").val(js_beautify(
+ data.markup,
+ { "indent_size": 3, "brace_style": "expand" }));
+ }
+
+ if('frame' in data && data.frame !== null)
+ {
+ hasData = true;
+ // fill the frame input box with the example frame
+ $("#frame").val(js_beautify(
+ data.frame,
+ { "indent_size": 3, "brace_style": "expand" }));
+ }
+ else
+ {
+ $("#frame").val("{}");
+ }
+
+ if(hasData)
+ {
+ // perform processing on the data provided in the input boxes
+ playground.process();
+
+ // apply the syntax colorization
+ prettyPrint();
+ }
+ };
+
+ /**
+ * Populate the UI with a named example.
*
* @param name the name of the example to pre-populate the input boxes.
*/
- playground.populate = function(name)
+ playground.populateWithExample = function(name)
{
+ var data = {
+ markup: null,
+ frame: null
+ };
+
if(name in playground.examples)
{
- // fill the markup box with the example
- $("#markup").val(js_beautify(JSON.stringify(playground.examples[name]),
- { "indent_size": 3, "brace_style": "expand" }));
- $("#frame").val("{}");
+ // fill the markup with the example
+ data.markup = JSON.stringify(playground.examples[name]);
if(name in playground.frames)
{
- // fill the frame input box with the example frame
- $("#frame").val(js_beautify(
- JSON.stringify(playground.frames[name]),
- { "indent_size": 3, "brace_style": "expand" }));
+ // fill the frame with the example frame
+ data.frame = JSON.stringify(playground.frames[name]);
}
}
- // perform processing on the data provided in the input boxes
- playground.process();
-
- // apply the syntax colorization
- prettyPrint();
+ // populate with the example
+ playground.populateWithJSON(data);
};
})(jQuery);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/requirements/ED/20110713/index.html Tue Jul 26 18:11:39 2011 -0400
@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>JSON-LD Requirements</title>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!--
+ === NOTA BENE ===
+ For the three scripts below, if your spec resides on dev.w3 you can check them
+ out in the same tree and use relative links so that they'll work offline,
+ -->
+<script type="text/javascript"
+ src="http://dev.w3.org/2009/dap/ReSpec.js/js/respec.js" class="remove">
+ </script>
+<script type="text/javascript" class="remove">
+
+ var preProc = {
+ apply: function(c) {
+ // extend the bibliography entries
+
+ // process the document before anything else is done
+ var refs = document.querySelectorAll('adef') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var sp = document.createElement( 'dfn' ) ;
+ var tit = item.getAttribute('title') ;
+ if (!tit) {
+ tit = con;
+ }
+ sp.className = 'adef' ;
+ sp.title=tit ;
+ sp.innerHTML = con ;
+ p.replaceChild(sp, item) ;
+ }
+ refs = document.querySelectorAll('aref') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var sp = document.createElement( 'a' ) ;
+ sp.className = 'aref' ;
+ sp.setAttribute('title', con);
+ sp.innerHTML = '@'+con ;
+ p.replaceChild(sp, item) ;
+ }
+ // local datatype references
+ refs = document.querySelectorAll('ldtref') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ if (!item) continue ;
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var ref = item.getAttribute('title') ;
+ if (!ref) {
+ ref = item.textContent ;
+ }
+ if (ref) {
+ ref = ref.replace(/\n/g, '_') ;
+ ref = ref.replace(/\s+/g, '_') ;
+ }
+ var sp = document.createElement( 'a' ) ;
+ sp.className = 'datatype';
+ sp.title = ref ;
+ sp.innerHTML = con ;
+ p.replaceChild(sp, item) ;
+ }
+ // external datatype references
+ refs = document.querySelectorAll('dtref') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ if (!item) continue ;
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var ref = item.getAttribute('title') ;
+ if (!ref) {
+ ref = item.textContent ;
+ }
+ if (ref) {
+ ref = ref.replace(/\n/g, '_') ;
+ ref = ref.replace(/\s+/g, '_') ;
+ }
+ var sp = document.createElement( 'a' ) ;
+ sp.className = 'externalDFN';
+ sp.title = ref ;
+ sp.innerHTML = con ;
+ p.replaceChild(sp, item) ;
+ }
+ // now do terms
+ refs = document.querySelectorAll('tdef') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ if (!item) continue ;
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var ref = item.getAttribute('title') ;
+ if (!ref) {
+ ref = item.textContent ;
+ }
+ if (ref) {
+ ref = ref.replace(/\n/g, '_') ;
+ ref = ref.replace(/\s+/g, '_') ;
+ }
+ var sp = document.createElement( 'dfn' ) ;
+ sp.title = ref ;
+ sp.innerHTML = con ;
+ p.replaceChild(sp, item) ;
+ }
+ // now term references
+ refs = document.querySelectorAll('tref') ;
+ for (var i = 0; i < refs.length; i++) {
+ var item = refs[i];
+ if (!item) continue ;
+ var p = item.parentNode ;
+ var con = item.innerHTML ;
+ var ref = item.getAttribute('title') ;
+ if (!ref) {
+ ref = item.textContent ;
+ }
+ if (ref) {
+ ref = ref.replace(/\n/g, '_') ;
+ ref = ref.replace(/\s+/g, '_') ;
+ }
+
+ var sp = document.createElement( 'a' ) ;
+ var id = item.textContent ;
+ sp.className = 'tref' ;
+ sp.title = ref ;
+ sp.innerHTML = con ;
+ p.replaceChild(sp, item) ;
+ }
+ }
+ } ;
+
+
+ var respecConfig = {
+ // specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
+ specStatus: "unofficial",
+ publishDate: "2011-07-13",
+
+ // the specification's short name, as in http://www.w3.org/TR/short-name/
+ shortName: "json-ld",
+ subtitle: "A Context-based JSON Serialization for Linked Data",
+ // if you wish the publication date to be other than today, set this
+ // publishDate: "2009-08-06",
+
+ // if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
+ // and its maturity status
+ previousPublishDate: "2011-07-03",
+ previousMaturity: "ED",
+ previousDiffURI: "http://json-ld.org/requirements/ED/20110703/index.html",
+ diffTool: "http://www.aptest.com/standards/htmldiff/htmldiff.pl",
+
+ // if there a publicly available Editor's Draft, this is the link
+ edDraftURI: "http://json-ld.org/requirements/latest/",
+
+ // if this is a LCWD, uncomment and set the end of its review period
+ // lcEnd: "2009-08-05",
+
+ // if you want to have extra CSS, append them to this list
+ // it is recommended that the respec.css stylesheet be kept
+ extraCSS: [
+ "http://dev.w3.org/2009/dap/ReSpec.js/css/respec.css"
+ ],
+
+ // editors, add as many as you like
+ // only "name" is required
+ editors: [
+ { name: "Gregg Kellogg", url: "http://greggkellogg.net/",
+ company: "Kellogg Associates" },
+ ],
+
+ // authors, add as many as you like.
+ // This is optional, uncomment if you have authors as well as editors.
+ // only "name" is required. Same format as editors.
+
+ // name of the WG
+ wg: "Linked Data in JSON Interest Group",
+
+ // URI of the public WG page
+ wgURI: "",
+
+ // name (with the @w3c.org) of the public mailing to which comments are due
+ wgPublicList: "",
+
+ // URI of the patent status for this WG, for Rec-track documents
+ // !!!! IMPORTANT !!!!
+ // This is important for Rec-track documents, do not copy a patent URI from a random
+ // document unless you know what you're doing. If in doubt ask your friendly neighbourhood
+ // Team Contact.
+ wgPatentURI: "",
+ maxTocLevel: 3,
+ preProcess: [ preProc ]
+ //alternateFormats: [ {uri: "diff-20110507.html", label: "diff to previous version"} ],
+ };
+ </script>
+<style>
+.diff { font-weight:bold; color:#0a3; }
+</style>
+</head>
+
+<body>
+<section id="abstract">
+<p>
+ This document attempts to gather requirements for Linked Data in JSON (JSON-LD)
+ in order to create an objective measure with which to evaluate the
+ <cite><a href="/spec/latest/">JSON-LD Specification</a></cite>.
+</p>
+</section>
+
+<section id='sotd'>
+<p>This document is an experimental work in progress.</p>
+<!-- <p>
+This document has been reviewed by W3C Members, by software
+developers, and by other W3C groups and interested parties, and is
+endorsed by the Director as a W3C Recommendation. It is a stable
+document and may be used as reference material or cited from another
+document. W3C's role in making the Recommendation is to draw attention
+to the specification and to promote its widespread deployment. This
+enhances the functionality and interoperability of the Web.
+</p> -->
+</section>
+
+<section>
+<h1>Introduction</h1>
+</section>
+
+<section><h1>Definitions</h1>
+ <dl>
+ <dt><tdef>JSON</tdef></dt><dd>
+ <abbr title="JavaScript Object Notation">JSON</abbr> (JavaScript Object Notation)
+ [[!RFC4627]]
+ is a simple way to express objects in a syntax compatible with JavaScript.
+ </dd>
+ <dt>Linked Data</dt><dd>
+ According to <cite><a
+ href="http://en.wikipedia.org/wiki/Linked_Data">Wikipedia</a></cite>, Linked Data ...
+ <blockquote cite="http://en.wikipedia.org/wiki/Linked_Data">
+ describes a method of publishing structured data so that it can be interlinked and
+ become more useful. It builds upon standard Web technologies such as HTTP and URIs,
+ but rather than using them to serve web pages for human readers, it extends them to
+ share information in a way that can be read automatically by computers. This
+ enables data from different sources to be connected and queried.
+ </blockquote>
+ </dd>
+ <dt><tdef>JSON Object</tdef></dt><dd>
+ From [[RFC4627]]: <blockquote>
+ An object structure is represented as a pair of curly brackets surrounding zero or
+ more name/value pairs (or members). A name is a string. A single colon comes after
+ each name, separating the name from the value. A single comma separates a value
+ from a following name. The names within an object SHOULD be unique.
+ </blockquote>
+ </dd>
+ </dl>
+</section>
+
+<section><h1>Requirements</h1>
+ <section><h2>Linked Data</h2>
+ <p>
+ The following are taken to be assertions about the meaning of <tref>Linked Data</tref>.
+ </p>
+ <p class="note">
+ This section is intended to abstractly describe the concept of <tref>Linked
+ Data</tref>. This does not necessarily relate concepts directly to a JSON syntactic
+ expression; that is left for the following section.
+ </p>
+ <ol>
+ <li><tdef>Linked Data</tdef> is a set of documents, each containing a representation of a linked data graph.</li>
+ <li>A <tdef>linked data graph</tdef> is a labeled directed graph, where nodes are <tref>subject</tref>s or <tref>object</tref>s, and edges are properties.</li>
+ <li>A <tdef>subject</tdef> is any node in a <tref>linked data graph</tref> with at least one outgoing edge.</li>
+ <li>
+ A <tref>subject</tref> MAY be labeled with a IRI.
+ <p class="issue">
+ There is some controversy over the use of MAY vs. SHOULD. Could a subject be labeled with a literal?
+ Can nodes be unlabeled (i.e., like RDF Blank Nodes)?
+ </p>
+ </li>
+ <li>A <tdef>property</tdef> is an edge of the <tref>linked data graph</tref>.</li>
+ <li>A <tref>property</tref> SHOULD be labeled with an IRI.</li>
+ <li>An <tdef>object</tdef> is a node in a <tref>linked data graph</tref> with at least one incoming edge.</li>
+ <li>An <tref>object</tref> MAY be labeled with an IRI.</li>
+ <li>An IRI that is a label in a <tref>linked data graph</tref> SHOULD be dereferencable to a <tref>Linked Data</tref> document describing the labeled <tref>subject</tref>, <tref>object</tref> or <tref>property</tref>.</li>
+ <li>A <tdef>literal</tdef> is an <tref>object</tref> with a label that is not an IRI</li>
+ </ol>
+ </section>
+ <section><h2>JSON-LD</h2>
+ <p>The following are taken to be requirements for creating <tref>Linked Data</tref> using JSON.</p>
+ <p class="issue">
+ This section has not been discussed on a teleconference
+ </p>
+ <ol>
+ <li>A JSON-LD document MUST be able to express a <tref>linked data graph</tref>.</li>
+ <li>
+ A JSON-LD document uses <trefs>JSON object</trefs>s, arrays, numbers, strings and
+ other literal names to express semantic information.
+ </li>
+ <li>A <tref>subject</tref> is represented with a <tref>JSON object</tref>.</li>
+ <li>There MUST be a way label a <tref>JSON object</tref> with an IRI.</li>
+ <li>There MUST be a way to reference an un-labeled JSON object that does not have a direct child relationship.</li>
+ <li>JSON name/value pairs are used to describe property-object relationships.</li>
+ <li>There MUST be a way to associate a IRI with the name in a JSON name/value pair.</li>
+ <li>JSON strings MAY represent literals.</li>
+ <li>JSON strings MAY represent IRIs.</li>
+ <li>There MUST be a way to determine if a JSON value represents a IRI.</li>
+ <li>There SHOULD be a way to associate a datatype IRI with a literal JSON value.</li>
+ <li>JSON booleans, numbers and other literal values represent specific datatyped literals.</li>
+ <li>A JSON array MAY be used to associate multiple <tref>object</tref>s with a <tref>subject</tref> through a common <tref>property</tref>.</li>
+ <li>A JSON array MUST NOT be used to imply an order to the component entities.</li>
+ </ol>
+ </section>
+</section>
+
+</body>
+</html>
+
--- a/requirements/latest/index.html Tue Jul 26 18:11:06 2011 -0400
+++ b/requirements/latest/index.html Tue Jul 26 18:11:39 2011 -0400
@@ -136,8 +136,7 @@
var respecConfig = {
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "unofficial",
- //publishDate: "2011-07-03",
- //copyrightStart: "2010",
+ //publishDate: "2011-07-13",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "json-ld",
@@ -147,13 +146,13 @@
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
- previousPublishDate: "2011-05-07",
+ previousPublishDate: "2011-07-03",
previousMaturity: "ED",
- previousDiffURI: "http://json-ld.org/requirements/ED/20100703/index.html",
+ previousDiffURI: "http://json-ld.org/requirements/ED/20110703/index.html",
diffTool: "http://www.aptest.com/standards/htmldiff/htmldiff.pl",
// if there a publicly available Editor's Draft, this is the link
- edDraftURI: "http://json-ld.org/spec/latest/",
+ edDraftURI: "http://json-ld.org/requirements/latest/",
// if this is a LCWD, uncomment and set the end of its review period
// lcEnd: "2009-08-05",
@@ -233,7 +232,7 @@
[[!RFC4627]]
is a simple way to express objects in a syntax compatible with JavaScript.
</dd>
- <dt><tdef>Linked Data</tdef></dt><dd>
+ <dt>Linked Data</dt><dd>
According to <cite><a
href="http://en.wikipedia.org/wiki/Linked_Data">Wikipedia</a></cite>, Linked Data ...
<blockquote cite="http://en.wikipedia.org/wiki/Linked_Data">
@@ -266,62 +265,47 @@
expression; that is left for the following section.
</p>
<ol>
+ <li><tdef>Linked Data</tdef> is a set of documents, each containing a representation of a linked data graph.</li>
+ <li>A <tdef>linked data graph</tdef> is a labeled directed graph, where nodes are <tref>subject</tref>s or <tref>object</tref>s, and edges are properties.</li>
+ <li>A <tdef>subject</tdef> is any node in a <tref>linked data graph</tref> with at least one outgoing edge.</li>
<li>
- Linked Data is used to represent a directed graph, and within the context of Linked
- Data, the graph can be represented as (directed) edges between different nodes.
- Nodes may be labeled. Nodes are externally addressable if the label is a URI.
- <p class="note">
- Note, original approved wording was: <em>Linked Data is used to represent a
- directed graph, and within the context of Linked Data, the graph can be
- represented as connections between different nodes, nodes are subjects and
- objects, links are properties. Nodes may have identifiers that are URIs allowing
- them to be externally addressed.</em></p>
- </li>
- <li>A <tdef>subject</tdef> is any node in a directed graph with at least one outgoing edge.</li>
- <li>A <tref>subject</tref> MAY be labeled with a IRI.</li>
- <li class="issue">A <tref>subject</tref> without a IRI is scoped to the document in which it is expressed.</li>
- <li>A node may be unlabeled.</li>
- <li class="issue">An unlabeled node MAY be given an identifier for intra-document referencing.</li>
- <li>A <tdef>property</tdef> is an edge of the directed graph.</li>
- <li>A <tdef>property</tdef> SHOULD be labeled with an IRI.
- <p class="note">
- Using a IRI for a property is a best practice, as it allows the edge to be
- described unambiguously. Simply labeling an edge "homeAddress", for example, could
- be ambiguous. In the context of JSON-LD, this does not necessarily mean that an
- object key is represented directly be a URI; it may be simple term (NCName) which
- is mapped to a URI elsewhere (i.e., @context).
+ A <tref>subject</tref> MAY be labeled with a IRI.
+ <p class="issue">
+ There is some controversy over the use of MAY vs. SHOULD. Could a subject be labeled with a literal?
+ Can nodes be unlabeled (i.e., like RDF Blank Nodes)?
</p>
</li>
- <li>An <tdef>object</tdef> is a node in a directed graph with at least one incoming edge.</li>
- <li>An <tdef>object</tdef> MAY be labeled with an IRI.</li>
- <li class="issue">An <tref>object</tref> MAY be labeled with an IRI or a <tref>literal</t>.</li>
- <li class="issue">A <tdef>literal</tdef> MAY include a datatype or have a language.</li>
+ <li>A <tdef>property</tdef> is an edge of the <tref>linked data graph</tref>.</li>
+ <li>A <tref>property</tref> SHOULD be labeled with an IRI.</li>
+ <li>An <tdef>object</tdef> is a node in a <tref>linked data graph</tref> with at least one incoming edge.</li>
+ <li>An <tref>object</tref> MAY be labeled with an IRI.</li>
+ <li>An IRI that is a label in a <tref>linked data graph</tref> SHOULD be dereferencable to a <tref>Linked Data</tref> document describing the labeled <tref>subject</tref>, <tref>object</tref> or <tref>property</tref>.</li>
+ <li>A <tdef>literal</tdef> is an <tref>object</tref> with a label that is not an IRI</li>
</ol>
</section>
<section><h2>JSON-LD</h2>
- <p>The following are taken to be requirements for expressing JSON as <tref>Linked Data</tref>.</p>
+ <p>The following are taken to be requirements for creating <tref>Linked Data</tref> using JSON.</p>
<p class="issue">
This section has not been discussed on a teleconference
</p>
<ol>
- <li>A JSON-LD document MUST be able to express <tref>Linked Data</tref>.</li>
+ <li>A JSON-LD document MUST be able to express a <tref>linked data graph</tref>.</li>
<li>
A JSON-LD document uses <trefs>JSON object</trefs>s, arrays, numbers, strings and
other literal names to express semantic information.
</li>
<li>A <tref>subject</tref> is represented with a <tref>JSON object</tref>.</li>
- <li>There MUST be a way to associate a IRI with a <tref>subject</tref>.</li>
- <li>There MAY be a way to associate a <tref>BNode</tref> identifier with a <tref>subject</tref>.</li>
- <li>JSON name/value pairs are used to describe property-object (or attribute-value) pairs.</li>
- <li>There MUST be a way to associate a IRI with a JSON name.</li>
+ <li>There MUST be a way label a <tref>JSON object</tref> with an IRI.</li>
+ <li>There MUST be a way to reference an un-labeled JSON object that does not have a direct child relationship.</li>
+ <li>JSON name/value pairs are used to describe property-object relationships.</li>
+ <li>There MUST be a way to associate a IRI with the name in a JSON name/value pair.</li>
<li>JSON strings MAY represent literals.</li>
<li>JSON strings MAY represent IRIs.</li>
<li>There MUST be a way to determine if a JSON value represents a IRI.</li>
- <li>There SHOULD be a way to associate a datatype with a literal JSON value.</li>
- <li>JSON numbers and other literal values represent specific typed literals.</li>
+ <li>There SHOULD be a way to associate a datatype IRI with a literal JSON value.</li>
+ <li>JSON booleans, numbers and other literal values represent specific datatyped literals.</li>
<li>A JSON array MAY be used to associate multiple <tref>object</tref>s with a <tref>subject</tref> through a common <tref>property</tref>.</li>
<li>A JSON array MUST NOT be used to imply an order to the component entities.</li>
- <li>JSON-LD MAY provide a way to express an ordered relationship.</li>
</ol>
</section>
</section>