<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { getDomain } from "../../lib/tldts/tldts-experimental.esm.js";

const tldtsOptions = {
    extractHostname: false,
    validateHostname: false,
    detectIp: false
};

export const libTld = {
    getDomain: function (url) {
        let hostname = extractHostname(url);
        if (isIp(hostname)) {
            return hostname;
        }
        return getDomain(hostname, tldtsOptions);
    }
};

export class UrlParser {

    constructor(url) {
        this.url = url;
    }

    get href() {
        return this.url;
    }

    set href(value) {
        this.url = value;
    }

    get protocol() {
        let { start, end } = getSchemeStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set protocol(value) {
        let { start, end } = getSchemeStartEnd(this.url);
        if (value.endsWith(":"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + value + ":" + this.url.slice(end);
    }

    get username() {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let i = auth.indexOf(":");
        if (i === -1)
            return auth.slice(0, -1);
        else
            return auth.slice(0, i);
    }

    set username(value) {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let newAuth = value;
        let i = auth.indexOf(":");
        if (i !== -1)
            newAuth += auth.slice(i);
        if (newAuth.endsWith("@"))
            this.url = this.url.slice(0, start) + newAuth + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + newAuth + "@" + this.url.slice(end);
    }

    get password() {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let i = auth.indexOf(":");
        if (i === -1)
            return "";
        else
            return auth.slice(i + 1, -1);
    }

    set password(value) {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        if (auth.length > 0) {
            let [user,] = auth.slice(0, -1).split(":", 2);
            this.url = this.url.slice(0, start) + user + ":" + value + "@" + this.url.slice(end);
        }
    }

    get origin() {
        return this.protocol + "//" + this.host;
    }

    get host() {
        let { start, end } = getHostStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set host(value) {
        let { start, end } = getHostStartEnd(this.url);
        this.url = this.url.slice(0, start) + value + this.url.slice(end);
    }

    get hostname() {
        return extractHostname(this.url);
    }

    set hostname(value) {
        let { start, end } = getHostnameStartEnd(this.url);
        this.url = this.url.slice(0, start) + value + this.url.slice(end);
    }

    get port() {
        let { start, end } = getPortStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set port(value) {
        let { start, end } = getPortStartEnd(this.url);
        if (value.startsWith(":"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + ":" + value + this.url.slice(end);
    }

    get pathname() {
        let { start, end } = getPathStartEnd(this.url);
        if (start === end) {
            return "/";
        } else {
            return this.url.slice(start, end);
        }
    }

    set pathname(value) {
        let { start, end } = getPathStartEnd(this.url);
        if (value.startsWith("/"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + "/" + value + this.url.slice(end);
    }

    get search() {
        let { start, end } = getSearchStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set search(value) {
        let { start, end } = getSearchStartEnd(this.url);
        if (value === "")
            this.url = this.url.slice(0, start) + this.url.slice(end);
        else if (value.startsWith("?"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + "?" + value + this.url.slice(end);
    }

    get hash() {
        let start = getHashStart(this.url);
        return this.url.slice(start);
    }

    set hash(value) {
        let start = getHashStart(this.url);
        if (value === "")
            this.url = this.url.slice(0, start);
        else if (value.startsWith("#"))
            this.url = this.url.slice(0, start) + value;
        else
            this.url = this.url.slice(0, start) + "#" + value;
    }
}

export class QueryParser extends UrlParser {

    constructor(url) {
        super(url);
        this.query = super.search;
    }

    getKeyStart(key) {
        let start = this.query.indexOf(key);
        if (start === -1 || (start > 0 && this.query.charAt(start - 1) !== "?" && this.query.charAt(start - 1) !== "&"))
            return undefined;
        return start;
    }

    getKeyEnd(key) {
        let start = this.getKeyStart(key);
        if (typeof start === "undefined")
            return undefined;
        let end = key.length + 1;
        if (end < this.query.length && "#&?=".indexOf(this.query.charAt(end)) === -1)
            return undefined;
        return end;
    }

    getValueEnd(keyEnd) {
        let end = keyEnd + 1;
        for (; end < this.query.length; end++)
            if (this.query.charAt(end) === "&" || this.query.charAt(end) === "?"
                || this.query.charAt(end) === "#")
                break;
        return end;
    }

    getValueStartEnd(key) {
        let start = this.getKeyStart(key);
        if (typeof start === "undefined" || this.query.charAt(start + key.length) !== "=")
            return undefined;
        start += key.length + 1;
        return { start, end: this.getValueEnd(start) };
    }

    get(key) {
        let startEnd = this.getValueStartEnd(key);
        if (typeof startEnd === "undefined")
            return "";
        else
            return this.query.slice(startEnd.start, startEnd.end);
    }

    set(key, value) {
        let keyEnd = this.getKeyEnd(key);
        if (typeof keyEnd === "undefined") {
            if (this.query.length === 0 || this.query.endsWith("?") || this.query.endsWith("&"))
                this.query += key + "=" + value;
            else
                this.query += "&" + key + "=" + value;
            return;
        }
        let valueEnd = this.getValueEnd(keyEnd);
        if (valueEnd === keyEnd + 1) {
            if (this.query.charAt(keyEnd) === "=")
                this.query = this.query.slice(0, valueEnd) + value + this.query.slice(valueEnd);
            else
                this.query = this.query.slice(0, keyEnd) + "=" + value + this.query.slice(keyEnd);
        } else {
            this.query = this.query.slice(0, keyEnd) + "=" + value + this.query.slice(valueEnd);
        }
    }

    get href() {
        super.search = this.query;
        return super.href;
    }
}

export const URL_PARAMETERS = Object.getOwnPropertyNames(UrlParser.prototype).filter(x => x !== "constructor");

export function extractHostname(url) {
    let { start, end } = getHostnameStartEnd(url);
    return url.slice(start, end);
}

function getHostnameStartEnd(url) {
    let i = 0;
    let hostname_begin = 0;
    let hostname_end = url.length;
    let auth = false;
    let port = false;
    if (url.startsWith("//")) {
        i = 2;
        hostname_begin = i;
    } else {
        for (; i < url.length; i++) {
            if (url.charAt(i) === ":" &&
                url.charAt(i + 1) === "/" &&
                url.charAt(i + 2) === "/") {
                i = i + 3;
                hostname_begin = i;
                break;
            }
        }
        if (hostname_begin === 0) {
            i = 0;
        }
    }
    if (url.charAt(hostname_begin) === "[") {
        hostname_begin = i;
        for (; i < url.length; i++) {
            if (url.charAt(i) === "]") {
                hostname_end = i + 1;
                return { start: hostname_begin, end: hostname_end };
            }
        }
    }
    for (; i < url.length; i++) {
        if (url.charAt(i) === "/") {
            if (!port) {
                hostname_end = i;
            }
            break;
        } else if (url.charAt(i) === "@") {
            auth = true;
            port = false;
            hostname_begin = i + 1;
            if (hostname_end < hostname_begin) {
                hostname_end = url.length;
            }
            if (url.charAt(hostname_begin) === "[") {
                i += 1;
                hostname_begin = i;
                for (; i < url.length; i++) {
                    if (url.charAt(i) === "]") {
                        hostname_end = i + 1;
                        return { start: hostname_begin, end: hostname_end };
                    }
                }
            }
        } else if (url.charAt(i) === ":") {
            hostname_end = i;
            if (auth) {
                break;
            }
            port = true;
        }
    }
    return { start: hostname_begin, end: hostname_end };
}

function getPortStartEnd(url) {
    let { end: start } = getHostnameStartEnd(url);
    if (url.charAt(start) !== ":")
        return { start, end: start };
    let end = start + 1;
    for (; end < url.length; end++) {
        if (url.charAt(end) === "/")
            break;
    }
    return { start, end };
}

function getHostStartEnd(url) {
    let { start, end: hostnameEnd } = getHostnameStartEnd(url);
    if (url.charAt(hostnameEnd) !== ":")
        return { start, end: hostnameEnd };
    let end = start + 1;
    for (; end < url.length; end++) {
        if (url.charAt(end) === "/")
            break;
    }
    return { start, end };
}

export function getAuthStartEnd(url) {
    let { start: hostStart } = getHostnameStartEnd(url);
    if (url.charAt(hostStart - 1) !== "@")
        return { start: hostStart, end: hostStart };
    let { end: schemeEnd } = getProtocolStartEnd(url);
    return { start: schemeEnd, end: hostStart };
}

export function getPathStartEnd(url) {
    let { end: protocolEnd } = getProtocolStartEnd(url);
    let start = url.indexOf("/", protocolEnd);
    let end = url.length;
    if (start === -1) {
        return { start: end, end };
    } else {
        for (end = start + 1; end < url.length; end++) {
            if (url.charAt(end) === "?" || url.charAt(end) === "#") {
                break;
            }
        }
        return { start, end };
    }
}

export function getSchemeStartEnd(url) {
    let start = 0;
    let end = url.indexOf("://");
    if (end === -1) {
        return { start, end: start };
    } else {
        return { start, end: end + 1 };
    }
}

export function getProtocolStartEnd(url) {
    let start = 0;
    let end = url.indexOf("://");
    if (end === -1) {
        return { start, end: start };
    } else {
        return { start, end: end + 3 };
    }
}

export function getSearchStartEnd(url) {
    let start = url.indexOf("?");
    let end = getHashStart(url);
    if (start === -1) {
        return { start: end, end };
    } else {
        return { start, end };
    }
}

export function getHashStart(url) {
    let start = url.indexOf("#");
    return start !== -1 ? start : url.length;
}

export function trimQueryParameters(url, trimPattern, invert) {
    if (!trimPattern) {
        return url;
    }
    let parser = new UrlParser(url);
    let query = parser.search;
    if (query.length < 2) {
        return url;
    }
    let queries = query.substring(1).split("?");
    let trimmedQuery = "";
    let trimmed = false;
    for (let query of queries) {
        let searchParams = query.split("&");
        let i = searchParams.length;
        if (invert) {
            while (i--) {
                if (!trimPattern.test(searchParams[i].split("=")[0])) {
                    searchParams.splice(i, 1);
                    trimmed = true;
                }
            }
        } else {
            while (i--) {
                if (trimPattern.test(searchParams[i].split("=")[0])) {
                    searchParams.splice(i, 1);
                    trimmed = true;
                }
            }
        }
        if (searchParams.length > 0) {
            if (trimmed)
                trimmedQuery += "?" + searchParams.join("&");
            else
                trimmedQuery += "?" + query;
        }
    }
    if (trimmed)
        parser.search = trimmedQuery;
    return parser.href;
}

/**
 * Parser for inline redirection url.
 * @param url
 */
export function parseInlineUrl(url) {
    let i = url.indexOf("http", 1);

    if (i < 0) {
        return null;
    }

    let inlineUrl = url.slice(i);

    // extract redirection url from a query parameter
    if (url.charAt(i - 1) === "=") {
        inlineUrl = inlineUrl.replace(/[&;].*/, "");
    }

    let j = 4;
    if (inlineUrl.charAt(j) === "s") {
        j++;
    }
    if (inlineUrl.startsWith("%3", j)) {
        inlineUrl = inlineUrl.replace(/\?.*/, "");
    }

    inlineUrl = decodeURIComponent(inlineUrl);

    if (!inlineUrl.startsWith("://", j)) {
        return null;
    }

    return inlineUrl;
}

function isProbablyIpv4(hostname) {
    let numberOfDots = 0;
    if (hostname.length < 7
        || !isDigitCode(hostname.charCodeAt(0))
        || !isDigitCode(hostname.charCodeAt(hostname.length - 1))) {
        return false;
    }
    for (let i = 1; i < hostname.length - 1; i += 1) {
        let code = hostname.charCodeAt(i);
        if (code === 46) {
            numberOfDots += 1;
        } else if (!isDigitCode(code)) {
            return false;
        }
    }
    return numberOfDots === 3;
}

function isDigitCode(c) {
    return c >= 48 && c <= 57;
}

function isProbablyIpv6(hostname) {
    return hostname.startsWith("[");
}

function isIp(hostname) {
    return isProbablyIpv6(hostname) || isProbablyIpv4(hostname);
}
<commit_msg>Refactor trim query parameters<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { getDomain } from "../../lib/tldts/tldts-experimental.esm.js";

const tldtsOptions = {
    extractHostname: false,
    validateHostname: false,
    detectIp: false
};

export const libTld = {
    getDomain: function (url) {
        let hostname = extractHostname(url);
        if (isIp(hostname)) {
            return hostname;
        }
        return getDomain(hostname, tldtsOptions);
    }
};

export class UrlParser {

    constructor(url) {
        this.url = url;
    }

    get href() {
        return this.url;
    }

    set href(value) {
        this.url = value;
    }

    get protocol() {
        let { start, end } = getSchemeStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set protocol(value) {
        let { start, end } = getSchemeStartEnd(this.url);
        if (value.endsWith(":"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + value + ":" + this.url.slice(end);
    }

    get username() {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let i = auth.indexOf(":");
        if (i === -1)
            return auth.slice(0, -1);
        else
            return auth.slice(0, i);
    }

    set username(value) {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let newAuth = value;
        let i = auth.indexOf(":");
        if (i !== -1)
            newAuth += auth.slice(i);
        if (newAuth.endsWith("@"))
            this.url = this.url.slice(0, start) + newAuth + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + newAuth + "@" + this.url.slice(end);
    }

    get password() {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        let i = auth.indexOf(":");
        if (i === -1)
            return "";
        else
            return auth.slice(i + 1, -1);
    }

    set password(value) {
        let { start, end } = getAuthStartEnd(this.url);
        let auth = this.url.slice(start, end);
        if (auth.length > 0) {
            let [user,] = auth.slice(0, -1).split(":", 2);
            this.url = this.url.slice(0, start) + user + ":" + value + "@" + this.url.slice(end);
        }
    }

    get origin() {
        return this.protocol + "//" + this.host;
    }

    get host() {
        let { start, end } = getHostStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set host(value) {
        let { start, end } = getHostStartEnd(this.url);
        this.url = this.url.slice(0, start) + value + this.url.slice(end);
    }

    get hostname() {
        return extractHostname(this.url);
    }

    set hostname(value) {
        let { start, end } = getHostnameStartEnd(this.url);
        this.url = this.url.slice(0, start) + value + this.url.slice(end);
    }

    get port() {
        let { start, end } = getPortStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set port(value) {
        let { start, end } = getPortStartEnd(this.url);
        if (value.startsWith(":"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + ":" + value + this.url.slice(end);
    }

    get pathname() {
        let { start, end } = getPathStartEnd(this.url);
        if (start === end) {
            return "/";
        } else {
            return this.url.slice(start, end);
        }
    }

    set pathname(value) {
        let { start, end } = getPathStartEnd(this.url);
        if (value.startsWith("/"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + "/" + value + this.url.slice(end);
    }

    get search() {
        let { start, end } = getSearchStartEnd(this.url);
        return this.url.slice(start, end);
    }

    set search(value) {
        let { start, end } = getSearchStartEnd(this.url);
        if (value === "")
            this.url = this.url.slice(0, start) + this.url.slice(end);
        else if (value.startsWith("?"))
            this.url = this.url.slice(0, start) + value + this.url.slice(end);
        else
            this.url = this.url.slice(0, start) + "?" + value + this.url.slice(end);
    }

    get hash() {
        let start = getHashStart(this.url);
        return this.url.slice(start);
    }

    set hash(value) {
        let start = getHashStart(this.url);
        if (value === "")
            this.url = this.url.slice(0, start);
        else if (value.startsWith("#"))
            this.url = this.url.slice(0, start) + value;
        else
            this.url = this.url.slice(0, start) + "#" + value;
    }
}

export class QueryParser extends UrlParser {

    constructor(url) {
        super(url);
        this.query = super.search;
    }

    getKeyStart(key) {
        let start = this.query.indexOf(key);
        if (start === -1 || (start > 0 && this.query.charAt(start - 1) !== "?" && this.query.charAt(start - 1) !== "&"))
            return undefined;
        return start;
    }

    getKeyEnd(key) {
        let start = this.getKeyStart(key);
        if (typeof start === "undefined")
            return undefined;
        let end = key.length + 1;
        if (end < this.query.length && "#&?=".indexOf(this.query.charAt(end)) === -1)
            return undefined;
        return end;
    }

    getValueEnd(keyEnd) {
        let end = keyEnd + 1;
        for (; end < this.query.length; end++)
            if (this.query.charAt(end) === "&" || this.query.charAt(end) === "?"
                || this.query.charAt(end) === "#")
                break;
        return end;
    }

    getValueStartEnd(key) {
        let start = this.getKeyStart(key);
        if (typeof start === "undefined" || this.query.charAt(start + key.length) !== "=")
            return undefined;
        start += key.length + 1;
        return { start, end: this.getValueEnd(start) };
    }

    get(key) {
        let startEnd = this.getValueStartEnd(key);
        if (typeof startEnd === "undefined")
            return "";
        else
            return this.query.slice(startEnd.start, startEnd.end);
    }

    set(key, value) {
        let keyEnd = this.getKeyEnd(key);
        if (typeof keyEnd === "undefined") {
            if (this.query.length === 0 || this.query.endsWith("?") || this.query.endsWith("&"))
                this.query += key + "=" + value;
            else
                this.query += "&" + key + "=" + value;
            return;
        }
        let valueEnd = this.getValueEnd(keyEnd);
        if (valueEnd === keyEnd + 1) {
            if (this.query.charAt(keyEnd) === "=")
                this.query = this.query.slice(0, valueEnd) + value + this.query.slice(valueEnd);
            else
                this.query = this.query.slice(0, keyEnd) + "=" + value + this.query.slice(keyEnd);
        } else {
            this.query = this.query.slice(0, keyEnd) + "=" + value + this.query.slice(valueEnd);
        }
    }

    get href() {
        super.search = this.query;
        return super.href;
    }
}

export const URL_PARAMETERS = Object.getOwnPropertyNames(UrlParser.prototype).filter(x => x !== "constructor");

export function extractHostname(url) {
    let { start, end } = getHostnameStartEnd(url);
    return url.slice(start, end);
}

function getHostnameStartEnd(url) {
    let i = 0;
    let hostname_begin = 0;
    let hostname_end = url.length;
    let auth = false;
    let port = false;
    if (url.startsWith("//")) {
        i = 2;
        hostname_begin = i;
    } else {
        for (; i < url.length; i++) {
            if (url.charAt(i) === ":" &&
                url.charAt(i + 1) === "/" &&
                url.charAt(i + 2) === "/") {
                i = i + 3;
                hostname_begin = i;
                break;
            }
        }
        if (hostname_begin === 0) {
            i = 0;
        }
    }
    if (url.charAt(hostname_begin) === "[") {
        hostname_begin = i;
        for (; i < url.length; i++) {
            if (url.charAt(i) === "]") {
                hostname_end = i + 1;
                return { start: hostname_begin, end: hostname_end };
            }
        }
    }
    for (; i < url.length; i++) {
        if (url.charAt(i) === "/") {
            if (!port) {
                hostname_end = i;
            }
            break;
        } else if (url.charAt(i) === "@") {
            auth = true;
            port = false;
            hostname_begin = i + 1;
            if (hostname_end < hostname_begin) {
                hostname_end = url.length;
            }
            if (url.charAt(hostname_begin) === "[") {
                i += 1;
                hostname_begin = i;
                for (; i < url.length; i++) {
                    if (url.charAt(i) === "]") {
                        hostname_end = i + 1;
                        return { start: hostname_begin, end: hostname_end };
                    }
                }
            }
        } else if (url.charAt(i) === ":") {
            hostname_end = i;
            if (auth) {
                break;
            }
            port = true;
        }
    }
    return { start: hostname_begin, end: hostname_end };
}

function getPortStartEnd(url) {
    let { end: start } = getHostnameStartEnd(url);
    if (url.charAt(start) !== ":")
        return { start, end: start };
    let end = start + 1;
    for (; end < url.length; end++) {
        if (url.charAt(end) === "/")
            break;
    }
    return { start, end };
}

function getHostStartEnd(url) {
    let { start, end: hostnameEnd } = getHostnameStartEnd(url);
    if (url.charAt(hostnameEnd) !== ":")
        return { start, end: hostnameEnd };
    let end = start + 1;
    for (; end < url.length; end++) {
        if (url.charAt(end) === "/")
            break;
    }
    return { start, end };
}

export function getAuthStartEnd(url) {
    let { start: hostStart } = getHostnameStartEnd(url);
    if (url.charAt(hostStart - 1) !== "@")
        return { start: hostStart, end: hostStart };
    let { end: schemeEnd } = getProtocolStartEnd(url);
    return { start: schemeEnd, end: hostStart };
}

export function getPathStartEnd(url) {
    let { end: protocolEnd } = getProtocolStartEnd(url);
    let start = url.indexOf("/", protocolEnd);
    let end = url.length;
    if (start === -1) {
        return { start: end, end };
    } else {
        for (end = start + 1; end < url.length; end++) {
            if (url.charAt(end) === "?" || url.charAt(end) === "#") {
                break;
            }
        }
        return { start, end };
    }
}

export function getSchemeStartEnd(url) {
    let start = 0;
    let end = url.indexOf("://");
    if (end === -1) {
        return { start, end: start };
    } else {
        return { start, end: end + 1 };
    }
}

export function getProtocolStartEnd(url) {
    let start = 0;
    let end = url.indexOf("://");
    if (end === -1) {
        return { start, end: start };
    } else {
        return { start, end: end + 3 };
    }
}

export function getSearchStartEnd(url) {
    let start = url.indexOf("?");
    let end = getHashStart(url);
    if (start === -1) {
        return { start: end, end };
    } else {
        return { start, end };
    }
}

export function getHashStart(url) {
    let start = url.indexOf("#");
    return start !== -1 ? start : url.length;
}

export function trimQueryParameters(url, trimPattern, invert = false) {
    if (!trimPattern) {
        return url;
    }
    let parser = new UrlParser(url);
    let query = parser.search;
    if (query.length < 2) {
        return url;
    }
    let queries = query.substring(1).split("?");
    let trimmedQuery = "";
    let trimmed = false;
    for (let query of queries) {
        let searchParams = query.split("&");
        let i = searchParams.length;
        while (i--) {
            if (trimPattern.test(searchParams[i].split("=")[0]) !== invert) {
                searchParams.splice(i, 1);
                trimmed = true;
            }
        }
        if (searchParams.length > 0) {
            if (trimmed)
                trimmedQuery += "?" + searchParams.join("&");
            else
                trimmedQuery += "?" + query;
        }
    }
    if (trimmed)
        parser.search = trimmedQuery;
    return parser.href;
}

/**
 * Parser for inline redirection url.
 * @param url
 */
export function parseInlineUrl(url) {
    let i = url.indexOf("http", 1);

    if (i < 0) {
        return null;
    }

    let inlineUrl = url.slice(i);

    // extract redirection url from a query parameter
    if (url.charAt(i - 1) === "=") {
        inlineUrl = inlineUrl.replace(/[&;].*/, "");
    }

    let j = 4;
    if (inlineUrl.charAt(j) === "s") {
        j++;
    }
    if (inlineUrl.startsWith("%3", j)) {
        inlineUrl = inlineUrl.replace(/\?.*/, "");
    }

    inlineUrl = decodeURIComponent(inlineUrl);

    if (!inlineUrl.startsWith("://", j)) {
        return null;
    }

    return inlineUrl;
}

function isProbablyIpv4(hostname) {
    let numberOfDots = 0;
    if (hostname.length < 7
        || !isDigitCode(hostname.charCodeAt(0))
        || !isDigitCode(hostname.charCodeAt(hostname.length - 1))) {
        return false;
    }
    for (let i = 1; i < hostname.length - 1; i += 1) {
        let code = hostname.charCodeAt(i);
        if (code === 46) {
            numberOfDots += 1;
        } else if (!isDigitCode(code)) {
            return false;
        }
    }
    return numberOfDots === 3;
}

function isDigitCode(c) {
    return c >= 48 && c <= 57;
}

function isProbablyIpv6(hostname) {
    return hostname.startsWith("[");
}

function isIp(hostname) {
    return isProbablyIpv6(hostname) || isProbablyIpv4(hostname);
}
<|endoftext|>


<commit_before>CenterScout.controller('HomeController', ['$scope', 'GradeData', 'AssignmentData', function($scope, GradeData, AssignmentData) {

    $scope.grades = [{ name: 'Loading...', class: '', date: '', percent: '', fraction: ''}];
    $scope.assignments = [{ done: false, name: 'Loading...', class: '', date: ''}]; // TODO: Find a better way of doing this hack
    $scope.courses = ['M', 'CAD']; // TODO: Find a way to use the PowerSchool names for only the classes in lfhs.or
    $scope.selectedCourse = '...';

    $scope.setSelectedCourse = function() {
        $scope.selectedCourse = this.course;
    };

    var updateClassList = function(grades) {
        grades.forEach(function(grade) {
            if(($scope.courses.indexOf(grade.class) === -1) && (grades.class.indexOf('Lunch') === -1))
                $scope.courses.push(grade.class);
        });
        $scope.selectedCourse = $scope.courses[0];
    };

    GradeData().then(function(grades) {
        $scope.grades = grades;
        updateClassList(grades);
    }, handleError);

    AssignmentData().then(function(assignments) {
        $scope.assignments = assignments;
    }, handleError);

}]);

CenterScout.controller('LoginController', ['$scope', 'AuthService', function($scope, AuthService) {

    $scope.signIn = function() {
        AuthService.signIn($scope.username, $scope.password);
    };

}]);

CenterScout.controller('ClassController', ['$scope', function($scope) {

}]);

CenterScout.controller('AboutController', ['$scope', function($scope) {

}]);

CenterScout.controller('ErrorController', ['$scope', function($scope) {

}]);

CenterScout.controller('SettingsController', ['$scope', 'Settings', function($scope, Settings) {

}]);
<commit_msg>Implement simple Settings controller<commit_after>CenterScout.controller('HomeController', ['$scope', 'GradeData', 'AssignmentData', function($scope, GradeData, AssignmentData) {

    $scope.grades = [{ name: 'Loading...', class: '', date: '', percent: '', fraction: ''}];
    $scope.assignments = [{ done: false, name: 'Loading...', class: '', date: ''}]; // TODO: Find a better way of doing this hack
    $scope.courses = ['M', 'CAD']; // TODO: Find a way to use the PowerSchool names for only the classes in lfhs.or
    $scope.selectedCourse = '...';

    $scope.setSelectedCourse = function() {
        $scope.selectedCourse = this.course;
    };

    var updateClassList = function(grades) {
        grades.forEach(function(grade) {
            if(($scope.courses.indexOf(grade.class) === -1) && (grades.class.indexOf('Lunch') === -1))
                $scope.courses.push(grade.class);
        });
        $scope.selectedCourse = $scope.courses[0];
    };

    GradeData().then(function(grades) {
        $scope.grades = grades;
        updateClassList(grades);
    }, handleError);

    AssignmentData().then(function(assignments) {
        $scope.assignments = assignments;
    }, handleError);

}]);

CenterScout.controller('LoginController', ['$scope', 'AuthService', function($scope, AuthService) {

    $scope.signIn = function() {
        AuthService.signIn($scope.username, $scope.password);
    };

}]);

CenterScout.controller('ClassController', ['$scope', function($scope) {

}]);

CenterScout.controller('AboutController', ['$scope', function($scope) {

}]);

CenterScout.controller('ErrorController', ['$scope', function($scope) {

}]);

CenterScout.controller('SettingsController', ['$scope', 'Settings', function($scope, Settings) {
    $scope.$watch('generalKeepLogin', Settings.setKeepLogin);
    $scope.generalKeepLogin = Settings.getKeepLogin();
}]);
<|endoftext|>


<commit_before>/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * [Create CommonJS files]:
 * Compatible with prevoius folder structure: `echarts/lib` exists in `node_modules`
 * (1) Build all files to CommonJS to `echarts/lib`.
 * (2) Remove __DEV__.
 * (3) Mount `echarts/src/export.js` to `echarts/lib/echarts.js`.
 *
 * [Create ESModule files]:
 * Build all files to CommonJS to `echarts/esm`.
 */

const nodePath = require('path');
const assert = require('assert');
const fs = require('fs');
const fsExtra = require('fs-extra');
const chalk = require('chalk');
const ts = require('typescript');
const globby = require('globby');
const transformDEVUtil = require('./transform-dev');
const preamble = require('./preamble');
const dts = require('@lang/rollup-plugin-dts').default;
const rollup = require('rollup');
const { transformImport } = require('zrender/build/transformImport');

const ecDir = nodePath.resolve(__dirname, '..');
const tmpDir = nodePath.resolve(ecDir, 'pre-publish-tmp');

const tsConfig = readTSConfig();

const autoGeneratedFileAlert = `
/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

`;

const mainSrcGlobby = {
    patterns: [
        'src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcGlobby = {
    patterns: [
        'extension-src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcDir = nodePath.resolve(ecDir, 'extension-src');
const extensionESMDir = nodePath.resolve(ecDir, 'extension');

const typesDir = nodePath.resolve(ecDir, 'types');
const esmDir = 'lib';

const compileWorkList = [
    {
        logLabel: 'main ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            rootDir: ecDir,
            outDir: tmpDir,
            // Generate types when buidling esm
            declaration: true,
            declarationDir: typesDir
        },
        srcGlobby: mainSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: tmpDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(tmpDir);
            fsExtra.removeSync(nodePath.resolve(ecDir, 'types'));
            fsExtra.removeSync(nodePath.resolve(ecDir, esmDir));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.blank.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.common.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.simple.js'));
        },
        after: async function () {
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.all.js'), nodePath.resolve(ecDir, 'index.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.blank.js'), nodePath.resolve(ecDir, 'index.blank.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.common.js'), nodePath.resolve(ecDir, 'index.common.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.simple.js'), nodePath.resolve(ecDir, 'index.simple.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src'), nodePath.resolve(ecDir, esmDir));

            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.blank.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.common.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.simple.js'), esmDir);

            await transformLibFiles(nodePath.resolve(ecDir, esmDir), esmDir);
            await transformLibFiles(nodePath.resolve(ecDir, 'types'), esmDir);
            fsExtra.removeSync(tmpDir);
        }
    },
    {
        logLabel: 'extension ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            rootDir: extensionSrcDir,
            outDir: extensionESMDir
        },
        srcGlobby: extensionSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: extensionESMDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(extensionESMDir);
        },
        after: async function () {
            await transformLibFiles(extensionESMDir, 'lib');
        }
    }
];

/**
 * @public
 */
module.exports = async function () {

    for (let {
        logLabel, compilerOptionsOverride, srcGlobby,
        transformOptions, before, after
    } of compileWorkList) {

        process.stdout.write(chalk.green.dim(`[${logLabel}]: compiling ...`));

        before && await before();

        let srcPathList = await readFilePaths(srcGlobby);

        await tsCompile(compilerOptionsOverride, srcPathList);

        process.stdout.write(chalk.green.dim(` done \n`));

        process.stdout.write(chalk.green.dim(`[${logLabel}]: transforming ...`));

        await transformCode(transformOptions);

        after && await after();

        process.stdout.write(chalk.green.dim(` done \n`));
    }

    process.stdout.write(chalk.green.dim(`Generating entries ...`));
    generateEntries();
    process.stdout.write(chalk.green.dim(`Bundling DTS ...`));
    await bundleDTS();

    console.log(chalk.green.dim('All done.'));
};

async function runTsCompile(localTs, compilerOptions, srcPathList) {
    // Must do it. becuase the value in tsconfig.json might be different from the inner representation.
    // For example: moduleResolution: "NODE" => moduleResolution: 2
    const {options, errors} = localTs.convertCompilerOptionsFromJson(compilerOptions, ecDir);

    if (errors.length) {
        let errMsg = 'tsconfig parse failed: '
            + errors.map(error => error.messageText).join('. ')
            + '\n compilerOptions: \n' + JSON.stringify(compilerOptions, null, 4);
        assert(false, errMsg);
    }

    // See: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API

    let program = localTs.createProgram(srcPathList, options);
    let emitResult = program.emit();

    let allDiagnostics = localTs
        .getPreEmitDiagnostics(program)
        .concat(emitResult.diagnostics);

    allDiagnostics.forEach(diagnostic => {
        if (diagnostic.file) {
            let {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
            let message = localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
            console.log(chalk.red(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`));
        }
        else {
            console.log(chalk.red(localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n')));
        }
    });
    if (allDiagnostics.length > 0) {
        throw new Error('TypeScript Compile Failed')
    }
}
module.exports.runTsCompile = runTsCompile;

async function tsCompile(compilerOptionsOverride, srcPathList) {
    assert(
        compilerOptionsOverride
        && compilerOptionsOverride.module
        && compilerOptionsOverride.rootDir
        && compilerOptionsOverride.outDir
    );

    let compilerOptions = {
        ...tsConfig.compilerOptions,
        ...compilerOptionsOverride,
        sourceMap: false
    };

    runTsCompile(ts, compilerOptions, srcPathList);
}

/**
 * Transform import/require path in the entry file to `esm` or `lib`.
 */
function transformRootFolderInEntry(entryFile, replacement) {
    let code = fs.readFileSync(entryFile, 'utf-8');
    // Simple regex replacement
    // TODO More robust way?
    assert(
        !/(import\s+|from\s+|require\(\s*)["']\.\/echarts\./.test(code)
        && !/(import\s+|from\s+|require\(\s*)["']echarts\./.test(code),
        'Import echarts.xxx.ts is not supported.'
    );
    code = code.replace(/((import\s+|from\s+|require\(\s*)["'])\.\//g, `$1./${replacement}/`);
    fs.writeFileSync(
        entryFile,
        // Also transform zrender.
        singleTransformImport(code, replacement),
        'utf-8'
    );
}

/**
 * Transform `zrender/src` to `zrender/lib` in all files
 */
async function transformLibFiles(rooltFolder, replacement) {
    const files = await readFilePaths({
        patterns: ['**/*.js', '**/*.d.ts'],
        cwd: rooltFolder
    });
    // Simple regex replacement
    // TODO More robust way?
    for (let fileName of files) {
        let code = fs.readFileSync(fileName, 'utf-8');
        code = singleTransformImport(code, replacement);
        // For lower ts version, not use import type
        // TODO Use https://github.com/sandersn/downlevel-dts ?
        // if (fileName.endsWith('.d.ts')) {
        //     code = singleTransformImportType(code);
        // }
        fs.writeFileSync(fileName, code, 'utf-8');
    }
}

/**
 * 1. Transform zrender/src to zrender/lib
 * 2. Add .js extensions
 */
function singleTransformImport(code, replacement) {
    return transformImport(
        code.replace(/([\"\'])zrender\/src\//g, `$1zrender/${replacement}/`),
        (moduleName) => {
            // Ignore 'tslib' and 'echarts' in the extensions.
            if (moduleName === 'tslib' || moduleName === 'echarts') {
                return moduleName;
            }
            else if (moduleName === 'zrender/lib/export') {
                throw new Error('Should not import the whole zrender library.');
            }
            else if (moduleName.endsWith('.ts')) {
                // Replace ts with js
                return moduleName.replace(/\.ts$/, '.js');
            }
            else if (moduleName.endsWith('.js')) {
                return moduleName;
            }
            else {
                return moduleName + '.js'
            }
        }
    );
}

// function singleTransformImportType(code) {
//     return code.replace(/import\s+type\s+/g, 'import ');
// }

/**
 * @param {Object} transformOptions
 * @param {Object} transformOptions.filesGlobby {patterns: string[], cwd: string}
 * @param {string} [transformOptions.preamble] See './preamble.js'
 * @param {boolean} [transformOptions.transformDEV]
 */
async function transformCode({filesGlobby, preamble, transformDEV}) {

    let filePaths = await readFilePaths(filesGlobby);

    filePaths.map(filePath => {
        let code = fs.readFileSync(filePath, 'utf8');

        if (transformDEV) {
            let result = transformDEVUtil.transform(code, false);
            code = result.code;
        }

        code = autoGeneratedFileAlert + code;

        if (preamble) {
            code = preamble + code;
        }

        fs.writeFileSync(filePath, code, 'utf8');
    });
}

async function readFilePaths({patterns, cwd}) {
    assert(patterns && cwd);
    return (
        await globby(patterns, {cwd})
    ).map(
        srcPath => nodePath.resolve(cwd, srcPath)
    );
}

async function bundleDTS() {

    const outDir = nodePath.resolve(__dirname, '../types/dist');
    const commonConfig = {
        onwarn(warning, rollupWarn) {
            // Not warn circular dependency
            if (warning.code !== 'CIRCULAR_DEPENDENCY') {
                rollupWarn(warning);
            }
        },
        plugins: [
            dts({
                respectExternal: true
            })
//             {
//                 generateBundle(options, bundle) {
//                     for (let chunk of Object.values(bundle)) {
//                         chunk.code = `
// type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
// ${chunk.code}`
//                     }
//                 }
//             }
        ]
    };

    // Bundle chunks.
    const parts = [
        'core', 'charts', 'components', 'renderers', 'option', 'features'
    ];
    const inputs = {};
    parts.forEach(partName => {
        inputs[partName] = nodePath.resolve(__dirname, `../types/src/export/${partName}.d.ts`)
    });

    const bundle = await rollup.rollup({
        input: inputs,
        ...commonConfig
    });
    let idx = 1;
    await bundle.write({
        dir: outDir,
        minifyInternalExports: false,
        manualChunks: (id) => {
            // Only create one chunk.
            return 'shared';
        },
        chunkFileNames: 'shared.d.ts'
    });

    // Bundle all in one
    const bundleAllInOne = await rollup.rollup({
        input: nodePath.resolve(__dirname, `../types/src/export/all.d.ts`),
        ...commonConfig
    });
    await bundleAllInOne.write({
        file: nodePath.resolve(outDir, 'echarts.d.ts')
    });
}

function readTSConfig() {
    // tsconfig.json may have comment string, which is invalid if
    // using `require('tsconfig.json'). So we use a loose parser.
    let filePath = nodePath.resolve(ecDir, 'tsconfig.json');
    const tsConfigText = fs.readFileSync(filePath, {encoding: 'utf8'});
    return (new Function(`return ( ${tsConfigText} )`))();
}

function generateEntries() {
    ['charts', 'components', 'renderers', 'core', 'features'].forEach(entryName => {
        if (entryName !== 'option') {
            const jsCode = fs.readFileSync(nodePath.join(__dirname, `template/${entryName}.js`), 'utf-8');
            fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.js`), jsCode, 'utf-8');
        }

        const dtsCode = fs.readFileSync(nodePath.join(__dirname, `/template/${entryName}.d.ts`), 'utf-8');
        fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.d.ts`), dtsCode, 'utf-8');
    });
}

module.exports.readTSConfig = readTSConfig;
<commit_msg>chore: not export declarations on the extension build<commit_after>/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * [Create CommonJS files]:
 * Compatible with prevoius folder structure: `echarts/lib` exists in `node_modules`
 * (1) Build all files to CommonJS to `echarts/lib`.
 * (2) Remove __DEV__.
 * (3) Mount `echarts/src/export.js` to `echarts/lib/echarts.js`.
 *
 * [Create ESModule files]:
 * Build all files to CommonJS to `echarts/esm`.
 */

const nodePath = require('path');
const assert = require('assert');
const fs = require('fs');
const fsExtra = require('fs-extra');
const chalk = require('chalk');
const ts = require('typescript');
const globby = require('globby');
const transformDEVUtil = require('./transform-dev');
const preamble = require('./preamble');
const dts = require('@lang/rollup-plugin-dts').default;
const rollup = require('rollup');
const { transformImport } = require('zrender/build/transformImport');

const ecDir = nodePath.resolve(__dirname, '..');
const tmpDir = nodePath.resolve(ecDir, 'pre-publish-tmp');

const tsConfig = readTSConfig();

const autoGeneratedFileAlert = `
/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

`;

const mainSrcGlobby = {
    patterns: [
        'src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcGlobby = {
    patterns: [
        'extension-src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcDir = nodePath.resolve(ecDir, 'extension-src');
const extensionESMDir = nodePath.resolve(ecDir, 'extension');

const typesDir = nodePath.resolve(ecDir, 'types');
const esmDir = 'lib';

const compileWorkList = [
    {
        logLabel: 'main ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            rootDir: ecDir,
            outDir: tmpDir,
            // Generate types when buidling esm
            declaration: true,
            declarationDir: typesDir
        },
        srcGlobby: mainSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: tmpDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(tmpDir);
            fsExtra.removeSync(nodePath.resolve(ecDir, 'types'));
            fsExtra.removeSync(nodePath.resolve(ecDir, esmDir));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.blank.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.common.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.simple.js'));
        },
        after: async function () {
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.all.js'), nodePath.resolve(ecDir, 'index.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.blank.js'), nodePath.resolve(ecDir, 'index.blank.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.common.js'), nodePath.resolve(ecDir, 'index.common.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.simple.js'), nodePath.resolve(ecDir, 'index.simple.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src'), nodePath.resolve(ecDir, esmDir));

            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.blank.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.common.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.simple.js'), esmDir);

            await transformLibFiles(nodePath.resolve(ecDir, esmDir), esmDir);
            await transformLibFiles(nodePath.resolve(ecDir, 'types'), esmDir);
            fsExtra.removeSync(tmpDir);
        }
    },
    {
        logLabel: 'extension ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            declaration: false,
            rootDir: extensionSrcDir,
            outDir: extensionESMDir
        },
        srcGlobby: extensionSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: extensionESMDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(extensionESMDir);
        },
        after: async function () {
            await transformLibFiles(extensionESMDir, 'lib');
        }
    }
];

/**
 * @public
 */
module.exports = async function () {

    for (let {
        logLabel, compilerOptionsOverride, srcGlobby,
        transformOptions, before, after
    } of compileWorkList) {

        process.stdout.write(chalk.green.dim(`[${logLabel}]: compiling ...`));

        before && await before();

        let srcPathList = await readFilePaths(srcGlobby);

        await tsCompile(compilerOptionsOverride, srcPathList);

        process.stdout.write(chalk.green.dim(` done \n`));

        process.stdout.write(chalk.green.dim(`[${logLabel}]: transforming ...`));

        await transformCode(transformOptions);

        after && await after();

        process.stdout.write(chalk.green.dim(` done \n`));
    }

    process.stdout.write(chalk.green.dim(`Generating entries ...`));
    generateEntries();
    process.stdout.write(chalk.green.dim(`Bundling DTS ...`));
    await bundleDTS();

    console.log(chalk.green.dim('All done.'));
};

async function runTsCompile(localTs, compilerOptions, srcPathList) {
    // Must do it. becuase the value in tsconfig.json might be different from the inner representation.
    // For example: moduleResolution: "NODE" => moduleResolution: 2
    const {options, errors} = localTs.convertCompilerOptionsFromJson(compilerOptions, ecDir);

    if (errors.length) {
        let errMsg = 'tsconfig parse failed: '
            + errors.map(error => error.messageText).join('. ')
            + '\n compilerOptions: \n' + JSON.stringify(compilerOptions, null, 4);
        assert(false, errMsg);
    }

    // See: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API

    let program = localTs.createProgram(srcPathList, options);
    let emitResult = program.emit();

    let allDiagnostics = localTs
        .getPreEmitDiagnostics(program)
        .concat(emitResult.diagnostics);

    allDiagnostics.forEach(diagnostic => {
        if (diagnostic.file) {
            let {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
            let message = localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
            console.log(chalk.red(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`));
        }
        else {
            console.log(chalk.red(localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n')));
        }
    });
    if (allDiagnostics.length > 0) {
        throw new Error('TypeScript Compile Failed')
    }
}
module.exports.runTsCompile = runTsCompile;

async function tsCompile(compilerOptionsOverride, srcPathList) {
    assert(
        compilerOptionsOverride
        && compilerOptionsOverride.module
        && compilerOptionsOverride.rootDir
        && compilerOptionsOverride.outDir
    );

    let compilerOptions = {
        ...tsConfig.compilerOptions,
        ...compilerOptionsOverride,
        sourceMap: false
    };

    runTsCompile(ts, compilerOptions, srcPathList);
}

/**
 * Transform import/require path in the entry file to `esm` or `lib`.
 */
function transformRootFolderInEntry(entryFile, replacement) {
    let code = fs.readFileSync(entryFile, 'utf-8');
    // Simple regex replacement
    // TODO More robust way?
    assert(
        !/(import\s+|from\s+|require\(\s*)["']\.\/echarts\./.test(code)
        && !/(import\s+|from\s+|require\(\s*)["']echarts\./.test(code),
        'Import echarts.xxx.ts is not supported.'
    );
    code = code.replace(/((import\s+|from\s+|require\(\s*)["'])\.\//g, `$1./${replacement}/`);
    fs.writeFileSync(
        entryFile,
        // Also transform zrender.
        singleTransformImport(code, replacement),
        'utf-8'
    );
}

/**
 * Transform `zrender/src` to `zrender/lib` in all files
 */
async function transformLibFiles(rooltFolder, replacement) {
    const files = await readFilePaths({
        patterns: ['**/*.js', '**/*.d.ts'],
        cwd: rooltFolder
    });
    // Simple regex replacement
    // TODO More robust way?
    for (let fileName of files) {
        let code = fs.readFileSync(fileName, 'utf-8');
        code = singleTransformImport(code, replacement);
        // For lower ts version, not use import type
        // TODO Use https://github.com/sandersn/downlevel-dts ?
        // if (fileName.endsWith('.d.ts')) {
        //     code = singleTransformImportType(code);
        // }
        fs.writeFileSync(fileName, code, 'utf-8');
    }
}

/**
 * 1. Transform zrender/src to zrender/lib
 * 2. Add .js extensions
 */
function singleTransformImport(code, replacement) {
    return transformImport(
        code.replace(/([\"\'])zrender\/src\//g, `$1zrender/${replacement}/`),
        (moduleName) => {
            // Ignore 'tslib' and 'echarts' in the extensions.
            if (moduleName === 'tslib' || moduleName === 'echarts') {
                return moduleName;
            }
            else if (moduleName === 'zrender/lib/export') {
                throw new Error('Should not import the whole zrender library.');
            }
            else if (moduleName.endsWith('.ts')) {
                // Replace ts with js
                return moduleName.replace(/\.ts$/, '.js');
            }
            else if (moduleName.endsWith('.js')) {
                return moduleName;
            }
            else {
                return moduleName + '.js'
            }
        }
    );
}

// function singleTransformImportType(code) {
//     return code.replace(/import\s+type\s+/g, 'import ');
// }

/**
 * @param {Object} transformOptions
 * @param {Object} transformOptions.filesGlobby {patterns: string[], cwd: string}
 * @param {string} [transformOptions.preamble] See './preamble.js'
 * @param {boolean} [transformOptions.transformDEV]
 */
async function transformCode({filesGlobby, preamble, transformDEV}) {

    let filePaths = await readFilePaths(filesGlobby);

    filePaths.map(filePath => {
        let code = fs.readFileSync(filePath, 'utf8');

        if (transformDEV) {
            let result = transformDEVUtil.transform(code, false);
            code = result.code;
        }

        code = autoGeneratedFileAlert + code;

        if (preamble) {
            code = preamble + code;
        }

        fs.writeFileSync(filePath, code, 'utf8');
    });
}

async function readFilePaths({patterns, cwd}) {
    assert(patterns && cwd);
    return (
        await globby(patterns, {cwd})
    ).map(
        srcPath => nodePath.resolve(cwd, srcPath)
    );
}

async function bundleDTS() {

    const outDir = nodePath.resolve(__dirname, '../types/dist');
    const commonConfig = {
        onwarn(warning, rollupWarn) {
            // Not warn circular dependency
            if (warning.code !== 'CIRCULAR_DEPENDENCY') {
                rollupWarn(warning);
            }
        },
        plugins: [
            dts({
                respectExternal: true
            })
//             {
//                 generateBundle(options, bundle) {
//                     for (let chunk of Object.values(bundle)) {
//                         chunk.code = `
// type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
// ${chunk.code}`
//                     }
//                 }
//             }
        ]
    };

    // Bundle chunks.
    const parts = [
        'core', 'charts', 'components', 'renderers', 'option', 'features'
    ];
    const inputs = {};
    parts.forEach(partName => {
        inputs[partName] = nodePath.resolve(__dirname, `../types/src/export/${partName}.d.ts`)
    });

    const bundle = await rollup.rollup({
        input: inputs,
        ...commonConfig
    });
    let idx = 1;
    await bundle.write({
        dir: outDir,
        minifyInternalExports: false,
        manualChunks: (id) => {
            // Only create one chunk.
            return 'shared';
        },
        chunkFileNames: 'shared.d.ts'
    });

    // Bundle all in one
    const bundleAllInOne = await rollup.rollup({
        input: nodePath.resolve(__dirname, `../types/src/export/all.d.ts`),
        ...commonConfig
    });
    await bundleAllInOne.write({
        file: nodePath.resolve(outDir, 'echarts.d.ts')
    });
}

function readTSConfig() {
    // tsconfig.json may have comment string, which is invalid if
    // using `require('tsconfig.json'). So we use a loose parser.
    let filePath = nodePath.resolve(ecDir, 'tsconfig.json');
    const tsConfigText = fs.readFileSync(filePath, {encoding: 'utf8'});
    return (new Function(`return ( ${tsConfigText} )`))();
}

function generateEntries() {
    ['charts', 'components', 'renderers', 'core', 'features'].forEach(entryName => {
        if (entryName !== 'option') {
            const jsCode = fs.readFileSync(nodePath.join(__dirname, `template/${entryName}.js`), 'utf-8');
            fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.js`), jsCode, 'utf-8');
        }

        const dtsCode = fs.readFileSync(nodePath.join(__dirname, `/template/${entryName}.d.ts`), 'utf-8');
        fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.d.ts`), dtsCode, 'utf-8');
    });
}

module.exports.readTSConfig = readTSConfig;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

var getAPIUrl;
var updateSubscription;

$(function () {

    //var TD_API_CONTAINER = '#td-apis';

    //var EV_TD_API = 'eventTDAPISelection';

    //events.register(EV_TD_API);

    // Views.extend('view', {
    //        id: 'apiListView',
    //        container: TD_API_CONTAINER,
    //        partial: 'td-apis-subscriptions',
    //        beforeRender: function (data) {
    //     var user = data;
    //        },
    //        subscriptions: [EV_TD_API],
    //        afterRender: function () {}
    //    });

    /*
     *This function generate the location of the templates used in the rendering
     */
    var getSubscriptionAPI = function (action) {
        return caramel.context + '/asts/api/apis/api-subscriptions/' + action;
    };

    /*
     *This function bind the data and get the UUID needed to return API URL.
     */
    getAPIUrl = function (apiProvider, apiName, apiVersion) {
        var apiData = {};
        apiData.apiName = apiName;
        apiData.apiVersion = apiVersion;
        apiData.apiProvider = apiProvider;
        $.ajax({
            type: 'POST',
            url: getSubscriptionAPI('getUUID'),
            data: apiData,
            success: function (data) {
                var uuid = data.data;
                window.location = 'details/' + uuid;
            }
        });
    };

    /*
     *This function update the metadata by new row values.
     */
    var setMetadata = function (apiProvider, apiName, apiVersion, appId, status, apiUsername, application) {
        metadata.newRowData = [];
        metadata.newRowData.apiProvider = apiProvider;
        metadata.newRowData.apiName = apiName;
        metadata.newRowData.apiVersion = apiVersion;
        metadata.newRowData.appId = appId;
        metadata.newRowData.status = status;
        metadata.newRowData.apiUsername = apiUsername;
        metadata.newRowData.application = application;
    };

    /*
     *This function crete the new content for the "Subscribed APIs & Actions" td.
     */
    var getNewDivContent = function () {
        var contentData = "Unknown state selected!";
        if (metadata.newRowData.status == "UNBLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" id=\"r1-" + metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" value=\"PROD_ONLY_BLOCKED\"> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" id=\"r2-" + metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" value=\"BLOCKED\" checked> Production & Sandbox  Block  </form>";
        } else if (metadata.newRowData.status == "BLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" + metadata.newRowData.apiProvider +
            "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" disabled> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" checked disabled> Production & Sandbox  Unblock  </form>";
        } else if (metadata.newRowData.status == "PROD_ONLY_BLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" + metadata.newRowData.apiProvider +
            "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" checked disabled> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" disabled> Production & Sandbox  Unblock  </form>";
        }
        return contentData;
    };

    /*
     *This function update the api subscription status according to the data sent.
     */
    updateSubscription = function (apiProvider, apiName, apiVersion, appId, status, apiUsername, application) {
        var apiData = {};
        var newStatus = status;
        if (status == 'GET_SELECTED') {
            if (document.getElementById('r1-' + apiProvider + '-' + apiName + '-' + apiVersion + '-' +
                appId + '-' + apiUsername + '-' + application).checked) {
                newStatus = document.getElementById('r1-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).value;
            } else if (document.getElementById('r2-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).checked) {
                newStatus = document.getElementById('r2-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).value;
            }
        }
        setMetadata(apiProvider, apiName, apiVersion, appId, newStatus, apiUsername, application);
        apiData.apiName = apiName;
        apiData.apiVersion = apiVersion;
        apiData.apiProvider = apiProvider;
        apiData.appId = appId;
        apiData.status = newStatus;
        $.ajax({
            type: 'POST',
            url: getSubscriptionAPI('updateSubscription'),
            data: apiData,
            success: function (data) {
                if (data) {
                    document.getElementById("td-" + metadata.newRowData.apiUsername + "-" +
                    metadata.newRowData.application + "-" + metadata.newRowData.apiName + "-" +
                    metadata.newRowData.apiVersion).innerHTML = getNewDivContent();
                }
            }
        });
    };

    //events.publish(EV_TD_API);

});<commit_msg>Removing unwanted code comments<commit_after>/*
 * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

var getAPIUrl;
var updateSubscription;

$(function () {

    /*
     *This function generate the location of the templates used in the rendering
     */
    var getSubscriptionAPI = function (action) {
        return caramel.context + '/asts/api/apis/api-subscriptions/' + action;
    };

    /*
     *This function bind the data and get the UUID needed to return API URL.
     */
    getAPIUrl = function (apiProvider, apiName, apiVersion) {
        var apiData = {};
        apiData.apiName = apiName;
        apiData.apiVersion = apiVersion;
        apiData.apiProvider = apiProvider;
        $.ajax({
            type: 'POST',
            url: getSubscriptionAPI('getUUID'),
            data: apiData,
            success: function (data) {
                var uuid = data.data;
                window.location = 'details/' + uuid;
            }
        });
    };

    /*
     *This function update the metadata by new row values.
     */
    var setMetadata = function (apiProvider, apiName, apiVersion, appId, status, apiUsername, application) {
        metadata.newRowData = [];
        metadata.newRowData.apiProvider = apiProvider;
        metadata.newRowData.apiName = apiName;
        metadata.newRowData.apiVersion = apiVersion;
        metadata.newRowData.appId = appId;
        metadata.newRowData.status = status;
        metadata.newRowData.apiUsername = apiUsername;
        metadata.newRowData.application = application;
    };

    /*
     *This function crete the new content for the "Subscribed APIs & Actions" td.
     */
    var getNewDivContent = function () {
        var contentData = "Unknown state selected!";
        if (metadata.newRowData.status == "UNBLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" id=\"r1-" + metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" value=\"PROD_ONLY_BLOCKED\"> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" id=\"r2-" + metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" value=\"BLOCKED\" checked> Production & Sandbox  Block  </form>";
        } else if (metadata.newRowData.status == "BLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" + metadata.newRowData.apiProvider +
            "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" disabled> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" checked disabled> Production & Sandbox  Unblock  </form>";
        } else if (metadata.newRowData.status == "PROD_ONLY_BLOCKED") {
            contentData = "<form><input type=\"radio\" name=\"" + metadata.newRowData.apiProvider +
            "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" checked disabled> Production Only <input type=\"radio\" name=\"" +
            metadata.newRowData.apiProvider + "-" + metadata.newRowData.apiName + "-" +
            metadata.newRowData.apiVersion + "-" + metadata.newRowData.appId + "-" +
            metadata.newRowData.apiUsername + "-" + metadata.newRowData.application +
            "\" disabled> Production & Sandbox  Unblock  </form>";
        }
        return contentData;
    };

    /*
     *This function update the api subscription status according to the data sent.
     */
    updateSubscription = function (apiProvider, apiName, apiVersion, appId, status, apiUsername, application) {
        var apiData = {};
        var newStatus = status;
        if (status == 'GET_SELECTED') {
            if (document.getElementById('r1-' + apiProvider + '-' + apiName + '-' + apiVersion + '-' +
                appId + '-' + apiUsername + '-' + application).checked) {
                newStatus = document.getElementById('r1-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).value;
            } else if (document.getElementById('r2-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).checked) {
                newStatus = document.getElementById('r2-' + apiProvider + '-' + apiName + '-' +
                apiVersion + '-' + appId + '-' + apiUsername + '-' + application).value;
            }
        }
        setMetadata(apiProvider, apiName, apiVersion, appId, newStatus, apiUsername, application);
        apiData.apiName = apiName;
        apiData.apiVersion = apiVersion;
        apiData.apiProvider = apiProvider;
        apiData.appId = appId;
        apiData.status = newStatus;
        $.ajax({
            type: 'POST',
            url: getSubscriptionAPI('updateSubscription'),
            data: apiData,
            success: function (data) {
                if (data) {
                    document.getElementById("td-" + metadata.newRowData.apiUsername + "-" +
                    metadata.newRowData.application + "-" + metadata.newRowData.apiName + "-" +
                    metadata.newRowData.apiVersion).innerHTML = getNewDivContent();
                }
            }
        });
    };

    //events.publish(EV_TD_API);

});<|endoftext|>


<commit_before>/* Demo application for Addressbook
 */
// Some From http://brondsema.net/blog/index.php/2006/11/25/javascript_rdfparser_from_tabulator

// For quick access to those namespaces:
var FOAF = $rdf.Namespace("http://xmlns.com/foaf/0.1/")
var RDF = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
var RDFS = $rdf.Namespace("http://www.w3.org/2000/01/rdf-schema#")
var OWL = $rdf.Namespace("http://www.w3.org/2002/07/owl#")
var DC = $rdf.Namespace("http://purl.org/dc/elements/1.1/")
var RSS = $rdf.Namespace("http://purl.org/rss/1.0/")
var XSD = $rdf.Namespace("http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#dt-")
var CONTACT = $rdf.Namespace("http://www.w3.org/2000/10/swap/pim/contact#")

var card = function(who) {
    var snip = '
'
    var image = kb.any(who, FOAF('img'));
    if (!image) image = kb.any(who, FOAF('depiction'));
    if (image) {
        snip += '';
    }
    var nam = kb.any(who, FOAF('name'));
    if (!nam) { nam = "???";}
    snip+="
"+nam+"
";

    nam = kb.any(who, FOAF('phone'));
    if (nam) {
        snip+="
"+nam+"
";
    }
    snip += "
"
    $("body").append(snip)
};

// TestStore implementation from dig.csail.mit.edu/2005/ajar/ajaw/test/rdf/rdfparser.test.html
// RDFIndexedFormula from dig.csail.mit.edu/2005/ajar/ajaw/rdf/identity.js
//  (extends RDFFormula from dig.csail.mit.edu/2005/ajar/ajaw/rdf/term.js which has no indexing and smushing)
// for the real implementation used by Tabulator which uses indexing and smushing

// var kb = new TestStore()

var kb = $rdf.graph();

var uri = 'http://bblfish.net/people/henry/card#me';

var person = $rdf.sym(uri);
var docURI = uri.slice(0, uri.indexOf('#'));
var fetch = $rdf.fetcher(kb);
fetch.nowOrWhenFetched(docURI,undefined,function(ok, body){ // @@ check ok
    card(person)
});

// document.write("
"+uri+ " Size: "+kb.statements.length+"
")

var friends = kb.each(person, FOAF('knows'));
var i, n = friends.length, friend;
document.write("
"+n+" acquaintainces
")
for (i=0; i<n; i++) {
    friend = friends[i];
    furi = friend.uri
    if (furi && (furi.indexOf('#') >= 0)) {
//	document.write('Loading:  '+furi+'')
        furi = furi.slice(0, furi.indexOf('#'))
        kb.load(furi)
    }

    sa = kb.any(friend, RDFS('seeAlso'))
    if (sa) {
//	document.write('See also: '+sa.uri+'')
        kb.load(sa.uri)
    }

    card(friend)
}

<commit_msg>Added xhr object to nowOrWhenFetched<commit_after>/* Demo application for Addressbook
 */
// Some From http://brondsema.net/blog/index.php/2006/11/25/javascript_rdfparser_from_tabulator

// For quick access to those namespaces:
var FOAF = $rdf.Namespace("http://xmlns.com/foaf/0.1/")
var RDF = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
var RDFS = $rdf.Namespace("http://www.w3.org/2000/01/rdf-schema#")
var OWL = $rdf.Namespace("http://www.w3.org/2002/07/owl#")
var DC = $rdf.Namespace("http://purl.org/dc/elements/1.1/")
var RSS = $rdf.Namespace("http://purl.org/rss/1.0/")
var XSD = $rdf.Namespace("http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#dt-")
var CONTACT = $rdf.Namespace("http://www.w3.org/2000/10/swap/pim/contact#")

var card = function(who) {
    var snip = '
'
    var image = kb.any(who, FOAF('img'));
    if (!image) image = kb.any(who, FOAF('depiction'));
    if (image) {
        snip += '';
    }
    var nam = kb.any(who, FOAF('name'));
    if (!nam) { nam = "???";}
    snip+="
"+nam+"
";

    nam = kb.any(who, FOAF('phone'));
    if (nam) {
        snip+="
"+nam+"
";
    }
    snip += "
"
    $("body").append(snip)
};

// TestStore implementation from dig.csail.mit.edu/2005/ajar/ajaw/test/rdf/rdfparser.test.html
// RDFIndexedFormula from dig.csail.mit.edu/2005/ajar/ajaw/rdf/identity.js
//  (extends RDFFormula from dig.csail.mit.edu/2005/ajar/ajaw/rdf/term.js which has no indexing and smushing)
// for the real implementation used by Tabulator which uses indexing and smushing

// var kb = new TestStore()

var kb = $rdf.graph();

var uri = 'http://bblfish.net/people/henry/card#me';

var person = $rdf.sym(uri);
var docURI = uri.slice(0, uri.indexOf('#'));
var fetch = $rdf.fetcher(kb);
fetch.nowOrWhenFetched(docURI,undefined,function(ok, body, xhr){ // @@ check ok
    card(person)
});

// document.write("
"+uri+ " Size: "+kb.statements.length+"
")

var friends = kb.each(person, FOAF('knows'));
var i, n = friends.length, friend;
document.write("
"+n+" acquaintainces
")
for (i=0; i<n; i++) {
    friend = friends[i];
    furi = friend.uri
    if (furi && (furi.indexOf('#') >= 0)) {
//	document.write('Loading:  '+furi+'')
        furi = furi.slice(0, furi.indexOf('#'))
        kb.load(furi)
    }

    sa = kb.any(friend, RDFS('seeAlso'))
    if (sa) {
//	document.write('See also: '+sa.uri+'')
        kb.load(sa.uri)
    }

    card(friend)
}

<|endoftext|>


<commit_before>module.exports = function (grunt) {

  'use strict';

  var async = require('async');
  var handlebars = require('handlebars');
  var path = require('path');

  var templatesDir = path.resolve(__dirname, '../templates');

  var gitUser = require('../lib/gitUser');
  var gitCommits = require('../lib/gitCommits');
  var getLogs = require('../lib/getLogs');

  var formats = {
    'gmail': require('../lib/gmail'),
    // 'slack': require('../lib/slack'),
    'hipchat': require('../lib/hipchat')
  };

  grunt.registerTask('bilder/reporter', function () {

    var done = this.async();
    var options = this.options({
      'maxCommits': 3,
      'maxDeployments': 2
    });

    var logFile = path.resolve(options.logFile);
    var log = getLogs(logFile);
    var deployment = {
      'user': gitUser(),
      'environment': options.environment,
      'commits': gitCommits(options.maxCommits),
      'release': options.release,
      'date': (new Date(options.timestamp)).toString()
    };

    // keep only a few last deploy logs
    var deployments = log.deployments;
    deployments.unshift(deployment);
    log.deployments = deployments.slice(0, options.maxDeployments);

    // data for templates
    var current = deployments[0];
    var previous = deployments[1];
    var diff = previous && {
      'previous': previous.commits[0].sha1,
      'current': current.commits[0].sha1
    };

    var data = {
      'user': current.user.name,
      'environment': current.environment,
      'repoUrl': options.repoUrl,
      'changed': !!(diff && (diff.previous !== diff.current)),
      'diff': diff,
      'commits': current.commits.map(function (commit) {
        commit.repoUrl = options.repoUrl;
        return commit;
      })
    };

    // send out notifications
    var notifications = Object.keys(formats);
    async.forEach(notifications, function (type, callback) {
      var template = grunt.file.read(path.join(templatesDir, type + '.tmpl'));
      var templateFn = handlebars.compile(template);
      formats[type](data, templateFn, options[type], grunt, callback);
    }, function () {
      grunt.file.write(logFile, JSON.stringify(log, null, 2));
      done();
    });
  });
};<commit_msg>enable slack, use options for whitelisting<commit_after>module.exports = function (grunt) {

  'use strict';

  var async = require('async');
  var handlebars = require('handlebars');
  var path = require('path');

  var templatesDir = path.resolve(__dirname, '../templates');

  var gitUser = require('../lib/gitUser');
  var gitCommits = require('../lib/gitCommits');
  var getLogs = require('../lib/getLogs');

  var formats = {
    'gmail': require('../lib/gmail'),
    'slack': require('../lib/slack'),
    'hipchat': require('../lib/hipchat')
  };

  grunt.registerTask('bilder/reporter', function () {

    var done = this.async();
    var options = this.options({
      'maxCommits': 3,
      'maxDeployments': 2,
      'notify': []
    });

    var logFile = path.resolve(options.logFile);
    var log = getLogs(logFile);
    var deployment = {
      'user': gitUser(),
      'environment': options.environment,
      'commits': gitCommits(options.maxCommits),
      'release': options.release,
      'date': (new Date(options.timestamp)).toString()
    };

    // keep only a few last deploy logs
    var deployments = log.deployments;
    deployments.unshift(deployment);
    log.deployments = deployments.slice(0, options.maxDeployments);

    // data for templates
    var current = deployments[0];
    var previous = deployments[1];
    var diff = previous && {
      'previous': previous.commits[0].sha1,
      'current': current.commits[0].sha1
    };

    var data = {
      'user': current.user.name,
      'environment': current.environment,
      'repoUrl': options.repoUrl,
      'changed': !!(diff && (diff.previous !== diff.current)),
      'diff': diff,
      'commits': current.commits.map(function (commit) {
        commit.repoUrl = options.repoUrl;
        return commit;
      })
    };

    // send out notifications
    var notifications = options.notify.filter(function (key) {
      return key in formats;
    });
    async.forEach(notifications, function (type, callback) {
      var template = grunt.file.read(path.join(templatesDir, type + '.tmpl'));
      var templateFn = handlebars.compile(template);
      formats[type](data, templateFn, options[type], grunt, callback);
    }, function () {
      grunt.file.write(logFile, JSON.stringify(log, null, 2));
      done();
    });
  });
};<|endoftext|>


<commit_before>module.exports = {
  build: [
    `tsc`,
    `tsc -p static`,
    `rimraf static/index.bundle.* static/css static/fonts`,
    `cpy ./node_modules/bootstrap/dist/css/bootstrap.min.css static/css/`,
    `cpy ./node_modules/bootstrap/fonts/*.* ./static/fonts`,
    `cpy ./node_modules/highlight.js/styles/github.css static/css`,
    `cleancss -o static/index.bundle.css static/index.css`,
    `webpack --config static/webpack.config.js`
  ],
  lint: [
    `tslint "scripts/*.tsx" "*.ts"`,
    `standard "**/*.config.js"`
  ],
  test: [
    'tsc -p spec',
    'jasmine',
    'tsc -p static_spec',
    'karma start static_spec/karma.config.js'
  ],
  fix: [
    `standard --fix "**/*.config.js"`
  ],
  release: [
    `rimraf dist`,
    `clean-release`
  ]
}
<commit_msg>better webpack cli command<commit_after>module.exports = {
  build: [
    `tsc`,
    `tsc -p static`,
    `rimraf static/index.bundle.* static/css static/fonts`,
    `cpy ./node_modules/bootstrap/dist/css/bootstrap.min.css static/css/`,
    `cpy ./node_modules/bootstrap/fonts/*.* ./static/fonts`,
    `cpy ./node_modules/highlight.js/styles/github.css static/css`,
    `cleancss -o static/index.bundle.css static/index.css`,
    `webpack --display-modules --config static/webpack.config.js`
  ],
  lint: [
    `tslint "scripts/*.tsx" "*.ts"`,
    `standard "**/*.config.js"`
  ],
  test: [
    'tsc -p spec',
    'jasmine',
    'tsc -p static_spec',
    'karma start static_spec/karma.config.js'
  ],
  fix: [
    `standard --fix "**/*.config.js"`
  ],
  release: [
    `rimraf dist`,
    `clean-release`
  ]
}
<|endoftext|>