~launchpad-pqm/launchpad/devel

7675.1193.6 by Danilo Segan
Add lp.names.launchpad_to_css and css_to_launchpad JS functions for converting between valid Launchpad names and CSS class names.
1
/* Copyright 2011 Canonical Ltd.  This software is licensed under the
2
 * GNU Affero General Public License version 3 (see the file LICENSE).
3
 *
4
 * Utility functions for converting valid Launchpad names for use in
5
 * CSS classes and back.
6
 *
7
 * Launchpad account names match the pattern [a-z0-9][a-z0-9+.-]*.
8
 * CSS class names roughly match the pattern -?[_a-z][_a-z0-9-]*.
9
 *
10
 * These method uses the fact that CSS allows '_' anywhere whereas LP
11
 * does not use it to escape starting digits and '+' or '.'.
12
 *
13
 * When no exceptions are thrown,
14
 *   css_to_launchpad(launchpad_to_css(string))
15
 * is idempotent.
16
 *
17
 * See `lp.app.validators.name.valid_name_pattern` and
18
 * http://www.w3.org/TR/CSS21/grammar.html#scanner
19
 *
20
 * @module lp
21
 * @submodule names
22
 */
23
24
YUI.add('lp.names', function(Y) {
25
26
var namespace = Y.namespace('lp.names');
27
28
/**
29
 * Gets a name suitable to be used as a CSS class for the "valid"
30
 * Launchpad name.
31
 *
32
 * Throws an exception if the `name` is not a valid Launchpad name.
33
 *
34
 * This is a bijective function with the inverse provided by
35
 *   css_to_launchpad().
36
 *
37
 * @method launchpad_to_css
38
 * @param name {String} A valid Launchpad name (eg. a person or project name).
39
 * @return {String} A converted `name` usable in a CSS class directly.
40
 */
41
function launchpad_to_css(name) {
42
43
    // Ensure we're being asked to convert the valid LP name.
44
    if (!name.match(/^[a-z0-9][a-z0-9\+\.\-]*$/)) {
45
        Y.error(
46
            'Passed value "' + name + '" is not a valid Launchpad name.');
47
        return;
48
    }
49
50
    if (name.match(/^[a-z][a-z0-9\-]*$/)) {
51
        // This is an intersection between valid LP and CSS names.
52
        return name;
53
    } else {
54
        // Do the conversion.
55
        var first_char = name.charAt(0);
56
        if (first_char >= '0' && first_char <= '9') {
57
            name = '_' + name;
58
        }
59
60
        // In the rest of the string, we convert all "+"s with "_y" and all
61
        // "."s with "_z".
62
        name = name.replace(/\+/g, '_y');
63
        name = name.replace(/\./g, '_z');
64
    }
65
    return name;
66
}
67
namespace.launchpad_to_css = launchpad_to_css;
68
69
/**
70
 * Convert the CSS name as gotten by launchpad_to_css to
71
 * it's originating Launchpad name.
72
 *
73
 * Throws an exception if the `name` is not a valid CSS class name
74
 * and in the format as produced by launchpad_to_css.
75
 * WARNING: this won't produce a valid Launchpad name for arbitrary
76
 * CSS class names.
77
 *
78
 * This is an inverse function of the function
79
 *   launchpad_to_css().
80
 *
81
 * @method css_to_launchpad
82
 * @param name {String} A valid CSS class name, but usually the result of
83
 *   launchpad_to_css() call.
84
 * @return {String} A converted `name` that is identical to the originating
85
 *   Launchpad name passed into launchpad_to_css().
86
 *   In practice, starting '_a', '_b', ..., '_j' are replaced with
87
 *   '0', '1', ..., '9' and '_y' and '_z' are replaced with '+' and '.'
88
 *   throughout the string.
89
 */
90
function css_to_launchpad(name) {
91
    if (!name.match(/^-?[_a-z][_a-z0-9\-]*$/)) {
92
        Y.error(
93
            'Passed value "' + name + '" is not a valid CSS class name.');
94
    }
95
    if (!name.match(/^((_[0-9yz])|[a-z])([a-z0-9\-]|(_[yz]))*$/)) {
96
        Y.error(
97
            'Passed value "' + name +
98
                '" is not produced by launchpad_to_css.');
99
    }
100
101
    if (name.match(/^[a-z][a-z0-9\-]*$/)) {
102
        // This is an intersection between valid LP and CSS names.
103
        return name;
104
    }
105
106
    if (name.charAt(0) === '_') {
107
        // It may start with a digit (iow, '_0' to '_9' for digits,
108
        // or '_y', '_z' for '+', '.' but we don't care about these [yet]).
109
        var second_char = name.charAt(1);
110
        if (second_char >= '0' && second_char <= '9') {
111
            name = name.substr(1);
112
        }
7675.1200.2 by Danilo Segan
Lint fixes.
113
    }
7675.1193.6 by Danilo Segan
Add lp.names.launchpad_to_css and css_to_launchpad JS functions for converting between valid Launchpad names and CSS class names.
114
    // Replace escaped variants of '+' and '.' back.
115
    name = name.replace(/_y/g, '+');
116
    name = name.replace(/_z/g, '.');
117
118
    return name;
119
}
120
namespace.css_to_launchpad = css_to_launchpad;
121
122
}, "0.1", {});