1 /*
  2  * jQuery CURIE @VERSION
  3  *
  4  * Copyright (c) 2008,2009 Jeni Tennison
  5  * Licensed under the MIT (MIT-LICENSE.txt)
  6  *
  7  * Depends:
  8  *  jquery.uri.js
  9  *  jquery.xmlns.js
 10  */
 11 
 12 /**
 13  * @fileOverview jQuery CURIE handling
 14  * @author <a href="mailto:jeni@jenitennison.com">Jeni Tennison</a>
 15  * @copyright (c) 2008,2009 Jeni Tennison
 16  * @license MIT license (MIT-LICENSE.txt)
 17  * @version 1.0
 18  * @requires jquery.uri.js
 19  * @requires jquery.xmlns.js
 20  */
 21 (function ($) {
 22 
 23    /**
 24     * Creates a {@link jQuery.uri} object by parsing a CURIE.
 25     * @methodOf jQuery
 26     * @param {String} curie The CURIE to be parsed
 27     * @param {String} uri The URI string to be converted to a CURIE.
 28     * @param {Object} [options] CURIE parsing options
 29     * @param {string} [options.reservedNamespace='http://www.w3.org/1999/xhtml/vocab#'] The namespace to apply to a CURIE that has no prefix and either starts with a colon or is in the list of reserved local names
 30     * @param {string} [options.defaultNamespace]  The namespace to apply to a CURIE with no prefix which is not mapped to the reserved namespace by the rules given above.
 31     * @param {Object} [options.namespaces] A map of namespace bindings used to map CURIE prefixes to URIs.
 32     * @param {string[]} [options.reserved=['alternate', 'appendix', 'bookmark', 'cite', 'chapter', 'contents', 'copyright', 'first', 'glossary', 'help', 'icon', 'index', 'last', 'license', 'meta', 'next', 'p3pv1', 'prev', 'role', 'section', 'stylesheet', 'subsection', 'start', 'top', 'up']] A list of local names that will always be mapped to the URI specified by reservedNamespace.
 33     * @param {string} [options.charcase='lower'] Specifies whether the curie's case is altered before it's interpreted. Acceptable values are:
 34     * <dl>
 35     * <dt>lower</dt><dd>Force the CURIE string to lower case.</dd>
 36     * <dt>upper</dt><dd>Force the CURIE string to upper case.</dd>
 37     * <dt>preserve</dt><dd>Preserve the original case of the CURIE. Note that this might not be possible if the CURIE has been taken from an HTML attribute value because of the case conversions performed automatically by browsers. For this reason, it's a good idea to avoid mixed-case CURIEs within RDFa.</dd>
 38     * </dl>
 39     * @returns {jQuery.uri} A new {@link jQuery.uri} object representing the full absolute URI specified by the CURIE.
 40     */
 41   $.curie = function (curie, options) {
 42     var
 43       opts = $.extend({}, $.curie.defaults, options || {}),
 44       m = /^(([^:]*):)?(.+)$/.exec(curie),
 45       prefix = m[2],
 46       local = m[3],
 47       ns = opts.namespaces[prefix];
 48     if (/^:.+/.test(curie)) { // This is the case of a CURIE like ":test"
 49       if (opts.reservedNamespace === undefined || opts.reservedNamespace === null) {
 50         throw "Malformed CURIE: No prefix and no default namespace for unprefixed CURIE " + curie;
 51       } else {
 52         ns = opts.reservedNamespace;
 53       }
 54     } else if (prefix) {
 55       if (ns === undefined) {
 56         throw "Malformed CURIE: No namespace binding for " + prefix + " in CURIE " + curie;
 57       }
 58     } else {
 59       if (opts.charcase === 'lower') {
 60         curie = curie.toLowerCase();
 61       } else if (opts.charcase === 'upper') {
 62         curie = curie.toUpperCase();
 63       }
 64       if (opts.reserved.length && $.inArray(curie, opts.reserved) >= 0) {
 65         ns = opts.reservedNamespace;
 66         local = curie;
 67       } else if (opts.defaultNamespace === undefined || opts.defaultNamespace === null) {
 68         // the default namespace is provided by the application; it's not clear whether
 69         // the default XML namespace should be used if there's a colon but no prefix
 70         throw "Malformed CURIE: No prefix and no default namespace for unprefixed CURIE " + curie;
 71       } else {
 72         ns = opts.defaultNamespace;
 73       }
 74     }
 75     return $.uri(ns + local);
 76   };
 77 
 78   $.curie.defaults = {
 79     namespaces: {},
 80     reserved: [],
 81     reservedNamespace: undefined,
 82     defaultNamespace: undefined,
 83     charcase: 'preserve'
 84   };
 85 
 86    /**
 87     * Creates a {@link jQuery.uri} object by parsing a safe CURIE string (a CURIE
 88     * contained within square brackets). If the input safeCurie string does not
 89     * start with '[' and end with ']', the entire string content will be interpreted
 90     * as a URI string.
 91     * @methodOf jQuery
 92     * @param {String} safeCurie The safe CURIE string to be parsed.
 93     * @param {Object} [options] CURIE parsing options
 94     * @param {string} [options.reservedNamespace='http://www.w3.org/1999/xhtml/vocab#'] The namespace to apply to a CURIE that has no prefix and either starts with a colon or is in the list of reserved local names
 95     * @param {string} [options.defaultNamespace]  The namespace to apply to a CURIE with no prefix which is not mapped to the reserved namespace by the rules given above.
 96     * @param {Object} [options.namespaces] A map of namespace bindings used to map CURIE prefixes to URIs.
 97     * @param {string[]} [options.reserved=['alternate', 'appendix', 'bookmark', 'cite', 'chapter', 'contents', 'copyright',
 98       'first', 'glossary', 'help', 'icon', 'index', 'last', 'license', 'meta', 'next',
 99       'p3pv1', 'prev', 'role', 'section', 'stylesheet', 'subsection', 'start', 'top', 'up']]
100                         A list of local names that will always be mapped to the URI specified by reservedNamespace.
101     * @param {string} [options.charcase='lower'] Specifies whether the curie's case is altered before it's interpreted. Acceptable values are:
102     * <dl>
103     * <dt>lower</dt><dd>Force the CURIE string to lower case.</dd>
104     * <dt>upper</dt><dd>Force the CURIE string to upper case.</dd>
105     * <dt>preserve</dt><dd>Preserve the original case of the CURIE. Note that this might not be possible if the CURIE has been taken from an HTML attribute value because of the case conversions performed automatically by browsers. For this reason, it's a good idea to avoid mixed-case CURIEs within RDFa.</dd>
106     * </dl>
107     * @returns {jQuery.uri} A new {@link jQuery.uri} object representing the full absolute URI specified by the CURIE.
108     */
109   $.safeCurie = function (safeCurie, options) {
110     var m = /^\[([^\]]+)\]$/.exec(safeCurie);
111     return m ? $.curie(m[1], options) : $.uri(safeCurie);
112   };
113 
114    /**
115     * Creates a CURIE string from a URI string.
116     * @methodOf jQuery
117     * @param {String} uri The URI string to be converted to a CURIE.
118     * @param {Object} [options] CURIE parsing options
119     * @param {string} [options.reservedNamespace='http://www.w3.org/1999/xhtml/vocab#']
120     *        If the input URI starts with this value, the generated CURIE will
121     *        have no namespace prefix and will start with a colon character (:),
122     *        unless the local part of the CURIE is one of the reserved names specified
123     *        by the reservedNames option (see below), in which case the generated
124     *        CURIE will have no namespace prefix and will not start with a colon
125     *        character.
126     * @param {string} [options.defaultNamespace]  If the input URI starts with this value, the generated CURIE will have no namespace prefix and will not start with a colon.
127     * @param {Object} [options.namespaces] A map of namespace bindings used to map CURIE prefixes to URIs.
128     * @param {string[]} [options.reserved=['alternate', 'appendix', 'bookmark', 'cite', 'chapter', 'contents', 'copyright',
129       'first', 'glossary', 'help', 'icon', 'index', 'last', 'license', 'meta', 'next',
130       'p3pv1', 'prev', 'role', 'section', 'stylesheet', 'subsection', 'start', 'top', 'up']]
131                         A list of local names that will always be mapped to the URI specified by reservedNamespace.
132     * @param {string} [options.charcase='lower'] Specifies the case normalisation done to the CURIE. Acceptable values are:
133     * <dl>
134     * <dt>lower</dt><dd>Normalise the CURIE to lower case.</dd>
135     * <dt>upper</dt><dd>Normalise the CURIE to upper case.</dd>
136     * <dt>preserve</dt><dd>Preserve the original case of the CURIE. Note that this might not be possible if the CURIE has been taken from an HTML attribute value because of the case conversions performed automatically by browsers. For this reason, it's a good idea to avoid mixed-case CURIEs within RDFa.</dd>
137     * </dl>
138     * @returns {jQuery.uri} A new {@link jQuery.uri} object representing the full absolute URI specified by the CURIE.
139     */
140   $.createCurie = function (uri, options) {
141     var opts = $.extend({}, $.curie.defaults, options || {}),
142       ns = opts.namespaces,
143       curie;
144     uri = $.uri(uri).toString();
145     if (opts.reservedNamespace !== undefined && 
146         uri.substring(0, opts.reservedNamespace.toString().length) === opts.reservedNamespace.toString()) {
147       curie = uri.substring(opts.reservedNamespace.toString().length);
148       if ($.inArray(curie, opts.reserved) === -1) {
149         curie = ':' + curie;
150       }
151     } else {
152       $.each(ns, function (prefix, namespace) {
153         if (uri.substring(0, namespace.toString().length) === namespace.toString()) {
154           curie = prefix + ':' + uri.substring(namespace.toString().length);
155           return null;
156         }
157       });
158     }
159     if (curie === undefined) {
160       throw "No Namespace Binding: There's no appropriate namespace binding for generating a CURIE from " + uri;
161     } else {
162       return curie;
163     }
164   };
165 
166    /**
167     * Creates a {@link jQuery.uri} object by parsing the specified
168     * CURIE string in the context of the namespaces defined by the
169     * jQuery selection.
170     * @methodOf jQuery#
171     * @name jQuery#curie
172     * @param {String} curie The CURIE string to be parsed
173     * @param {Object} options The CURIE parsing options.
174     *        See {@link jQuery.curie} for details of the supported options.
175     *        The namespace declarations declared on the current jQuery
176     *        selection (and inherited from any ancestor elements) will automatically
177     *        be included in the options.namespaces property.
178     * @returns {jQuery.uri}
179     * @see jQuery.curie
180     */
181   $.fn.curie = function (curie, options) {
182     var opts = $.extend({}, $.fn.curie.defaults, { namespaces: this.xmlns() }, options || {});
183     return $.curie(curie, opts);
184   };
185 
186    /**
187     * Creates a {@link jQuery.uri} object by parsing the specified
188     * safe CURIE string in the context of the namespaces defined by
189     * the jQuery selection.
190     *
191     * @methodOf jQuery#
192     * @name jQuery#safeCurie
193     * @param {String} safeCurie The safe CURIE string to be parsed. See {@link jQuery.safeCurie} for details on how safe CURIE strings are processed.
194     * @param {Object} options   The CURIE parsing options.
195     *        See {@link jQuery.safeCurie} for details of the supported options.
196     *        The namespace declarations declared on the current jQuery
197     *        selection (and inherited from any ancestor elements) will automatically
198     *        be included in the options.namespaces property.
199     * @returns {jQuery.uri}
200     * @see jQuery.safeCurie
201     */
202   $.fn.safeCurie = function (safeCurie, options) {
203     var opts = $.extend({}, $.fn.curie.defaults, { namespaces: this.xmlns() }, options || {});
204     return $.safeCurie(safeCurie, opts);
205   };
206 
207    /**
208     * Creates a CURIE string from a URI string using the namespace
209     * bindings in the context of the current jQuery selection.
210     *
211     * @methodOf jQuery#
212     * @name jQuery#createCurie
213     * @param {String|jQuery.uri} uri The URI string to be converted to a CURIE
214     * @param {Object} options the CURIE parsing options.
215     *        See {@link jQuery.createCurie} for details of the supported options.
216     *        The namespace declarations declared on the current jQuery
217     *        selection (and inherited from any ancestor elements) will automatically
218     *        be included in the options.namespaces property.
219     * @returns {String}
220     * @see jQuery.createCurie
221     */
222   $.fn.createCurie = function (uri, options) {
223     var opts = $.extend({}, $.fn.curie.defaults, { namespaces: this.xmlns() }, options || {});
224     return $.createCurie(uri, opts);
225   };
226 
227   $.fn.curie.defaults = {
228     reserved: [
229       'alternate', 'appendix', 'bookmark', 'cite', 'chapter', 'contents', 'copyright',
230       'first', 'glossary', 'help', 'icon', 'index', 'last', 'license', 'meta', 'next',
231       'p3pv1', 'prev', 'role', 'section', 'stylesheet', 'subsection', 'start', 'top', 'up'
232     ],
233     reservedNamespace: 'http://www.w3.org/1999/xhtml/vocab#',
234     defaultNamespace: undefined,
235     charcase: 'lower'
236   };
237 
238 })(jQuery);
239