      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