Merge branch 'master' of github.com:json-ld/json-ld.org
authorManu Sporny <msporny@digitalbazaar.com>
Tue, 26 Jul 2011 18:11:39 -0400
changeset 78 d2d545c77e3f
parent 74 f17d652d1d92 (current diff)
parent 77 736ada9aaa55 (diff)
child 79 390a52145e4f
Merge branch 'master' of github.com:json-ld/json-ld.org
--- /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>