Update to latest jsonld.js.
authorDave Longley <dlongley@digitalbazaar.com>
Fri, 15 Feb 2013 00:38:57 -0500
changeset 1265 ec12e249afa6
parent 1264 58ce85eb695f
child 1266 a2bddb703b43
Update to latest jsonld.js.
playground/jsonld.js
--- a/playground/jsonld.js	Fri Feb 15 00:37:06 2013 -0500
+++ b/playground/jsonld.js	Fri Feb 15 00:38:57 2013 -0500
@@ -3713,8 +3713,10 @@
   if(typeOrLanguageValue === '@id' && _isSubjectReference(value)) {
     // try to compact value to a term
     var term = _compactIri(
-      activeCtx, value['@id'], null, {vocab: true, base: true});
-    if(term in activeCtx.mappings) {
+      activeCtx, value['@id'], null, {vocab: true});
+    if(term in activeCtx.mappings &&
+      activeCtx.mappings[term] &&
+      activeCtx.mappings[term]['@id'] === value['@id']) {
       // prefer @vocab
       options = ['@vocab', '@id', '@none'];
     }
@@ -3777,7 +3779,6 @@
  * @param iri the IRI to compact.
  * @param value the value to check or null.
  * @param relativeTo options for how to compact IRIs:
- *          base: true to compact against the base IRI, false not to.
  *          vocab: true to split after @vocab, false not to.
  * @param parent the parent element for the value.
  *
@@ -3951,8 +3952,8 @@
     }
   }
 
-  // no compaction choices, return IRI as is
-  return iri;
+  // compact IRI relative to base
+  return _removeBase(activeCtx['@base'], iri);
 }
 
 /**
@@ -4013,7 +4014,7 @@
     // compact @type IRI
     if('@type' in value) {
       rval[_compactIri(activeCtx, '@type')] = _compactIri(
-        activeCtx, value['@type'], null, {base: true, vocab: true});
+        activeCtx, value['@type'], null, {vocab: true});
     }
     // alias @language
     else if('@language' in value) {
@@ -4029,19 +4030,16 @@
   // value is a subject reference
   var expandedProperty = _expandIri(activeCtx, activeProperty);
   var type = jsonld.getContextValue(activeCtx, activeProperty, '@type');
-  var term = _compactIri(
-    activeCtx, value['@id'], null, {
-      vocab: type === '@vocab',
-      base: true
-    });
+  var compacted = _compactIri(
+    activeCtx, value['@id'], null, {vocab: type === '@vocab'});
 
   // compact to scalar
   if(type === '@id' || type === '@vocab' || expandedProperty === '@graph') {
-    return term;
+    return compacted;
   }
 
   var rval = {};
-  rval[_compactIri(activeCtx, '@id')] = term;
+  rval[_compactIri(activeCtx, '@id')] = compacted;
   return rval;
 }
 
@@ -4479,7 +4477,7 @@
   else {
     path = base.pathname;
 
-    // prepend last directory for base
+    // use up to last directory for base
     if(rel.pathname !== '') {
       path = path.substr(0, path.lastIndexOf('/') + 1) + rel.pathname;
     }
@@ -4527,7 +4525,68 @@
     path += rel.hash;
   }
 
-  return (base.protocol || '') + '//' + authority + path;
+  var rval = (base.protocol || '') + '//';
+  if(base.auth) {
+    rval += base.auth + '@';
+  }
+  rval += authority + path;
+
+  return rval;
+}
+
+/**
+ * Removes a base IRI from the given absolute IRI.
+ *
+ * @param base the base IRI.
+ * @param iri the absolute IRI.
+ *
+ * @return the relative IRI if relative to base, otherwise the absolute IRI.
+ */
+function _removeBase(base, iri) {
+  if(_isString(base)) {
+    base = jsonld.url.parse(base || '');
+    base.pathname = base.pathname || '';
+  }
+
+  // establish base root
+  var root = (base.protocol || '') + '//';
+  if(base.auth) {
+    root += base.auth + '@';
+  }
+  root += (base.host || '');
+
+  // IRI not relative to base
+  if(iri.indexOf(root) !== 0) {
+    return iri;
+  }
+
+  // remove path segments that match
+  var baseSegments = base.pathname.split('/');
+  var iriSegments = iri.substr(root.length).split('/');
+  while(baseSegments.length > 0 && iriSegments.length > 0) {
+    if(baseSegments[0] !== iriSegments[0]) {
+      break;
+    }
+    baseSegments.shift();
+    iriSegments.shift();
+  }
+
+  // use '../' for each non-matching base segment
+  var rval = '';
+  if(baseSegments.length > 0) {
+    // do not count the last segment if it isn't a path (doesn't end in '/')
+    if(base.pathname.indexOf('/', base.pathname.length - 1) === -1) {
+      baseSegments.pop();
+    }
+    for(var i = 0; i < baseSegments.length; ++i) {
+      rval += '../';
+    }
+  }
+
+  // prepend remaining segments
+  rval += iriSegments.join('/');
+
+  return rval;
 }
 
 /**