svg2-tools: Add <edit:script> and custom replacement functions; keep ...

details:   https://svgwg.org/hg/svg2-tools/rev/6b530890be51
branches:  
changeset: 78:6b530890be51
user:      Cameron McCormack <cam@mcc.id.au>
date:      Sun Apr 07 16:03:59 2013 +1000
description:
Add <edit:script> and custom replacement functions; keep track of which spec each imported definitions file comes from.

diffstat:

 publish/config.js      |  14 +++++-
 publish/definitions.js |  92 ++++++++++++++++++++++++++++++++++++++++---------
 publish/processing.js  |  66 ++++++++++++++++++++++-------------
 3 files changed, 127 insertions(+), 45 deletions(-)

diffs (391 lines):

diff --git a/publish/config.js b/publish/config.js
--- a/publish/config.js
+++ b/publish/config.js
@@ -140,23 +140,31 @@ function Config(filename) {
     latestRec:  attr(versions, 'latestRec', 'href')
   };
 
   this.toc = attr(root, 'toc', 'href');
   this.elementIndex = attr(root, 'elementindex', 'href');
   this.attributeIndex = attr(root, 'attributeindex', 'href');
   this.propertyIndex = attr(root, 'propertyindex', 'href');
 
-  var definitionsFilenamesAndBases = [];
+  var definitionInfos = [];
   for (var n = root.firstChild; n; n = n.nextSibling) {
     if (n.nodeName == 'definitions') {
-      definitionsFilenamesAndBases.push([n.getAttribute('href'), n.getAttribute('base') || null]);
+      definitionInfos.push({
+        href: n.getAttribute('href'),
+        base: n.getAttribute('base') || null,
+        specid: n.getAttribute('specid') || null,
+        mainspec: n.getAttribute('mainspec') || null
+      });
     }
   }
-  this.definitions = definitions.load(definitionsFilenamesAndBases.reverse());
+  var allDefinitions = definitions.load(definitionInfos);
+  this.definitions = allDefinitions.definitions;
+  this.definitionsBySpec = allDefinitions.definitionsBySpec;
+  this.definitionMainSpecs = allDefinitions.mainSpecs;
 
   this.resources = [];
   for (var n = root.firstChild; n; n = n.nextSibling) {
     if (n.nodeName == 'resource') {
       this.resources.push(n.getAttribute('href'));
     }
   }
 
diff --git a/publish/definitions.js b/publish/definitions.js
--- a/publish/definitions.js
+++ b/publish/definitions.js
@@ -294,187 +294,245 @@ Definitions.prototype.formatNameLink = f
   }
   if (types.length > 1) {
     utils.warn('ambiguous name "' + name + '" matching ' + types.join(" and "), context);
     return utils.parse('<span class="xxx">@@ ambiguous name "{{name}}" (matches {{types}})</span>', { name: name, types: types.join(' and ') });
   }
   return (element || attribute || property).formatLink(omitQuotes);
 };
 
