]> git.parisson.com Git - pdf.js.git/commitdiff
Metadata parsing/serialization
authorSaebekassebil <saebekassebil@gmail.com>
Sat, 24 Mar 2012 18:59:51 +0000 (19:59 +0100)
committerSaebekassebil <saebekassebil@gmail.com>
Sat, 24 Mar 2012 18:59:51 +0000 (19:59 +0100)
Makefile
make.js
src/metadata.js [new file with mode: 0644]
src/obj.js
web/viewer.html
web/viewer.js

index 62565670ade9c659a537f03b2312e91ad4c3ba75..3cc423350c8fb5815cdb15b0987ee3a2f54690ce 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,7 @@ PDF_JS_FILES = \
   ../external/jpgjs/jpg.js \
   jpx.js \
   bidi.js \
+  metadata.js \
        $(NULL)
 
 # make server
diff --git a/make.js b/make.js
index 33771aeb7c5a8594a229246940e8e1cb1a35ba8e..69732667f836d96b601a8f7497bae42b82df9ae8 100755 (executable)
--- a/make.js
+++ b/make.js
@@ -97,7 +97,8 @@ target.bundle = function() {
         'worker.js',
         '../external/jpgjs/jpg.js',
         'jpx.js',
-        'bidi.js'];
+        'bidi.js',
+        'metadata-js'];
 
   if (!exists(BUILD_DIR))
     mkdir(BUILD_DIR);
diff --git a/src/metadata.js b/src/metadata.js
new file mode 100644 (file)
index 0000000..68b1976
--- /dev/null
@@ -0,0 +1,80 @@
+var Metadata = (function MetadataClosure() {
+  function Metadata(meta) {
+    if (typeof meta === 'string') {
+      var parser = new DOMParser();
+      meta = parser.parseFromString(meta, 'application/xml');
+    } else if (!(meta instanceof Document)) {
+      error('Metadata: Invalid metadata object');
+    }
+
+    this.metaDocument = meta;
+    this.metadata = {};
+    this.parse();
+  }
+
+  Metadata.prototype = {
+    parse: function() {
+      var doc = this.metaDocument;
+      var rdf = doc.documentElement;
+      if (rdf.tagName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
+        rdf = rdf.firstChild;
+        while (rdf.nodeName && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
+          rdf = rdf.nextSibling;
+        }
+      }
+      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf' || !rdf.hasChildNodes()) {
+        return;
+      }
+
+      var childNodes = rdf.childNodes, desc, namespace, entries, entry;
+
+      for (var i = 0, length = childNodes.length; i < length; i++) {
+        desc = childNodes[i];
+        if (desc.nodeName.toLowerCase() !== 'rdf:description') {
+          continue;
+        }
+
+        entries = [];
+        for (var ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
+            entries.push(desc.childNodes[ii]);
+          }
+        }
+
+        for (ii = 0, iLength = entries.length; ii < iLength; ii++) {
+          var entry = entries[ii];
+          var name = entry.nodeName.toLowerCase();
+          var entryName = name.split(':');
+          entryName = (entryName.length > 1) ? entryName[1] : entryName[0];
+          switch (name) {
+            case 'pdf:moddate':
+            case 'xap:createdate':
+            case 'xap:metadatadate':
+            case 'xap:modifydate':
+              this.metadata[entryName] = new Date(entry.textContent.trim());
+              break;
+
+            default:
+              // For almost all entries we just add them to the metadata object
+              if (this.metadata[entryName]) {
+                this.metadata[name] = entry.textContent.trim();
+              } else {
+                this.metadata[entryName] = entry.textContent.trim();
+              }
+              break;
+          }
+        }
+      }
+    },
+
+    get: function(name) {
+      return this.metadata[name] || null;
+    },
+
+    has: function(name) {
+      return typeof this.metadata[name] !== 'undefined';
+    }
+  };
+
+  return Metadata;
+})();
index 3c649fb068ef5a2ae09ddbe3d49472ab660242ec..144a3a377415d51a79b7f32e96cf627267b74648 100644 (file)
@@ -111,6 +111,27 @@ var Catalog = (function CatalogClosure() {
   }
 
   Catalog.prototype = {
+    get metadata() {
+      var ref = this.catDict.get('Metadata');
+      if (!ref) {
+        return null;
+      }
+
+      var stream = this.xref.fetch(ref);
+      var dict = stream.dict;
+      if (isDict(dict)) {
+        var type = dict.get('Type');
+        var subtype = dict.get('Subtype');
+
+        if(isName(type) && isName(subtype) &&
+            type.name === 'Metadata' && subtype.name === 'XML') {
+          var metadata = stringToPDFString(bytesToString(stream.getbytes()));
+          return metadata;
+        }
+      }
+
+      return null;
+    },
     get toplevelPagesDict() {
       var pagesObj = this.catDict.get('Pages');
       assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference');
index 34b2e77cbb48dc9dfc14778b34edf1691e49577c..2806d3a7e909922f907d34160dd1b99f90e882c2 100644 (file)
@@ -11,6 +11,7 @@
         <!-- PDFJSSCRIPT_INCLUDE_BUILD -->
         <script type="text/javascript" src="../src/core.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/util.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
+        <script type="text/javascript" src="../src/metadata.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/canvas.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/obj.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/function.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
index 67ef67e97ef9cf99c14033df8699f071cf72e126..68577ad3405af311b8770dd22d6e7d95b67d456a 100644 (file)
@@ -499,6 +499,14 @@ var PDFView = {
       // Setting the default one.
       this.parseScale(kDefaultScale, true);
     }
+
+    var metadata = pdf.catalog.metadata;
+    if (metadata) {
+      this.metadata = metadata = new Metadata(metadata);
+      if (metadata.has('title')) {
+        document.title = metadata.get('title');
+      }
+    }
   },
 
   setHash: function pdfViewSetHash(hash) {