aboutsummaryrefslogtreecommitdiffstats
path: root/lib/caldav/template.js
blob: 2916ce6b2b73384aa97b747f5b80b2092936e228 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
(function(module, ns) {

  function Template(root, rootAttrs) {
    if (typeof(rootAttrs) === 'undefined') {
      rootAttrs = {};
    }

    this.rootTag = root;
    this.rootAttrs = rootAttrs;
    this.activeNamespaces = {};
  }

  Template.prototype = {

    defaultNamespace: 'dav',
    doctype: '<?xml version="1.0" encoding="UTF-8"?>',

    _nsId: 0,

    xmlns: {
      dav: 'DAV:',
      calserver: 'http://calendarserver.org/ns/',
      ical: 'http://apple.com/ns/ical/',
      caldav: 'urn:ietf:params:xml:ns:caldav'
    },

    render: function(content) {
      var output = this.doctype;
      output += this.tag(this.rootTag, this.rootAttrs, content);

      return output;
    },

    /**
     * Registers an xml tag/namespace.
     *
     * @param {String} prefix xmlns.
     * @param {String} tag tag name.
     * @return {String} xml tag name.
     */
    _registerTag: function(prefix, tag) {
      if (prefix in this.xmlns) {
        prefix = this.xmlns[prefix];
      }

      if (prefix in this.activeNamespaces) {
        prefix = this.activeNamespaces[prefix];
      } else {
        var alias = 'N' + this._nsId++;
        this.activeNamespaces[prefix] = alias;
        this.rootAttrs['xmlns:' + alias] = prefix;
        prefix = alias;
      }

      return prefix + ':' + tag;
    },

    /**
     * Returns a xml string based on
     * input. Registers given xmlns on main
     * template. Always use this with render.
     *
     * @param {String|Array} tagDesc as a string defaults to
     *                               .defaultNamespace an array
     *                               takes a xmlns or an alias
     *                               defined in .xmlns.
     *
     * @param {Object} [attrs] optional attributes.
     * @param {String} content content of tag.
     * @return {String} xml tag output.
     */
    tag: function(tagDesc, attrs, content) {

      if (typeof(attrs) === 'string') {
        content = attrs;
        attrs = {};
      }

      if (typeof(content) === 'undefined') {
        content = false;
      }

      if (attrs && typeof(attrs.render) === 'function') {
        content = attrs.render(this);
        attrs = {};
      }

      if (typeof(tagDesc) === 'string') {
        tagDesc = [this.defaultNamespace, tagDesc];
      }

      var fullTag = this._registerTag(tagDesc[0], tagDesc[1]);
      var output = '';
      var key;

      output += '<' + fullTag + '';

      for (key in attrs) {
        output += ' ' + key + '="' + attrs[key] + '"';
      }

      if (content) {
        output += '>' + content + '</' + fullTag + '>';
      } else {
        output += ' />';
      }

      return output;
    }

  };

  module.exports = Template;

}.apply(
  this,
  (this.Caldav) ?
    [Caldav('template'), Caldav] :
    [module, require('./caldav')]
));