-function loadInto(filename, base, defs) {
+function loadInto(filename, base, specid, defs) {
   var doc = utils.parseXML(filename);
 
   // XXX Handle <import>.
 
   forEachChild(doc.documentElement, 'element', function(e) {
     var element = new Element({
       name: e.getAttribute('name'),
       href: utils.resolveURL(base, e.getAttribute('href')),
       contentModel: e.getAttribute('contentmodel'),
       elementCategories: utils.splitList(e.getAttribute('elementcategories')),
       elements: utils.splitList(e.getAttribute('elements')),
       attributeCategories: utils.splitList(e.getAttribute('attributecategories')),
       commonAttributes: utils.splitList(e.getAttribute('attributes')),
       interfaces: utils.splitList(e.getAttribute('interfaces')),
       specificAttributes: [],
-      categories: { }
+      categories: { },
+      specid: specid
     });
 
     forEachChild(e, 'attribute', function(c) {
       element.specificAttributes.push(new Attribute({
         name: c.getAttribute('name'),
         href: utils.resolveURL(base, c.getAttribute('href')),
-        animatable: c.getAttribute('animatable') == 'yes'
+        animatable: c.getAttribute('animatable') == 'yes',
+        specid: specid
       }));
     });
 
     forEachChild(e, 'contentmodel', function(c) {
       element.contentModelDescription = utils.cloneChildren(c);
     });
 
     defs.elements[element.name] = element;
   });
 
   forEachChild(doc.documentElement, 'elementcategory', function(ec) {
     var category = new ElementCategory({
       name: ec.getAttribute('name'),
       href: utils.resolveURL(base, ec.getAttribute('href')),
-      elements: utils.splitList(ec.getAttribute('elements'))
+      elements: utils.splitList(ec.getAttribute('elements')),
+      specid: specid
     });
 
     defs.elementCategories[category.name] = category;
   });
 
   forEachChild(doc.documentElement, 'attribute', function(a) {
     var attribute = new Attribute({
       name: a.getAttribute('name'),
       href: utils.resolveURL(base, a.getAttribute('href')),
-      animatable: a.getAttribute('animatable') == 'yes'
+      animatable: a.getAttribute('animatable') == 'yes',
+      specid: specid
     });
     if (a.hasAttribute('elements')) {
       attribute.elements = utils.set(utils.splitList(a.getAttribute('elements')));
       defs.commonAttributesForElements.push(attribute);
     } else {
       defs.commonAttributes[attribute.name] = attribute;
     }
   });
 
   forEachChild(doc.documentElement, 'attributecategory', function(ac) {
     var category = new AttributeCategory({
       name: ac.getAttribute('name'),
       href: utils.resolveURL(base, ac.getAttribute('href')),
       attributes: [],
       commonAttributes: utils.splitList(ac.getAttribute('attributes')),
-      presentationAttributes: utils.splitList(ac.getAttribute('presentationattributes'))
+      presentationAttributes: utils.splitList(ac.getAttribute('presentationattributes')),
+      specid: specid
     });
 
     forEachChild(ac, 'attribute', function(a) {
       category.attributes.push(new Attribute({
         name: a.getAttribute('name'),
         href: utils.resolveURL(base, a.getAttribute('href')),
-        animatable: a.getAttribute('animatable') == 'yes'
+        animatable: a.getAttribute('animatable') == 'yes',
+        specid: specid
       }));
     });
 
     defs.attributeCategories[category.name] = category;
   });
 
   forEachChild(doc.documentElement, 'property', function(p) {
     var property = new Property({
       name: p.getAttribute('name'),
       href: utils.resolveURL(base, p.getAttribute('href')),
+      specid: specid
     });
 
     defs.properties[property.name] = property;
 
     var presentationAttribute = new Attribute({
       name: property.name,
       href: property.href,
-      property: property.name
+      property: property.name,
+      specid: specid
     });
     defs.presentationAttributes[property.name] = presentationAttribute;
   });
 
   forEachChild(doc.documentElement, 'interface', function(i) {
     var intf = new Interface({
       name: i.getAttribute('name'),
       href: utils.resolveURL(base, i.getAttribute('href')),
+      specid: specid
     });
 
     defs.interfaces[intf.name] = intf;
   });
 
   forEachChild(doc.documentElement, 'symbol', function(s) {
     var symbol = new Symbol({
       name: s.getAttribute('name'),
       href: utils.resolveURL(base, s.getAttribute('href')),
+      specid: specid
     });
 
     defs.symbols[symbol.name] = symbol;
   });
 
   forEachChild(doc.documentElement, 'term', function(t) {
     var term = new Term({
       name: t.getAttribute('name'),
       href: utils.resolveURL(base, t.getAttribute('href')),
+      specid: specid
     });
 
     if (t.firstChild) {
       term.markup = utils.cloneChildren(t);
     }
 
     defs.terms[normalizeTermName(term.name)] = term;
   });
 }
 
-function resolve(defs) {
+function resolve(defs, mainspecDefs) {
   for (var name in defs.elements) {
     var element = defs.elements[name];
     element.attributes = { };
     element.attributeOrder = [];
     for (var i = 0; i < element.attributeCategories.length; i++) {
       var catName = element.attributeCategories[i];
-      var cat = defs.attributeCategories[catName];
+      var cat = defs.attributeCategories[catName] ||
+                mainspecDefs && mainspecDefs.attributeCategories[catName];
       if (cat) {
         for (var j = 0; j < cat.attributes.length; j++) {
           element.attributes[cat.attributes[j].name] = cat.attributes[j];
           element.attributeOrder.push(cat.attributes[j].name);
         }
       }
     }
+    if (mainspecDefs) {
+      for (var i = 0; i < mainspecDefs.commonAttributesForElements.length; i++) {
+        var attr = mainspecDefs.commonAttributesForElements[i];
+        if (attr.elements[element.name]) {
+          element.attributes[attr.name] = attr;
+          element.attributeOrder.push(attr.name);
+        }
+      }
+    }
     for (var i = 0; i < defs.commonAttributesForElements.length; i++) {
       var attr = defs.commonAttributesForElements[i];
       if (attr.elements[element.name]) {
         element.attributes[attr.name] = attr;
         element.attributeOrder.push(attr.name);
       }
     }
     for (var i = 0; i < element.commonAttributes.length; i++) {
       var attrName = element.commonAttributes[i];
-      if (defs.commonAttributes[attrName]) {
-        element.attributes[attrName] = defs.commonAttributes[attrName];
+      var commonAttribute = defs.commonAttributes[attrName] ||
+                            mainspecDefs && mainspecDefs.commonAttributes[attrName];
+      if (commonAttribute) {
+        element.attributes[attrName] = commonAttribute;
         element.attributeOrder.push(attrName);
       }
     }
     for (var i = 0; i < element.specificAttributes.length; i++) {
       var attr = element.specificAttributes[i];
       element.attributes[attr.name] = attr;
       element.attributeOrder.push(attr.name);
     }
   }
 
+  if (mainspecDefs) {
+    for (var name in mainspecDefs.elementCategories) {
+      var cat = mainspecDefs.elementCategories[name];
+      for (var i = 0; i < cat.elements.length; i++) {
+        var eltName = cat.elements[i];
+        if (defs.elements[eltName]) {
+          defs.elements[eltName].categories[name] = cat;
+        }
+      }
+    }
+  }
   for (var name in defs.elementCategories) {
     var cat = defs.elementCategories[name];
     for (var i = 0; i < cat.elements.length; i++) {
       var eltName = cat.elements[i];
-      defs.elements[eltName].categories[name] = cat;
+      var elt = defs.elements[eltName] ||
+                mainspecDefs && mainspecDefs.elements[eltName];
+      if (elt) {
+        elt.categories[name] = cat;
+      }
     }
   }
 }
 
-exports.load = function(filenamesAndBases) {
+exports.load = function(infos) {
   var defs = new Definitions();
-  for (var i = 0; i < filenamesAndBases.length; i++) {
-    loadInto(filenamesAndBases[i][0], filenamesAndBases[i][1], defs);
+  var defsBySpec = { };
+  var mainSpecs = { };
+  infos.reverse();
+  for (var i = 0; i < infos.length; i++) {
+    var href = infos[i].href;
+    var base = infos[i].base;
+    var specid = infos[i].specid;
+    loadInto(href, base, specid, defs);
+    if (specid) {
+      defsBySpec[specid] = new Definitions();
+      loadInto(href, base, specid, defsBySpec[specid]);
+    }
+  }
+  for (var i = 0; i < infos.length; i++) {
+    var specid = infos[i].specid;
+    if (specid) {
+      var mainspec = infos[i].mainspec;
+      resolve(defsBySpec[specid], mainspec && defsBySpec[mainspec]);
+      if (mainspec) {
+        mainSpecs[specid] = mainspec;
+      }
+    }
   }
   resolve(defs);
-  return defs;
+  return { definitions: defs, definitionsBySpec: defsBySpec, mainSpecs: mainSpecs };
 };
diff --git a/publish/processing.js b/publish/processing.js
--- a/publish/processing.js
+++ b/publish/processing.js
@@ -665,42 +665,58 @@ function doWhenPublished(conf, page, n) 
     return utils.replaceWithChildren(n);
   }
 }
 
 function doShortTitle(conf, page, n) {
   return utils.replace(n, n.ownerDocument.createTextNode(conf.shortTitle));
 }
 
+function doScript(conf, page, n) {
+  with ({ processing: exports,
+          utils: utils,
+          namespaces: namespaces }) {
+    eval(n.textContent);
+  }
+}
+
+var replacementFunctions = {
+  minitoc: doMiniTOC,
+  fulltoc: doFullTOC,
+  completeidl: doCompleteIDL,
+  interface: doInterface,
+  example: doExample,
+  includefile: doIncludeFile,
+  elementsummary: doElementSummary,
+  maturity: doLongMaturity,
+  date: doDate,
+  thisversion: doThisVersion,
+  latestversion: doLatestVersion,
+  includelatesteditorsdraft: doIncludeLatestEditorsDraft,
+  previousversion: doPreviousVersion,
+  copyright: doCopyright,
+  locallink: doLocalLink,
+  attributetable: doAttributeTable,
+  elementindex: doElementIndex,
+  elementcategory: doElementCategory,
+  attributecategory: doAttributeCategory,
+  elementswithattributecategory: doElementsWithAttributeCategory,
+  whenpublished: doWhenPublished,
+  shorttitle: doShortTitle,
+  script: doScript
+};
+
+exports.defineReplacement = function(elementName, fn) {
+  if (replacementFunctions[elementName]) {
+    throw 'replacement function for <edit:' + elementName + '> already defined';
+  }
+  replacementFunctions[elementName] = fn;
+};
+
 exports.processReplacements = function(conf, page, doc) {
-  var replacementFunctions = {
-    minitoc: doMiniTOC,
-    fulltoc: doFullTOC,
-    completeidl: doCompleteIDL,
-    interface: doInterface,
-    example: doExample,
-    includefile: doIncludeFile,
-    elementsummary: doElementSummary,
-    maturity: doLongMaturity,
-    date: doDate,
-    thisversion: doThisVersion,
-    latestversion: doLatestVersion,
-    includelatesteditorsdraft: doIncludeLatestEditorsDraft,
-    previousversion: doPreviousVersion,
-    copyright: doCopyright,
-    locallink: doLocalLink,
-    attributetable: doAttributeTable,
-    elementindex: doElementIndex,
-    elementcategory: doElementCategory,
-    attributecategory: doAttributeCategory,
-    elementswithattributecategory: doElementsWithAttributeCategory,
-    whenpublished: doWhenPublished,
-    shorttitle: doShortTitle
-  };
-
   utils.forEachNode(doc, function(n) {
     if (n.nodeType == n.ELEMENT_NODE &&
         n.namespaceURI == namespaces.edit &&
         n.localName != 'with') {
       if (!replacementFunctions[n.localName]) {
         utils.warn('unknown element "edit:' + n.localName + '"', n);
       } else {
         return replacementFunctions[n.localName](conf, page, n);

Received on Sunday, 7 April 2013 06:05:05 UTC