<commit_before>const AEXPR_IDENTIFIER_NAME = "aexpr";

const GET_MEMBER = "getMember";
const GET_AND_CALL_MEMBER = "getAndCallMember";

const IGNORE_STRING = "aexpr ignore";
const IGNORE_INDICATOR = Symbol("aexpr ignore");

const SET_MEMBER_BY_OPERATORS = {
    '=': 'setMember',
    '+=': 'setMemberAddition',
    '-=': 'setMemberSubtraction',
    '*=': 'setMemberMultiplication',
    '/=': 'setMemberDivision',
    '%=': 'setMemberRemainder',
    //'**=': 'setMemberExponentiation',
    '<<=': 'setMemberLeftShift',
    '>>=': 'setMemberRightShift',
    '>>>=': 'setMemberUnsignedRightShift',
    '&=': 'setMemberBitwiseAND',
    '^=': 'setMemberBitwiseXOR',
    '|=': 'setMemberBitwiseOR'
};

const SET_LOCAL = "setLocal";
const GET_LOCAL = "getLocal";

const SET_GLOBAL = "setGlobal";
const GET_GLOBAL = "getGlobal";

const REPLACED_GLOBAL_ASSIGNMENT_FLAG = Symbol('replaced_global_assignment_FLAG');

// TODO: use multiple flag for indication of generated content, marking explicit scopes, etc.
const FLAG_GENERATED_SCOPE_OBJECT = Symbol('FLAG: generated scope object');
const FLAG_SHOULD_NOT_REWRITE_IDENTIFIER = Symbol('FLAG: should not rewrite identifier');
const FLAG_SHOULD_NOT_REWRITE_MEMBER_EXPRESSION = Symbol('FLAG: should not rewrite member expression');
const FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION = Symbol('FLAG: should not rewrite assignment expression');

export default function(param) {
    let { types: t, template, traverse } = param;
    console.log(arguments);

    function getPropertyFromMemberExpression(node) {
        // We are looking for MemberExpressions, which have two distinct incarnations:
        // 1. we have a computed MemberExpression like a[b], with the property being an Expression
        // 2. a non-computed MemberExpression like a.b, with the property being an Identifier
        return node.computed ?
            // We can easily deal with the first case by replacing the MemberExpression with a call
            node.property :
            // In the second case, we introduce a StringLiteral matching the Identifier
            t.stringLiteral(node.property.name);
    }

    const GENERATED_FUNCTION = Symbol("generated function");
    function isGenerated(path) {
        return path.findParent(p => t.isFunctionDeclaration(p.node) && p.node[GENERATED_FUNCTION])
    }

    const GENERATED_IMPORT_IDENTIFIER = Symbol("generated import identifier");

//     let customTemplates = {};
//     customTemplates[SET_MEMBER] = template(`
//   (function(obj, prop, operator, val) {
//     return obj[prop] = val;
//   });
// `);
//
//     customTemplates[GET_MEMBER] = template(`
//   (function(obj, prop) {
//     return obj[prop];
//   });
// `);
//
//     customTemplates[GET_AND_CALL_MEMBER] = template(`
//   (function(obj, prop, args) {
//     return obj[prop](...args)
//   });
// `);
//
//     customTemplates[AEXPR_IDENTIFIER_NAME] = template(`
//   (function(expr) {
//     return { onChange(cb) {}};
//   });
// `);

    function addCustomTemplate(file, name) {
        let declar = file.declarations[name];
        if (declar) return declar;

        let identifier = file.declarations[name] = file.addImport("aexpr-source-transformation-propagation", name, name);
        identifier[GENERATED_IMPORT_IDENTIFIER] = true;
        return identifier;

        // let ref = customTemplates[name];
        // console.log(file.addImport("aexpr-source-transformation-propagation", "aexpr"));
        // let uid = file.declarations[name] = file.scope.generateUidIdentifier(name);
        //
        // ref = ref().expression;
        // ref[GENERATED_FUNCTION] = true;
        //
        // if (t.isFunctionExpression(ref) && !ref.id) {
        //     ref.body._compact = true;
        //     ref._generated = true;
        //     ref.id = uid;
        //     ref.type = "FunctionDeclaration";
        //     file.path.unshiftContainer("body", ref);
        // } else {
        //     ref._compact = true;
        //     file.scope.push({
        //         id: uid,
        //         init: ref,
        //         unique: true
        //     });
        // }
        //
        // return uid;
    }

    return {
        pre(file) {
            console.log("fff", file, traverse);

            traverse(file.ast, {
                enter(path) {
                    if (
                        path.node.leadingComments &&
                        path.node.leadingComments.some(comment => comment.value.includes(IGNORE_STRING))
                    ) {
                        console.log("IGNORED!!!");
                        file[IGNORE_INDICATOR] = true;
                    }
                }
            });
        },
        visitor: {
            Program: {
                enter(path, state) {
                    console.log("file", path, state);
                    if(state.file[IGNORE_INDICATOR]) { console.log("read ignored"); return; }

                    path.traverse({
                        Identifier(path) {
                            //console.log(path.node.name)

                            function logIdentifier(msg, path) {
                                console.log(msg, path.node.name, path.node.loc ? path.node.loc.start.line : '');
                            }

                            // Check for a call to undeclared aexpr:
                            if(
                                t.isCallExpression(path.parent) &&
                                path.node.name === AEXPR_IDENTIFIER_NAME &&
                                !path.scope.hasBinding(AEXPR_IDENTIFIER_NAME)
                            ) {
                                logIdentifier("call to aexpr", path);
                                path.replaceWith(
                                    addCustomTemplate(state.file, AEXPR_IDENTIFIER_NAME)
                                );
                                return;
                            }

                            if(path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER]) { return; }

                            if(
                                // TODO: is there a general way to exclude non-variables?
                            !t.isObjectProperty(path.parent) &&
                            !t.isClassMethod(path.parent) &&
                            !t.isImportSpecifier(path.parent) &&
                            !t.isMemberExpression(path.parent) &&
                            !t.isObjectMethod(path.parent) &&
                            !t.isVariableDeclarator(path.parent) &&
                            !t.isFunctionDeclaration(path.parent) &&
                            !t.isRestElement(path.parent) &&
                            (!t.isAssignmentExpression(path.parent) || !(path.parentKey === 'left'))
                            ) {
                                if(path.scope.hasBinding(path.node.name)) {
                                    path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                    logIdentifier('local var', path)
                                    let parentWithScope = path.findParent(par =>
                                        par.scope.hasOwnBinding(path.node.name)
                                    );
                                    if(parentWithScope) {
                                        let bindings = parentWithScope.scope.bindings;
                                        let scopeName = Object.keys(bindings).find(key => {
                                            return bindings[key].path &&
                                                bindings[key].path.node &&
                                                bindings[key].path.node.id &&
                                                bindings[key].path.node.id[FLAG_GENERATED_SCOPE_OBJECT] // should actually be IS_EXPLICIT_SCOPE_OBJECT
                                        });

                                        let uniqueIdentifier;
                                        if(scopeName) {
                                            uniqueIdentifier = t.identifier(scopeName);
                                            uniqueIdentifier[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                        } else {
                                            uniqueIdentifier = parentWithScope.scope.generateUidIdentifier('scope');
                                            uniqueIdentifier[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                            uniqueIdentifier[FLAG_GENERATED_SCOPE_OBJECT] = true;

                                            //parentWithScope.scope.generateDeclaredUidIdentifier('scope');
                                            parentWithScope.scope.push(t.variableDeclarator(
                                                uniqueIdentifier,
                                                t.objectExpression([])
                                            ));
                                        }
                                        path.replaceWith(
                                            t.sequenceExpression([
                                                t.callExpression(
                                                    addCustomTemplate(state.file, GET_LOCAL),
                                                    [
                                                        uniqueIdentifier,
                                                        t.stringLiteral(path.node.name)
                                                    ]
                                                ),
                                                path.node
                                            ])
                                        );
                                    }
                                } else {
                                    path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                    logIdentifier('get global', path);
                                    path.replaceWith(
                                        t.sequenceExpression([
                                            t.callExpression(
                                                addCustomTemplate(state.file, GET_GLOBAL),
                                                [t.stringLiteral(path.node.name)]
                                            ),
                                            path.node
                                        ])
                                    );
                                }
                                return;
                            }

                            logIdentifier('others', path);
                            return;

                            // l-value of an assignment
                            if(t.isAssignmentExpression(path.parent)
                                && path.parentKey === 'left'
                            ) {
                                //logIdentifier('l-value', path);
                                if(path.scope.hasBinding(path.node.name)) {
                                    logIdentifier('local assignment', path);
                                    console.log(path);
                                } else {
                                    logIdentifier('global assginment', path);
                                }
                            }

                            if(path.node[GENERATED_IMPORT_IDENTIFIER]) {
                                logIdentifier('Generated Import Identifier', path)
                                return;
                            }

                            // global?
                            //if (!path.isReferencedIdentifier()) {
                            //logIdentifier('is no referenced identifier', path);
                            //return;
                            //}

                            // The identifier should not reference a variable in current scope
                            if (path.scope.hasBinding(path.node.name)) {
                                logIdentifier('Binding for ', path);
                                return;
                            }

                            logIdentifier('Unexpected Case', path);

                            return;

                            //if(RESERVED_IDENTIFIERS.includes(path.node.name)) { return; }

                            if(t.isClassDeclaration(path.parent)) {
                                console.log("classDecl", path.node.name);
                                return;
                            }

                            if(t.isClassMethod(path.parent)) {
                                console.log("classMethod", path.node.name);
                                return;
                            }

                            if(t.isObjectMethod(path.parent)) {
                                console.log("objectMethod", path.node.name);
                                return;
                            }
                            if(t.isVariableDeclarator(path.parent)) {
                                console.log("varDecl", path.node.name);
                                return;
                            }

                            // is this correct here?
                            // TODO: is it correct for the locals plugin?
                            if (!path.isReferencedIdentifier()) {
                                console.log("def", path.node.name);
                                return;
                            }

                            // is locally defined variable?
                            if (path.scope.hasBinding(path.node.name)) {
                                console.log("local", path.node.name);
                            } else {
                                // we have a global
                                console.log("global", path.node.name);
                            }
                        },
                        AssignmentExpression(path) {
                            // check, whether we assign to a member (no support for pattern right now)
                            if(t.isMemberExpression(path.node.left) &&
                                !isGenerated(path) &&
                                SET_MEMBER_BY_OPERATORS[path.node.operator]
                            ) {
                                //state.file.addImport
                                path.replaceWith(
                                    t.callExpression(
                                        addCustomTemplate(state.file, SET_MEMBER_BY_OPERATORS[path.node.operator]),
                                        [
                                            path.node.left.object,
                                            getPropertyFromMemberExpression(path.node.left),
                                            //t.stringLiteral(path.node.operator),
                                            path.node.right
                                        ]
                                    )
                                );
                            }

                            if(t.isIdentifier(path.node.left) &&
                                !path.node[REPLACED_GLOBAL_ASSIGNMENT_FLAG]) {
                                if(path.scope.hasBinding(path.node.left.name)) {
                                    // TODO: local assignment
                                    console.log('---local---', path.node.left.name);
                                } else {
                                    // global assginment
                                    //console.log('---global---', path.node.left.name);
                                    path.node[REPLACED_GLOBAL_ASSIGNMENT_FLAG] = true;

                                    let valueToReturn = t.identifier(path.node.left.name);
                                    valueToReturn[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                    path.replaceWith(
                                        t.sequenceExpression([
                                            path.node,
                                            t.callExpression(
                                                addCustomTemplate(state.file, SET_GLOBAL),
                                                [t.stringLiteral(path.node.left.name)]
                                            ),
                                            valueToReturn
                                        ]));

                                }
                            }

                        },

                        MemberExpression(path) {
                            // lval (left values) are ignored for now
                            if(t.isAssignmentExpression(path.parent) && path.key === 'left') { return; }
                            if(isGenerated(path)) { return; }
//FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION
                            path.replaceWith(
                                t.callExpression(
                                    addCustomTemplate(state.file, GET_MEMBER),
                                    [
                                        path.node.object,
                                        getPropertyFromMemberExpression(path.node)
                                    ]
                                )
                            );
                        },

                        CallExpression(path) {
                            if(isGenerated(path)) { return; }

                            // check whether we call a MemberExpression
                            if(t.isMemberExpression(path.node.callee)) {
                                path.replaceWith(
                                    t.callExpression(
                                        addCustomTemplate(state.file, GET_AND_CALL_MEMBER),
                                        [
                                            path.node.callee.object,
                                            getPropertyFromMemberExpression(path.node.callee),
                                            t.arrayExpression(path.node.arguments)
                                        ]
                                    )
                                )
                            } else {
                                if(t.isIdentifier(path.node.callee) && true) {
                                }
                            }
                        }
                    });
                }
            }
        }
    };
}<commit_msg>first working version of setLocal<commit_after>const AEXPR_IDENTIFIER_NAME = "aexpr";

const GET_MEMBER = "getMember";
const GET_AND_CALL_MEMBER = "getAndCallMember";

const IGNORE_STRING = "aexpr ignore";
const IGNORE_INDICATOR = Symbol("aexpr ignore");

const SET_MEMBER_BY_OPERATORS = {
    '=': 'setMember',
    '+=': 'setMemberAddition',
    '-=': 'setMemberSubtraction',
    '*=': 'setMemberMultiplication',
    '/=': 'setMemberDivision',
    '%=': 'setMemberRemainder',
    //'**=': 'setMemberExponentiation',
    '<<=': 'setMemberLeftShift',
    '>>=': 'setMemberRightShift',
    '>>>=': 'setMemberUnsignedRightShift',
    '&=': 'setMemberBitwiseAND',
    '^=': 'setMemberBitwiseXOR',
    '|=': 'setMemberBitwiseOR'
};

const SET_LOCAL = "setLocal";
const GET_LOCAL = "getLocal";

const SET_GLOBAL = "setGlobal";
const GET_GLOBAL = "getGlobal";

const REPLACED_GLOBAL_ASSIGNMENT_FLAG = Symbol('replaced_global_assignment_FLAG');

// TODO: use multiple flag for indication of generated content, marking explicit scopes, etc.
const FLAG_GENERATED_SCOPE_OBJECT = Symbol('FLAG: generated scope object');
const FLAG_SHOULD_NOT_REWRITE_IDENTIFIER = Symbol('FLAG: should not rewrite identifier');
const FLAG_SHOULD_NOT_REWRITE_MEMBER_EXPRESSION = Symbol('FLAG: should not rewrite member expression');
const FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION = Symbol('FLAG: should not rewrite assignment expression');

export default function(param) {
    let { types: t, template, traverse } = param;
    console.log(arguments);

    function getPropertyFromMemberExpression(node) {
        // We are looking for MemberExpressions, which have two distinct incarnations:
        // 1. we have a computed MemberExpression like a[b], with the property being an Expression
        // 2. a non-computed MemberExpression like a.b, with the property being an Identifier
        return node.computed ?
            // We can easily deal with the first case by replacing the MemberExpression with a call
            node.property :
            // In the second case, we introduce a StringLiteral matching the Identifier
            t.stringLiteral(node.property.name);
    }

    const GENERATED_FUNCTION = Symbol("generated function");
    function isGenerated(path) {
        return path.findParent(p => t.isFunctionDeclaration(p.node) && p.node[GENERATED_FUNCTION])
    }

    const GENERATED_IMPORT_IDENTIFIER = Symbol("generated import identifier");

//     let customTemplates = {};
//     customTemplates[SET_MEMBER] = template(`
//   (function(obj, prop, operator, val) {
//     return obj[prop] = val;
//   });
// `);
//
//     customTemplates[GET_MEMBER] = template(`
//   (function(obj, prop) {
//     return obj[prop];
//   });
// `);
//
//     customTemplates[GET_AND_CALL_MEMBER] = template(`
//   (function(obj, prop, args) {
//     return obj[prop](...args)
//   });
// `);
//
//     customTemplates[AEXPR_IDENTIFIER_NAME] = template(`
//   (function(expr) {
//     return { onChange(cb) {}};
//   });
// `);

    function addCustomTemplate(file, name) {
        let declar = file.declarations[name];
        if (declar) return declar;

        let identifier = file.declarations[name] = file.addImport("aexpr-source-transformation-propagation", name, name);
        identifier[GENERATED_IMPORT_IDENTIFIER] = true;
        return identifier;

        // let ref = customTemplates[name];
        // console.log(file.addImport("aexpr-source-transformation-propagation", "aexpr"));
        // let uid = file.declarations[name] = file.scope.generateUidIdentifier(name);
        //
        // ref = ref().expression;
        // ref[GENERATED_FUNCTION] = true;
        //
        // if (t.isFunctionExpression(ref) && !ref.id) {
        //     ref.body._compact = true;
        //     ref._generated = true;
        //     ref.id = uid;
        //     ref.type = "FunctionDeclaration";
        //     file.path.unshiftContainer("body", ref);
        // } else {
        //     ref._compact = true;
        //     file.scope.push({
        //         id: uid,
        //         init: ref,
        //         unique: true
        //     });
        // }
        //
        // return uid;
    }

    return {
        pre(file) {
            console.log("fff", file, traverse);

            traverse(file.ast, {
                enter(path) {
                    if (
                        path.node.leadingComments &&
                        path.node.leadingComments.some(comment => comment.value.includes(IGNORE_STRING))
                    ) {
                        console.log("IGNORED!!!");
                        file[IGNORE_INDICATOR] = true;
                    }
                }
            });
        },
        visitor: {
            Program: {
                enter(path, state) {
                    console.log("file", path, state);
                    if(state.file[IGNORE_INDICATOR]) { console.log("read ignored"); return; }

                    function getIdentifierForExplicitScopeObject(parentWithScope) {
                        let bindings = parentWithScope.scope.bindings;
                        let scopeName = Object.keys(bindings).find(key => {
                            return bindings[key].path &&
                                bindings[key].path.node &&
                                bindings[key].path.node.id &&
                                bindings[key].path.node.id[FLAG_GENERATED_SCOPE_OBJECT] // should actually be IS_EXPLICIT_SCOPE_OBJECT
                        });

                        let uniqueIdentifier;
                        if(scopeName) {
                            uniqueIdentifier = t.identifier(scopeName);
                        } else {
                            uniqueIdentifier = parentWithScope.scope.generateUidIdentifier('scope');
                            uniqueIdentifier[FLAG_GENERATED_SCOPE_OBJECT] = true;

                            //parentWithScope.scope.generateDeclaredUidIdentifier('scope');
                            parentWithScope.scope.push(t.variableDeclarator(
                                uniqueIdentifier,
                                t.objectExpression([])
                            ));
                        }
                        uniqueIdentifier[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                        return uniqueIdentifier;
                    }

                    path.traverse({
                        Identifier(path) {
                            //console.log(path.node.name)

                            function logIdentifier(msg, path) {
                                console.log(msg, path.node.name, path.node.loc ? path.node.loc.start.line : '');
                            }

                            // Check for a call to undeclared aexpr:
                            if(
                                t.isCallExpression(path.parent) &&
                                path.node.name === AEXPR_IDENTIFIER_NAME &&
                                !path.scope.hasBinding(AEXPR_IDENTIFIER_NAME)
                            ) {
                                logIdentifier("call to aexpr", path);
                                path.replaceWith(
                                    addCustomTemplate(state.file, AEXPR_IDENTIFIER_NAME)
                                );
                                return;
                            }

                            if(path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER]) { return; }

                            if(
                                // TODO: is there a general way to exclude non-variables?
                            !t.isObjectProperty(path.parent) &&
                            !t.isClassMethod(path.parent) &&
                            !t.isImportSpecifier(path.parent) &&
                            !t.isMemberExpression(path.parent) &&
                            !t.isObjectMethod(path.parent) &&
                            !t.isVariableDeclarator(path.parent) &&
                            !t.isFunctionDeclaration(path.parent) &&
                            !t.isRestElement(path.parent) &&
                            (!t.isAssignmentExpression(path.parent) || !(path.parentKey === 'left'))
                            ) {
                                if(path.scope.hasBinding(path.node.name)) {
                                    logIdentifier('get local var', path)
                                    path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;

                                    let parentWithScope = path.findParent(par =>
                                        par.scope.hasOwnBinding(path.node.name)
                                    );
                                    if(parentWithScope) {

                                        path.replaceWith(
                                            t.sequenceExpression([
                                                t.callExpression(
                                                    addCustomTemplate(state.file, GET_LOCAL),
                                                    [
                                                        getIdentifierForExplicitScopeObject(parentWithScope),
                                                        t.stringLiteral(path.node.name)
                                                    ]
                                                ),
                                                path.node
                                            ])
                                        );
                                    }
                                } else {
                                    logIdentifier('get global var', path);
                                    path.node[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;

                                    path.replaceWith(
                                        t.sequenceExpression([
                                            t.callExpression(
                                                addCustomTemplate(state.file, GET_GLOBAL),
                                                [t.stringLiteral(path.node.name)]
                                            ),
                                            path.node
                                        ])
                                    );
                                }
                                return;
                            }

                            logIdentifier('others', path);
                            return;

                            // l-value of an assignment
                            if(t.isAssignmentExpression(path.parent)
                                && path.parentKey === 'left'
                            ) {
                                //logIdentifier('l-value', path);
                                if(path.scope.hasBinding(path.node.name)) {
                                    logIdentifier('local assignment', path);
                                    console.log(path);
                                } else {
                                    logIdentifier('global assginment', path);
                                }
                            }

                            if(path.node[GENERATED_IMPORT_IDENTIFIER]) {
                                logIdentifier('Generated Import Identifier', path)
                                return;
                            }

                            // global?
                            //if (!path.isReferencedIdentifier()) {
                            //logIdentifier('is no referenced identifier', path);
                            //return;
                            //}

                            // The identifier should not reference a variable in current scope
                            if (path.scope.hasBinding(path.node.name)) {
                                logIdentifier('Binding for ', path);
                                return;
                            }

                            logIdentifier('Unexpected Case', path);

                            return;

                            //if(RESERVED_IDENTIFIERS.includes(path.node.name)) { return; }

                            if(t.isClassDeclaration(path.parent)) {
                                console.log("classDecl", path.node.name);
                                return;
                            }

                            if(t.isClassMethod(path.parent)) {
                                console.log("classMethod", path.node.name);
                                return;
                            }

                            if(t.isObjectMethod(path.parent)) {
                                console.log("objectMethod", path.node.name);
                                return;
                            }
                            if(t.isVariableDeclarator(path.parent)) {
                                console.log("varDecl", path.node.name);
                                return;
                            }

                            // is this correct here?
                            // TODO: is it correct for the locals plugin?
                            if (!path.isReferencedIdentifier()) {
                                console.log("def", path.node.name);
                                return;
                            }

                            // is locally defined variable?
                            if (path.scope.hasBinding(path.node.name)) {
                                console.log("local", path.node.name);
                            } else {
                                // we have a global
                                console.log("global", path.node.name);
                            }
                        },
                        AssignmentExpression(path) {
                            // check, whether we assign to a member (no support for pattern right now)
                            if(t.isMemberExpression(path.node.left) &&
                                !isGenerated(path) &&
                                SET_MEMBER_BY_OPERATORS[path.node.operator]
                            ) {
                                //state.file.addImport
                                path.replaceWith(
                                    t.callExpression(
                                        addCustomTemplate(state.file, SET_MEMBER_BY_OPERATORS[path.node.operator]),
                                        [
                                            path.node.left.object,
                                            getPropertyFromMemberExpression(path.node.left),
                                            //t.stringLiteral(path.node.operator),
                                            path.node.right
                                        ]
                                    )
                                );
                            }

                            if(t.isIdentifier(path.node.left) &&
                                !path.node[REPLACED_GLOBAL_ASSIGNMENT_FLAG] &&
                                !path.node[FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION]) {
                                if(path.scope.hasBinding(path.node.left.name)) {
                                    // TODO: local assignment
                                    console.log('set local', path.node.left.name);

                                    //logIdentifier('get local var', path)
                                    path.node[FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION] = true;

                                    let parentWithScope = path.findParent(par =>
                                        par.scope.hasOwnBinding(path.node.left.name)
                                    );
                                    console.log('33333');
                                    if(parentWithScope) {
                                        console.log('33333');

                                        path.replaceWith(
                                            t.sequenceExpression([
                                                path.node,
                                                t.callExpression(
                                                    addCustomTemplate(state.file, SET_LOCAL),
                                                    [
                                                        getIdentifierForExplicitScopeObject(parentWithScope),
                                                        t.stringLiteral(path.node.left.name)
                                                    ]
                                                ),
                                                // TODO: FALG this
                                                path.node.left
                                            ])
                                        );
                                    }

                                } else {
                                    // global assginment
                                    //console.log('---global---', path.node.left.name);
                                    path.node[REPLACED_GLOBAL_ASSIGNMENT_FLAG] = true;

                                    let valueToReturn = t.identifier(path.node.left.name);
                                    valueToReturn[FLAG_SHOULD_NOT_REWRITE_IDENTIFIER] = true;
                                    path.replaceWith(
                                        t.sequenceExpression([
                                            path.node,
                                            t.callExpression(
                                                addCustomTemplate(state.file, SET_GLOBAL),
                                                [t.stringLiteral(path.node.left.name)]
                                            ),
                                            valueToReturn
                                        ]));

                                }
                            }

                        },

                        MemberExpression(path) {
                            // lval (left values) are ignored for now
                            if(t.isAssignmentExpression(path.parent) && path.key === 'left') { return; }
                            if(isGenerated(path)) { return; }
//FLAG_SHOULD_NOT_REWRITE_ASSIGNMENT_EXPRESSION
                            path.replaceWith(
                                t.callExpression(
                                    addCustomTemplate(state.file, GET_MEMBER),
                                    [
                                        path.node.object,
                                        getPropertyFromMemberExpression(path.node)
                                    ]
                                )
                            );
                        },

                        CallExpression(path) {
                            if(isGenerated(path)) { return; }

                            // check whether we call a MemberExpression
                            if(t.isMemberExpression(path.node.callee)) {
                                path.replaceWith(
                                    t.callExpression(
                                        addCustomTemplate(state.file, GET_AND_CALL_MEMBER),
                                        [
                                            path.node.callee.object,
                                            getPropertyFromMemberExpression(path.node.callee),
                                            t.arrayExpression(path.node.arguments)
                                        ]
                                    )
                                )
                            } else {
                                if(t.isIdentifier(path.node.callee) && true) {
                                }
                            }
                        }
                    });
                }
            }
        }
    };
}<|endoftext|>


<commit_before>/* global Hammer, FastClick, PouchDB, blobUtil */

(function() {
    var canvas,
        context,
        radius = 15,
        pointerPositions = [],
        db = new PouchDB('fingerpaint'),
        debug = false,
        app = {
            'init': init
        };

    return app;

    function init() {
        initCanvas();
        initTouch();
        initBrushPicker();
        initColorPicker();
        initActions();

        PouchDB.debug.enable('*');
    }

    function initCanvas() {
        canvas = document.getElementById('canvas');
        context = canvas.getContext("2d");

        canvas.width  = window.innerWidth;
        canvas.height = window.innerHeight;

        context.lineCap = context.lineJoin = 'round';

        // clearDrawing();
    }

    function initTouch() {
        var mc = new Hammer(canvas, { });

        mc.on("tap", function(e) {
            log('event type: ' + e.type);

            // prevent the source event from doing it's native behavior
            e.preventDefault();

        	e.pointers.forEach(function(pointer) {
        	    drawCircle(pointer.pageX, pointer.pageY);
        	});
        });

        mc.on("panstart panend", function(e) {
            log('event type: ' + e.type);

            e.preventDefault();

        	e.pointers.forEach(function(pointer, index) {
                if (e.type === "panend") {
                    drawCircle(pointer.pageX, pointer.pageY);
                    pointerPositions[pointer.identifier] = undefined;
                }
        	});
        });

        mc.on("panleft panright panup pandown", function(e) {
            log('event type: ' + e.type);

            e.preventDefault();

        	e.pointers.forEach(function(pointer, index) {
                var pos = pointerPositions[pointer.identifier];
        	    if (pos === undefined) {
        	        pos = {
        	            lastX: pointer.pageX,
            	        lastY: pointer.pageY
        	        };
        	        pointerPositions[pointer.identifier] = pos;
        	    }

        	    drawLine(pos.lastX, pos.lastY, pointer.pageX, pointer.pageY);

                pos.lastX = pointer.pageX;
                pos.lastY = pointer.pageY;
        	});
        });

        mc.get('pan').set({
            // enable vertical pan
            // blocks the vertical scrolling on a touch-device while on the element
            direction: Hammer.DIRECTION_ALL,
            // make it respond to drag and start drawing immediately
            threshold: 0,
            // all your fingers!
            pointers: 0
        });

        mc.get('tap').set({
            // allow this many pixel movement during gesture
            threshold: 10,
            // allow consecutive taps to be very far apart
            posThreshold: 19200
        });

        // disable context menu, often would appear after accidental 2nd finger touch
        window.addEventListener('contextmenu', function (e) { // Not compatibile with IE < 9 but neither is canvas
          e.preventDefault();
        }, false);

        // Chrome: to disable right-swipe back browser, left-swipe forward browser
        // set overscroll-history-navigation=disabled
        // chrome://flags/#overscroll-history-navigation

        // This library is to remove the 300ms touch browser click delay
        $(function() {
          FastClick.attach(document.body);
        });
    }

    function initBrushPicker() {
        $('.brush').on('click', function() {
            radius = $(this).data('radius');
            log('Brush size: ' + radius);
            $('.brush').removeClass('selected');
            $(this).addClass('selected');
        });
    }

    function initColorPicker() {
        $("#picker").spectrum({
            change: changeColor,
            clickoutFiresChange: true, // keep selected color when change brush
            showPaletteOnly: true,
            showPalette:true,
            flat: true,
            color: "#000",
            palette: [
                ["#000","#444","#666","#999","#ccc","#eee","#f3f3f3","#fff"],
                ["#f00","#f90","#ff0","#0f0","#0ff","#00f","#90f","#f0f"],
                ["#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#cfe2f3","#d9d2e9","#ead1dc"],
                ["#ea9999","#f9cb9c","#ffe599","#b6d7a8","#a2c4c9","#9fc5e8","#b4a7d6","#d5a6bd"],
                ["#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6fa8dc","#8e7cc3","#c27ba0"],
                ["#c00","#e69138","#f1c232","#6aa84f","#45818e","#3d85c6","#674ea7","#a64d79"],
                ["#900","#b45f06","#bf9000","#38761d","#134f5c","#0b5394","#351c75","#741b47"],
                ["#600","#783f04","#7f6000","#274e13","#0c343d","#073763","#20124d","#4c1130"]
            ]
        });

        $('#picker').show();
    }

    function initActions() {
        $('#save').on('click', function() {
           saveCanvasImage();
        });
        $('#slideshow').on('click', function() {
           openSlideshow();
        });
    }

    //-----------Drawing functions

    function changeColor(color) {
        context.fillStyle =
            context.strokeStyle =
                color.toHexString();
    }

    function drawCircle(x, y) {
        context.beginPath();
        context.arc(x, y, radius, 0, 2 * Math.PI, false);
        context.fill();
    }

    function drawLine(x1, y1, x2, y2) {
        context.beginPath();
        context.moveTo(x1, y1);
        context.lineTo(x2, y2);
        context.lineWidth = radius * 2;
        context.stroke();
    }

    function clearDrawing() {
        context.fillStyle = "#fff";
        context.rect(0, 0, canvas.width, canvas.height);
        context.fill();
    }

    //-----------File Management
    function saveCanvasImage() {
        var id = (+(new Date)).toString(),
            filename = 'image_' + id + '.png',
            doc = {
                _id: id,
                _attachments: {}
            };

        blobUtil.canvasToBlob(canvas).then(function (blob) {
            doc._attachments[filename] = {
                content_type: 'image/png',
                data: blob
            };

            // Cannot open the window from inside the promise
            var openedWindow = window.open('', 'fingerpaint-slideshow');

            db.put(doc).then(function() {
                // openImage(id, filename);
                // openSlideshow();
                openedWindow.location = 'slideshow.html';
            }).catch(function(err) {
                console.log(err);
            });
        }).catch(function (err) {
            console.log(err);
        });

        log('new doc id: ' + doc._id);
    }

    function openImage(id, filename) {
        db.get(id, {attachments: true}).then(function(doc) {
            var dataBase64 = doc._attachments[filename].data;
            //log('Data: ' + dataBase64);

            window.open('data:image/png;base64,' + dataBase64, filename);
        }).catch(function (err) {
            console.log(err);
        });
    }

    function openSlideshow() {
        window.open('slideshow.html', 'fingerpaint-slideshow');
    }

    function log(msg) {
        if (debug) {
            console.log(msg);
        }
    }

})().init();

// TODO:
//   Set content scalable meta for mobile<commit_msg>While drawing with pen and tablet and hand glances tablet, often a event around origin is fired (renders a line stretching from where pen is to origin).  Updated to track deltas between events and not register any where it temporarily jumps to the origin.<commit_after>/* global Hammer, FastClick, PouchDB, blobUtil */

(function() {
    var canvas,
        context,
        radius = 15,
        maxAllowedMovement = 50,
        pointerPositions = [],
        db = new PouchDB('fingerpaint'),
        debug = false,
        app = {
            'init': init
        };

    return app;

    function init() {
        initCanvas();
        initTouch();
        initBrushPicker();
        initColorPicker();
        initActions();

        PouchDB.debug.enable('*');
    }

    function initCanvas() {
        canvas = document.getElementById('canvas');
        context = canvas.getContext("2d");

        canvas.width  = window.innerWidth;
        canvas.height = window.innerHeight;

        context.lineCap = context.lineJoin = 'round';

        // clearDrawing();
    }

    function initTouch() {
        var mc = new Hammer(canvas, { });

        mc.on("tap", function(e) {
            log('event type: ' + e.type);

            // prevent the source event from doing it's native behavior
            e.preventDefault();

        	e.pointers.forEach(function(pointer) {
        	    drawCircle(pointer.pageX, pointer.pageY);
        	});
        });

        mc.on("panstart panend", function(e) {
            log('event type: ' + e.type);

            e.preventDefault();

        	e.pointers.forEach(function(pointer, index) {
                if (e.type === "panend") {
                    drawCircle(pointer.pageX, pointer.pageY);
                    pointerPositions[pointer.identifier] = undefined;
                }
        	});
        });

        mc.on("panleft panright panup pandown", function(e) {
            log('event type: ' + e.type);

            e.preventDefault();

        	e.pointers.forEach(function(pointer, index) {
                var dx, dy,
                    pos = pointerPositions[pointer.identifier];

        	    if (pos === undefined) {
        	        pos = {
        	            lastX: pointer.pageX,
            	        lastY: pointer.pageY
        	        };
        	        pointerPositions[pointer.identifier] = pos;
        	    }

                dx = Math.abs(pos.lastX - pointer.pageX);
                dy = Math.abs(pos.lastY - pointer.pageY);

                // filter out any erratic jumps to top-left that often occur
                // when using a pen and tablet
                if ( !(dx > maxAllowedMovement && (pos.lastX <= 0 || pointer.pageX <= 0)) &&
                     !(dy > maxAllowedMovement && (pos.lastY <= 0 || pointer.pageY <= 0))
                ) {
                    drawLine(pos.lastX, pos.lastY, pointer.pageX, pointer.pageY);

                    pos.lastX = pointer.pageX;
                    pos.lastY = pointer.pageY;
                }
            });
        });

        mc.get('pan').set({
            // enable vertical pan
            // blocks the vertical scrolling on a touch-device while on the element
            direction: Hammer.DIRECTION_ALL,
            // make it respond to drag and start drawing immediately
            threshold: 0,
            // all your fingers!
            pointers: 0
        });

        mc.get('tap').set({
            // allow this many pixel movement during gesture
            threshold: 10,
            // allow consecutive taps to be very far apart
            posThreshold: 19200
        });

        // disable context menu, often would appear after accidental 2nd finger touch
        window.addEventListener('contextmenu', function (e) { // Not compatibile with IE < 9 but neither is canvas
          e.preventDefault();
        }, false);

        // Chrome: to disable right-swipe back browser, left-swipe forward browser
        // set overscroll-history-navigation=disabled
        // chrome://flags/#overscroll-history-navigation

        // This library is to remove the 300ms touch browser click delay
        $(function() {
          FastClick.attach(document.body);
        });
    }

    function initBrushPicker() {
        $('.brush').on('click', function() {
            radius = $(this).data('radius');
            log('Brush size: ' + radius);
            $('.brush').removeClass('selected');
            $(this).addClass('selected');
        });
    }

    function initColorPicker() {
        $("#picker").spectrum({
            change: changeColor,
            clickoutFiresChange: true, // keep selected color when change brush
            showPaletteOnly: true,
            showPalette:true,
            flat: true,
            color: "#000",
            palette: [
                ["#000","#444","#666","#999","#ccc","#eee","#f3f3f3","#fff"],
                ["#f00","#f90","#ff0","#0f0","#0ff","#00f","#90f","#f0f"],
                ["#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#cfe2f3","#d9d2e9","#ead1dc"],
                ["#ea9999","#f9cb9c","#ffe599","#b6d7a8","#a2c4c9","#9fc5e8","#b4a7d6","#d5a6bd"],
                ["#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6fa8dc","#8e7cc3","#c27ba0"],
                ["#c00","#e69138","#f1c232","#6aa84f","#45818e","#3d85c6","#674ea7","#a64d79"],
                ["#900","#b45f06","#bf9000","#38761d","#134f5c","#0b5394","#351c75","#741b47"],
                ["#600","#783f04","#7f6000","#274e13","#0c343d","#073763","#20124d","#4c1130"]
            ]
        });

        $('#picker').show();
    }

    function initActions() {
        $('#save').on('click', function() {
           saveCanvasImage();
        });
        $('#slideshow').on('click', function() {
           openSlideshow();
        });
    }

    //-----------Drawing functions

    function changeColor(color) {
        context.fillStyle =
            context.strokeStyle =
                color.toHexString();
    }

    function drawCircle(x, y) {
        context.beginPath();
        context.arc(x, y, radius, 0, 2 * Math.PI, false);
        context.fill();
    }

    function drawLine(x1, y1, x2, y2) {
        context.beginPath();
        context.moveTo(x1, y1);
        context.lineTo(x2, y2);
        context.lineWidth = radius * 2;
        context.stroke();
    }

    function clearDrawing() {
        context.fillStyle = "#fff";
        context.rect(0, 0, canvas.width, canvas.height);
        context.fill();
    }

    //-----------File Management
    function saveCanvasImage() {
        var id = (+(new Date)).toString(),
            filename = 'image_' + id + '.png',
            doc = {
                _id: id,
                _attachments: {}
            };

        blobUtil.canvasToBlob(canvas).then(function (blob) {
            doc._attachments[filename] = {
                content_type: 'image/png',
                data: blob
            };

            // Cannot open the window from inside the promise
            var openedWindow = window.open('', 'fingerpaint-slideshow');

            db.put(doc).then(function() {
                // openImage(id, filename);
                // openSlideshow();
                openedWindow.location = 'slideshow.html';
            }).catch(function(err) {
                console.log(err);
            });
        }).catch(function (err) {
            console.log(err);
        });

        log('new doc id: ' + doc._id);
    }

    function openImage(id, filename) {
        db.get(id, {attachments: true}).then(function(doc) {
            var dataBase64 = doc._attachments[filename].data;
            //log('Data: ' + dataBase64);

            window.open('data:image/png;base64,' + dataBase64, filename);
        }).catch(function (err) {
            console.log(err);
        });
    }

    function openSlideshow() {
        window.open('slideshow.html', 'fingerpaint-slideshow');
    }

    function log(msg) {
        if (debug) {
            console.log(msg);
        }
    }

})().init();

// TODO:
//   Set content scalable meta for mobile<|endoftext|>


<commit_before>if (typeof phantom === "undefined") {
  spawn = require("child_process").spawn

  n = function(a,b,c,d) {
    for(b in a) {
      for(c=a=0;d=b.charCodeAt(c++);a%=934)a+=c*d;
      n[(a+360).toString(36)]=b
    }
  }

  module.exports = function(code, objs, cb) {
    var args = [__filename].concat(objs)
      , phantom = spawn("phantomjs", args, {cwd: __dirname})
      , data = ""

    code = code.toString()

    objs
      .slice(0).reverse()
      .forEach(function(scope) {
        code = "n(" + scope + ");" + code
      })

    phantom.stdout.on("data", function(chunk){ data += chunk })
    phantom.stderr.on('data', function(chunk){ cb(chunk); phantom.kill() })

    phantom.on("exit", function(){
      JSON.parse(data).forEach(n)

      for (var key in n) code = code
        .replace(RegExp("\\." + n[key] + "\\b", "g"), "[n." + key + "]")
        .replace(RegExp("'"   + n[key] + "'"  , "g"), "n."  + key      )
        .replace(RegExp('"'   + n[key] + '"'  , "g"), "n."  + key      )

      code = "n=function(a,b,c,d){for(b in a){for(c=a=0;d=b.charCodeAt(c++);a%=934)a+=c*d;n[(a+360).toString(36)]=b}};" + code

      cb(null, code)
    })
  }
}

else {
  var args = phantom.args
    .map(eval)
    .map(function(obj) {
      var key, keys = {}
      for (key in obj) keys[key] = true
      return keys
    })

  console.log(JSON.stringify(args))

  phantom.exit()
}<commit_msg>rename to avoid conflicts<commit_after>if (typeof phantom === "undefined") {
  var spawn = require("child_process").spawn
    , namespace = function(a,b,c,d) {
        for(b in a) {
          for(c=a=0;d=b.charCodeAt(c++);a%=934)a+=c*d;
          namespace[(a+360).toString(36)]=b
        }
      }

  module.exports = function(code, objs, cb) {
    var args = [__filename].concat(objs)
      , phantom = spawn("phantomjs", args, {cwd: __dirname})
      , data = ""

    code = code.toString()

    objs
      .slice(0).reverse()
      .forEach(function(scope) {
        code = "n(" + scope + ");" + code
      })

    phantom.stdout.on("data", function(chunk){ data += chunk })
    phantom.stderr.on('data', function(chunk){ cb(chunk); phantom.kill() })

    phantom.on("exit", function(){
      JSON.parse(data).forEach(namespace)

      for (var key in namespace) code = code
        .replace(RegExp("\\." + namespace[key] + "\\b", "g"), "[n." + key + "]")
        .replace(RegExp("'"   + namespace[key] + "'"  , "g"), "n."  + key      )
        .replace(RegExp('"'   + namespace[key] + '"'  , "g"), "n."  + key      )

      code = "n=function(a,b,c,d){for(b in a){for(c=a=0;d=b.charCodeAt(c++);a%=934)a+=c*d;n[(a+360).toString(36)]=b}};" + code

      cb(null, code)
    })
  }
}

else {
  var args = phantom.args
    .map(eval)
    .map(function(obj) {
      var key, keys = {}
      for (key in obj) keys[key] = true
      return keys
    })

  console.log(JSON.stringify(args))

  phantom.exit()
}<|endoftext|>


<commit_before>(function (module) {
  'use strict';
  var Beep = {
  };
  Beep.parse = function (postContent, callback) {
    var badwords = [
      'anal',
      'anus',
      'arse',
      'ass',
      'ballsack',
      'balls',
      'bastard',
      'bitch',
      'biatch',
      'bloody',
      'blowjob',
      'blow job',
      'bollock',
      'bollok',
      'boner',
      'boob',
      'bugger',
      'bum',
      'butt',
      'buttplug',
      'clitoris',
      'cock',
      'coon',
      //'crap',
      'cunt',
      'damn',
      'dick',
      'dildo',
      'dyke',
      'fag',
      'feck',
      'fellate',
      'fellatio',
      'felching',
      'fuck',
      'f u c k',
      'fudgepacker',
      'fudge packer',
      'flange',
      //'Goddamn',
      //'God damn',
      //'hell',
      'homo',
      'jerk',
      'jizz',
      'knobend',
      'knob end',
      'labia',
      //'lmao',
      //'lmfao',
      'muff',
      'nigger',
      'nigga',
      //'omg',
      'penis',
      'piss',
      'poop',
      'prick',
      'pube',
      'pussy',
      'queer',
      //'scrotum',
      'sex',
      'shit',
      //'s hit',
      'sh1t',
      'slut',
      'smegma',
      'spunk',
      'tit',
      'tosser',
      'turd',
      'twat',
      'vagina',
      'wank',
      'whore'
      //'wtf'
    ];
    for (var w in badwords) {
      var re = new RegExp(badwords[w],"i");

      var hidesting = '';

      for (var i = 0; i < badwords[w].length - 2; i++) {
        hidesting += '*';
      }

      var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1),"ig");
      if (postContent.match(re)) {
        postContent = postContent.replace(re2, hidesting);
      }
    }
    /* TODO
    jQuery('document').ready(function() {
    	for (var w in badwords) {
			var re = new RegExp(badwords[w],"i");
			var hidesting = '';
			for (var i = 0; i < badwords[w].length - 2; i++) {
			hidesting += '*';
			}
			var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1),"i");
			$('.topic-title').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
			$('.header-topic-title').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
			$('.breadcrumb').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
	    }
    }*/
    callback(null, postContent);
  };
  module.exports = Beep;
}(module));

<commit_msg>bending the spoon<commit_after>(function (module) {
  'use strict';
  var Beep = {};
  Beep.parse = function (postContent, callback) {
    var badwords = [
      'anal',
      'anus',
      'arse',
      'ass',
      'ballsack',
      'balls',
      'bastard',
      'bitch',
      'biatch',
      'bloody',
      'blowjob',
      'blow job',
      'bollock',
      'bollok',
      'boner',
      'boob',
      'bugger',
      'bum',
      'butt',
      'buttplug',
      'clitoris',
      'cock',
      'coon',
      'crap',
      'cunt',
      'damn',
      'dick',
      'dildo',
      'dyke',
      'fag',
      'feck',
      'fellate',
      'fellatio',
      'felching',
      'fuck',
      'f u c k',
      'fudgepacker',
      'fudge packer',
      'flange',
      'homo',
      'jerk',
      'jizz',
      'knobend',
      'knob end',
      'labia',
      'muff',
      'nigger',
      'nigga',
      'penis',
      'piss',
      'poop',
      'prick',
      'pube',
      'pussy',
      'queer',
      'sex',
      'shit',
      's hit',
      'sh1t',
      'slut',
      'smegma',
      'spunk',
      'tit',
      'tosser',
      'turd',
      'twat',
      'vagina',
      'wank',
      'whore'
    ];
    for (var w in badwords) {
      var re = new RegExp(badwords[w], 'ig');
      var hidesting = '';
      for (var i = 0; i < badwords[w].length - 2; i++) {
        hidesting += '*';
      }
      var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1), 'ig');
      var hashword = w.replace(re2, hidesting)
      if (postContent.match(re)) {
        postContent = postContent.replace(re, hashword);
      }
    }
    /* TODO
    jQuery('document').ready(function() {
    	for (var w in badwords) {
			var re = new RegExp(badwords[w],"i");
			var hidesting = '';
			for (var i = 0; i < badwords[w].length - 2; i++) {
			hidesting += '*';
			}
			var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1),"i");
			$('.topic-title').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
			$('.header-topic-title').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
			$('.breadcrumb').each(function() {
				if ($(this).html().match(re)) {
					$(this).html($(this).html().replace(re2,hidesting));
				};
			});
	    }
    }*/

    callback(null, postContent);
  };
  module.exports = Beep;
}(module));
<|endoftext|>


<commit_before>'use strict';

var raml2obj = require('raml2obj');
var pjson = require('./package.json');
var Q = require('q');

/**
 * Render the source RAML object using the config's processOutput function
 *
 * The config object should contain at least the following property:
 * processRamlObj: function that takes the raw RAML object and returns a promise with the rendered HTML
 *
 * @param {(String|Object)} source - The source RAML file. Can be a filename, url, contents of the RAML file,
 * or an already-parsed RAML object.
 * @param {Object} config
 * @param {Function} config.processRamlObj
 * @returns a promise
 */
function render(source, config) {
  config = config || {};
  config.raml2HtmlVersion = pjson.version;

  return raml2obj.parse(source).then(function (ramlObj) {
    ramlObj.config = config;

    if (config.processRamlObj) {
      return config.processRamlObj(ramlObj).then(function (html) {
        if (config.postProcessHtml) {
          return config.postProcessHtml(html);
        }
        return html;
      });
    }

    return ramlObj;
  });
}

/**
 * @param {String} [mainTemplate] - The filename of the main template, leave empty to use default templates
 * @param {String} [templatesPath] - Optional, by default it uses the current working directory
 * @returns {{processRamlObj: Function, postProcessHtml: Function}}
 */
function getDefaultConfig(mainTemplate, templatesPath) {
  if (!mainTemplate) {
    mainTemplate = './lib/template.nunjucks';

    // When using the default template, make sure that Nunjucks isn't
    // using the working directory since that might be anything
    templatesPath = __dirname;
  }

  return {
    processRamlObj: function (ramlObj) {
      var nunjucks = require('nunjucks');
      var markdown = require('nunjucks-markdown');
      var marked = require('marked');
      var ramljsonexpander = require('raml-jsonschema-expander');
      var renderer = new marked.Renderer();
      renderer.table = function (thead, tbody) {
        // Render Bootstrap style tables
        return '

' + thead + '

' + tbody + '

';
      };

      // Setup the Nunjucks environment with the markdown parser
      var env = nunjucks.configure(templatesPath, { watch: false });
      markdown.register(env, function (md) {
        return marked(md, { renderer: renderer });
      });

      // Add extra function for finding a security scheme by name
      ramlObj.securitySchemeWithName = function (name) {
        for (var index = 0; index < ramlObj.securitySchemes.length; ++index) {
          if (ramlObj.securitySchemes[index][name] !== null) {
            return ramlObj.securitySchemes[index][name];
          }
        }
      };

      // Parse securedBy and use scopes if they are defined
      ramlObj.renderSecuredBy = function (securedBy) {
        if(typeof securedBy === 'object'){
          var out = "";
          for (key in securedBy){
            out += "" + key + "";
            if(securedBy[key].scopes){
              out += " with scopes:
";
              for (var i = securedBy[key].scopes.length - 1; i >= 0; i--) {
                out += "
" + securedBy[key].scopes[i] + "
";
              };
              out += "
";
            }
          }
          return out;
        } else {
          return securedBy;
        }
      };

      // Find and replace the $ref parameters.
      ramlObj = ramljsonexpander.expandJsonSchemas(ramlObj);

      // Render the main template using the raml object and fix the double quotes
      var html = env.render(mainTemplate, ramlObj);
      html = html.replace(/"/g, '"');

      // Return the promise with the html
      return Q.fcall(function () {
        return html;
      });
    },

    postProcessHtml: function (html) {
      // Minimize the generated html and return the promise with the result
      var Minimize = require('minimize');
      var minimize = new Minimize({ quotes: true });

      var deferred = Q.defer();

      minimize.parse(html, function (error, result) {
        if (error) {
          deferred.reject(new Error(error));
        } else {
          deferred.resolve(result);
        }
      });

      return deferred.promise;
    }
  };
}

module.exports = {
  getDefaultConfig: getDefaultConfig,
  render: render
};

if (require.main === module) {
  console.log('This script is meant to be used as a library. You probably want to run bin/raml2html if you\'re looking for a CLI.');
  process.exit(1);
}
<commit_msg>Change coding style to align with the project<commit_after>'use strict';

var raml2obj = require('raml2obj');
var pjson = require('./package.json');
var Q = require('q');

/**
 * Render the source RAML object using the config's processOutput function
 *
 * The config object should contain at least the following property:
 * processRamlObj: function that takes the raw RAML object and returns a promise with the rendered HTML
 *
 * @param {(String|Object)} source - The source RAML file. Can be a filename, url, contents of the RAML file,
 * or an already-parsed RAML object.
 * @param {Object} config
 * @param {Function} config.processRamlObj
 * @returns a promise
 */
function render(source, config) {
  config = config || {};
  config.raml2HtmlVersion = pjson.version;

  return raml2obj.parse(source).then(function (ramlObj) {
    ramlObj.config = config;

    if (config.processRamlObj) {
      return config.processRamlObj(ramlObj).then(function (html) {
        if (config.postProcessHtml) {
          return config.postProcessHtml(html);
        }
        return html;
      });
    }

    return ramlObj;
  });
}

/**
 * @param {String} [mainTemplate] - The filename of the main template, leave empty to use default templates
 * @param {String} [templatesPath] - Optional, by default it uses the current working directory
 * @returns {{processRamlObj: Function, postProcessHtml: Function}}
 */
function getDefaultConfig(mainTemplate, templatesPath) {
  if (!mainTemplate) {
    mainTemplate = './lib/template.nunjucks';

    // When using the default template, make sure that Nunjucks isn't
    // using the working directory since that might be anything
    templatesPath = __dirname;
  }

  return {
    processRamlObj: function (ramlObj) {
      var nunjucks = require('nunjucks');
      var markdown = require('nunjucks-markdown');
      var marked = require('marked');
      var ramljsonexpander = require('raml-jsonschema-expander');
      var renderer = new marked.Renderer();
      renderer.table = function (thead, tbody) {
        // Render Bootstrap style tables
        return '

' + thead + '

' + tbody + '

';
      };

      // Setup the Nunjucks environment with the markdown parser
      var env = nunjucks.configure(templatesPath, { watch: false });
      markdown.register(env, function (md) {
        return marked(md, { renderer: renderer });
      });

      // Add extra function for finding a security scheme by name
      ramlObj.securitySchemeWithName = function (name) {
        for (var index = 0; index < ramlObj.securitySchemes.length; ++index) {
          if (ramlObj.securitySchemes[index][name] !== null) {
            return ramlObj.securitySchemes[index][name];
          }
        }
      };

      // Parse securedBy and use scopes if they are defined
      ramlObj.renderSecuredBy = function (securedBy) {
        if (typeof securedBy === 'object'){
          var out = "";
          for (key in securedBy) {
            out += "" + key + "";
            if (securedBy[key].scopes) {
              out += " with scopes:
";
              for (var index = 0; index < securedBy[key].scopes.length; ++index) {
                out += "
" + securedBy[key].scopes[index] + "
";
              }
              out += "
";
            }
          }
          return out;
        } else {
          return securedBy;
        }
      };

      // Find and replace the $ref parameters.
      ramlObj = ramljsonexpander.expandJsonSchemas(ramlObj);

      // Render the main template using the raml object and fix the double quotes
      var html = env.render(mainTemplate, ramlObj);
      html = html.replace(/"/g, '"');

      // Return the promise with the html
      return Q.fcall(function () {
        return html;
      });
    },

    postProcessHtml: function (html) {
      // Minimize the generated html and return the promise with the result
      var Minimize = require('minimize');
      var minimize = new Minimize({ quotes: true });

      var deferred = Q.defer();

      minimize.parse(html, function (error, result) {
        if (error) {
          deferred.reject(new Error(error));
        } else {
          deferred.resolve(result);
        }
      });

      return deferred.promise;
    }
  };
}

module.exports = {
  getDefaultConfig: getDefaultConfig,
  render: render
};

if (require.main === module) {
  console.log('This script is meant to be used as a library. You probably want to run bin/raml2html if you\'re looking for a CLI.');
  process.exit(1);
}
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict'

var path = require('path')
var Funnel = require('broccoli-funnel')

module.exports = {
  name: 'ember-cli-bourbon',

  blueprintsPath() {
    return path.join(__dirname, 'blueprints')
  },

  included(app) {
    this._super.included.apply(this, arguments)

    let target = findTargetHost(this, app)

    this.bourbonPath = path.dirname(
      require('resolve').sync('bourbon', {
        basedir: target.project.root
      })
    )
  },

  treeForStyles() {
    return new Funnel(this.bourbonPath, {
      srcDir: 'core',
      destDir: 'app/styles',
      annotation: 'Funnel (bourbon)'
    })
  }
}

function findTargetHost(addon, app) {
  let target = app

  if (typeof addon.import === 'function') {
    target = addon
  } else {
    // If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just
    // use that.
    if (typeof addon._findHost === 'function') {
      target = addon._findHost()
    }

    // Otherwise, we'll use this implementation borrowed from the _findHost()
    // method in ember-cli.
    // Keep iterating upward until we don't have a grandparent.
    // Has to do this grandparent check because at some point we hit the project.
    let current = addon
    do {
      target = current.app || app
    } while (current.parent.parent && (current = current.parent))
  }

  return target
}
<commit_msg>Handle errors if bourbon isn’t installed<commit_after>/* jshint node: true */
'use strict'

var path = require('path')
var Funnel = require('broccoli-funnel')

module.exports = {
  name: 'ember-cli-bourbon',

  blueprintsPath() {
    return path.join(__dirname, 'blueprints')
  },

  included(app) {
    this._super.included.apply(this, arguments)

    let target = findTargetHost(this, app)

    try {
      this.bourbonPath = path.dirname(
        require('resolve').sync('bourbon', {
          basedir: target.project.root
        })
      )
    } catch (err) {
      this.writeError(err.message)
    }
  },

  treeForStyles() {
    return new Funnel(this.bourbonPath, {
      srcDir: 'core',
      destDir: 'app/styles',
      annotation: 'Funnel (bourbon)'
    })
  }
}

function findTargetHost(addon, app) {
  let target = app

  if (typeof addon.import === 'function') {
    target = addon
  } else {
    // If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just
    // use that.
    if (typeof addon._findHost === 'function') {
      target = addon._findHost()
    }

    // Otherwise, we'll use this implementation borrowed from the _findHost()
    // method in ember-cli.
    // Keep iterating upward until we don't have a grandparent.
    // Has to do this grandparent check because at some point we hit the project.
    let current = addon
    do {
      target = current.app || app
    } while (current.parent.parent && (current = current.parent))
  }

  return target
}
<|endoftext|>


<commit_before>
//  - Information about clearing settings in Chrome (can't link to chrome:// URLs)
//  - Indicate if permissions are already granted, if the relevant API allows it.

window.addEventListener("load", function() {

  var toggle = document.querySelector("#toggle");
  toggle.classList.add("instant");
  if (window.location.protocol == "https:") {
    toggle.classList.add("https");
    toggle.protocol = "http:";
  } else if (window.location.protocol == "http:") {
    toggle.classList.add("http");
    toggle.protocol = "https:";
  }
  setTimeout(function() {
    toggle.classList.remove("instant");
  }, 10);

  function displayOutcome(type, outcome) {
    return function() {
      var argList = [outcome, type].concat([].slice.call(arguments));
      switch(outcome) {
        case "success":
          console.info.apply(console, argList);
          break;
        case "error":
          console.error.apply(console, argList);
          break;
        default:
          console.log.apply(console, argList);
      }
      document.getElementById(type).classList.remove('success', 'error', 'default');
      document.getElementById(type).classList.add(outcome);
    };
  };

  function displayOutcomeForNotifications(outcome) {
    switch(outcome) {
      case "granted":
        console.info(outcome, "notifications");
        document.getElementById("notifications").classList.add("success");
        break;
      case "denied":
      case "default":
        // "default" is supposed to be like "denied", except the user hasn't made an explicit decision yet.
        // https://notifications.spec.whatwg.org/#permission-model
        console.error(outcome, "notifications");
        document.getElementById("notifications").classList.add("error");
        break;
      default:
        throw "Unknown notification API response.";
    }
  };

  function triggerDownload() {
    // Based on http://stackoverflow.com/a/27280611
    var a = document.createElement('a');
    a.download = "test-image.png";
    a.href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABC0lEQVQYlTXPPUsCYQDA8b/e04tdQR5ZBpE3NAR6S0SDVDZKDQ2BY9TUy1foE0TQ1Edo6hOEkyUG0QuBRtQgl0hnenVdnZD5eLbU7xv8Avy5X16KhrQBg47EtpziXO6qBhAEeNEm0qr7VdBcLxt2mlnNbhVu0NMAgdj1wvjOoX2xdSt0L7MGgx2GGid8yLrJvJMUkbKfOF8N68bUIqcz2wQR7GUcYvJIr1dFQijvkh89xGV6BPPMwvMF/nQXJMgWiM+KLPX2tc0HNa/HUxDv2owpx7xV+023Hiwpdt7yhmcjj9/NdrIhn8LrPVmotctWVd01Nt27wH9T3YhHU5O+sT/6SuVZKa4cNGoAv/ZMas7pC/KaAAAAAElFTkSuQmCC";
    a.click();
  }

  navigator.getUserMedia = (
    navigator.getUserMedia ||
    navigator.webkitGetUserMedia ||
    navigator.mozGetUserMedia ||
    navigator.msGetUserMedia
  );
  navigator.requestFullscreen = (
    navigator.requestFullscreen ||
    navigator.webkitRequestFullscreen ||
    navigator.mozRequestFullscreen ||
    navigator.msRequestFullscreen
  );
  navigator.requestMIDIAccess = (
    navigator.requestMIDIAccess ||
    navigator.webkitRequestMIDIAccess ||
    navigator.mozRequestMIDIAccess ||
    navigator.msRequestMIDIAccess
  );
  document.body.requestFullScreen = (
    document.body.requestFullScreen ||
    document.body.webkitRequestFullScreen ||
    document.body.mozRequestFullScreen ||
    document.body.msRequestFullScreen
  );
  document.body.requestPointerLock = (
    document.body.requestPointerLock ||
    document.body.webkitRequestPointerLock ||
    document.body.mozRequestPointerLock ||
    document.body.msRequestPointerLock
  );

  var register = {
    "notifications": function () {
      Notification.requestPermission(
        displayOutcomeForNotifications
      );
    },
    "location": function() {
      navigator.geolocation.getCurrentPosition(
        displayOutcome("location", "success"),
        displayOutcome("location", "error")
      );
    },
    "camera": function() {
      navigator.getUserMedia(
        {video: true},
        displayOutcome("camera", "success"),
        displayOutcome("camera", "error")
      );
    },
    "microphone": function() {
      navigator.getUserMedia(
        {audio: true},
        displayOutcome("microphone", "success"),
        displayOutcome("microphone", "error")
      );
    },
    "camera+microphone": function() {
      navigator.getUserMedia(
        {audio: true, video: true},
        displayOutcome("camera+microphone", "success"),
        displayOutcome("camera+microphone", "error")
      );
    },
    "midi": function() {
      navigator.requestMIDIAccess({
        sysex: true
      }).then(
        displayOutcome("midi", "success"),
        displayOutcome("midi", "error")
      );
    },
    "bluetooth": function() {
      navigator.bluetooth.requestDevice({
        filters: [{services: ['battery_service']}]
      }).then(
        displayOutcome("bluetooth", "success"),
        displayOutcome("bluetooth", "error")
      );
    },
    "usb": function() {
      navigator.usb.requestDevice({filters: [{}]}).then(
        displayOutcome("usb", "success"),
        displayOutcome("usb", "error")
      );
    },
    "eme": function() {
      // https://w3c.github.io/encrypted-media/#requestMediaKeySystemAccess
      // Tries multiple configuration per key system. The configurations are in
      // descending order of privileges such that a supported permission-requiring
      // configuration should be attempted before a configuration that does not
      // require permissions.

      var knownKeySystems = [
        "com.example.somesystem",  // Ensure no real system is the first tried.
        "com.widevine.alpha",
        "com.microsoft.playready",
        "com.adobe.primetime",
        "com.apple.fps.2_0",
        "com.apple.fps",
        "com.apple.fps.1_0",
        "com.example.somesystem"  // Ensure no real system is the last tried.
      ];
      var tryKeySystem = function(keySystem) {
        // http://w3c.github.io/encrypted-media/#idl-def-mediakeysystemconfiguration
        // One of videoCapabilities or audioCapabilities must be present. Pick
        // a set that all browsers should support at least one of.
        var capabilities = [
          { contentType: 'audio/mp4; codecs="mp4a.40.2"' },
          { contentType: 'audio/webm; codecs="opus"' },
        ];
        navigator.requestMediaKeySystemAccess(
          keySystem,
          [
            { distinctiveIdentifier: "required",
              persistentState: "required",
              audioCapabilities: capabilities,
              label: "'distinctiveIdentifier' and 'persistentState' required"
            },
            { distinctiveIdentifier: "required",
              audioCapabilities: capabilities,
              label: "'distinctiveIdentifier' required"
            },
            { persistentState: "required",
              audioCapabilities: capabilities,
              label: "'persistentState' required"
            },
            { audioCapabilities: capabilities,
              label: "empty"
            },
            { label: "no capabilities" }
          ]
        ).then(
          function (mediaKeySystemAccess) {
            displayOutcome("eme", "success")(
              "Key System: " + keySystem,
              "Configuration: " + mediaKeySystemAccess.getConfiguration().label,
              mediaKeySystemAccess);
          },
          function (error) {
            if (knownKeySystems.length > 0)
              return tryKeySystem(knownKeySystems.shift());

            displayOutcome("eme", "error")(
              error,
              error.name == "NotSupportedError" ? "No known key systems supported or permitted." : "");
          }
        );
      };
      tryKeySystem(knownKeySystems.shift());
    },
    "copy": (function() {
      var interceptCopy = false;

      document.addEventListener("copy", function(e){
        if (interceptCopy) {
          // From http://www.w3.org/TR/clipboard-apis/#h4_the-copy-action
          e.clipboardData.setData("text/plain",
            "This text was copied from the permission.site clipboard example."
          );
          e.clipboardData.setData("text/html",
            "This text was copied from the " +
            "" +
            "permission.site clipboard example."
          );
          e.preventDefault();
        }
      });

      return function() {
        interceptCopy = true;
        document.execCommand("copy");
        interceptCopy = false;
      };
    }()),
    "popup": function() {
      var w = window.open(
        location.href,
        "Popup",
        "resizable,scrollbars,status"
      )
      displayOutcome("popup", w ? "success" : "error")(w);
    },
    "popup-delayed": function() {
      setTimeout(function() {
        var w = window.open(
          location.href,
          "Popup",
          "resizable,scrollbars,status"
        )
        displayOutcome("popup-delayed", w ? "success" : "error")(w);
      }, 2000);
    },
    "fullscreen": function() {
      // Note: As of 2014-12-16, fullscreen only allows "ask" and "allow" in Chrome.
      document.body.requestFullScreen(
        /* no callback */
      );
    },
    "pointerlock": function() {
      document.body.requestPointerLock(
        /* no callback */
      );
    },
    "download": function() {
      // Two downloads at the same time trigger a permission prompt in Chrome.
      triggerDownload();
      triggerDownload();
    },
    "keygen": function() {
      var keygen = document.createElement("keygen");
      document.getElementById("keygen-container").appendChild(keygen);
    },
    "persistent-storage": function() {
      // https://storage.spec.whatwg.org
      navigator.storage.persist().then(
        function(persisted) {
          displayOutcome("persistent-storage", persisted ? "success" : "default")(persisted);
        },
        displayOutcome("persistent-storage", "error")
      )
    },
    "quota-management": function() {
      // https://www.w3.org/TR/2012/WD-quota-api-20120703/
      navigator.webkitPersistentStorage.queryUsageAndQuota(
        function(currentUsageInBytes, currentQuotaInBytes) {
          var quota = currentQuotaInBytes + 1024 * 1024;
          navigator.webkitPersistentStorage.requestQuota(quota,
            function(newQuota) {
              displayOutcome("quota-management", (newQuota == quota) ? "success" : "default")(newQuota);
            },
            displayOutcome("quota-management", "error"));
        },
        displayOutcome("quota-management", "error")
      )
    },
    "protocol-handler": function() {
      // https://www.w3.org/TR/html5/webappapis.html#navigatorcontentutils
      var url = window.location + '%s';
      try {
        navigator.registerProtocolHandler('web+permission.site', url, 'title');
      } catch(e) {
        displayOutcome("protocol-handler", "error")(e);
      }
    }
  };

  for (var type in register) {
    document.getElementById(type).addEventListener('click',
      register[type]
    );
  }

});
<commit_msg>Use 'acceptAllDevices' for Bluetooth.<commit_after>
//  - Information about clearing settings in Chrome (can't link to chrome:// URLs)
//  - Indicate if permissions are already granted, if the relevant API allows it.

window.addEventListener("load", function() {

  var toggle = document.querySelector("#toggle");
  toggle.classList.add("instant");
  if (window.location.protocol == "https:") {
    toggle.classList.add("https");
    toggle.protocol = "http:";
  } else if (window.location.protocol == "http:") {
    toggle.classList.add("http");
    toggle.protocol = "https:";
  }
  setTimeout(function() {
    toggle.classList.remove("instant");
  }, 10);

  function displayOutcome(type, outcome) {
    return function() {
      var argList = [outcome, type].concat([].slice.call(arguments));
      switch(outcome) {
        case "success":
          console.info.apply(console, argList);
          break;
        case "error":
          console.error.apply(console, argList);
          break;
        default:
          console.log.apply(console, argList);
      }
      document.getElementById(type).classList.remove('success', 'error', 'default');
      document.getElementById(type).classList.add(outcome);
    };
  };

  function displayOutcomeForNotifications(outcome) {
    switch(outcome) {
      case "granted":
        console.info(outcome, "notifications");
        document.getElementById("notifications").classList.add("success");
        break;
      case "denied":
      case "default":
        // "default" is supposed to be like "denied", except the user hasn't made an explicit decision yet.
        // https://notifications.spec.whatwg.org/#permission-model
        console.error(outcome, "notifications");
        document.getElementById("notifications").classList.add("error");
        break;
      default:
        throw "Unknown notification API response.";
    }
  };

  function triggerDownload() {
    // Based on http://stackoverflow.com/a/27280611
    var a = document.createElement('a');
    a.download = "test-image.png";
    a.href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABC0lEQVQYlTXPPUsCYQDA8b/e04tdQR5ZBpE3NAR6S0SDVDZKDQ2BY9TUy1foE0TQ1Edo6hOEkyUG0QuBRtQgl0hnenVdnZD5eLbU7xv8Avy5X16KhrQBg47EtpziXO6qBhAEeNEm0qr7VdBcLxt2mlnNbhVu0NMAgdj1wvjOoX2xdSt0L7MGgx2GGid8yLrJvJMUkbKfOF8N68bUIqcz2wQR7GUcYvJIr1dFQijvkh89xGV6BPPMwvMF/nQXJMgWiM+KLPX2tc0HNa/HUxDv2owpx7xV+023Hiwpdt7yhmcjj9/NdrIhn8LrPVmotctWVd01Nt27wH9T3YhHU5O+sT/6SuVZKa4cNGoAv/ZMas7pC/KaAAAAAElFTkSuQmCC";
    a.click();
  }

  navigator.getUserMedia = (
    navigator.getUserMedia ||
    navigator.webkitGetUserMedia ||
    navigator.mozGetUserMedia ||
    navigator.msGetUserMedia
  );
  navigator.requestFullscreen = (
    navigator.requestFullscreen ||
    navigator.webkitRequestFullscreen ||
    navigator.mozRequestFullscreen ||
    navigator.msRequestFullscreen
  );
  navigator.requestMIDIAccess = (
    navigator.requestMIDIAccess ||
    navigator.webkitRequestMIDIAccess ||
    navigator.mozRequestMIDIAccess ||
    navigator.msRequestMIDIAccess
  );
  document.body.requestFullScreen = (
    document.body.requestFullScreen ||
    document.body.webkitRequestFullScreen ||
    document.body.mozRequestFullScreen ||
    document.body.msRequestFullScreen
  );
  document.body.requestPointerLock = (
    document.body.requestPointerLock ||
    document.body.webkitRequestPointerLock ||
    document.body.mozRequestPointerLock ||
    document.body.msRequestPointerLock
  );

  var register = {
    "notifications": function () {
      Notification.requestPermission(
        displayOutcomeForNotifications
      );
    },
    "location": function() {
      navigator.geolocation.getCurrentPosition(
        displayOutcome("location", "success"),
        displayOutcome("location", "error")
      );
    },
    "camera": function() {
      navigator.getUserMedia(
        {video: true},
        displayOutcome("camera", "success"),
        displayOutcome("camera", "error")
      );
    },
    "microphone": function() {
      navigator.getUserMedia(
        {audio: true},
        displayOutcome("microphone", "success"),
        displayOutcome("microphone", "error")
      );
    },
    "camera+microphone": function() {
      navigator.getUserMedia(
        {audio: true, video: true},
        displayOutcome("camera+microphone", "success"),
        displayOutcome("camera+microphone", "error")
      );
    },
    "midi": function() {
      navigator.requestMIDIAccess({
        sysex: true
      }).then(
        displayOutcome("midi", "success"),
        displayOutcome("midi", "error")
      );
    },
    "bluetooth": function() {
      navigator.bluetooth.requestDevice({
        // filters: [...] <- Prefer filters to save energy & show relevant devices.
        // acceptAllDevices here ensures dialog can populate, we don't care with what.
        acceptAllDevices:true
      }).then(
        displayOutcome("bluetooth", "success"),
        displayOutcome("bluetooth", "error")
      );
    },
    "usb": function() {
      navigator.usb.requestDevice({filters: [{}]}).then(
        displayOutcome("usb", "success"),
        displayOutcome("usb", "error")
      );
    },
    "eme": function() {
      // https://w3c.github.io/encrypted-media/#requestMediaKeySystemAccess
      // Tries multiple configuration per key system. The configurations are in
      // descending order of privileges such that a supported permission-requiring
      // configuration should be attempted before a configuration that does not
      // require permissions.

      var knownKeySystems = [
        "com.example.somesystem",  // Ensure no real system is the first tried.
        "com.widevine.alpha",
        "com.microsoft.playready",
        "com.adobe.primetime",
        "com.apple.fps.2_0",
        "com.apple.fps",
        "com.apple.fps.1_0",
        "com.example.somesystem"  // Ensure no real system is the last tried.
      ];
      var tryKeySystem = function(keySystem) {
        // http://w3c.github.io/encrypted-media/#idl-def-mediakeysystemconfiguration
        // One of videoCapabilities or audioCapabilities must be present. Pick
        // a set that all browsers should support at least one of.
        var capabilities = [
          { contentType: 'audio/mp4; codecs="mp4a.40.2"' },
          { contentType: 'audio/webm; codecs="opus"' },
        ];
        navigator.requestMediaKeySystemAccess(
          keySystem,
          [
            { distinctiveIdentifier: "required",
              persistentState: "required",
              audioCapabilities: capabilities,
              label: "'distinctiveIdentifier' and 'persistentState' required"
            },
            { distinctiveIdentifier: "required",
              audioCapabilities: capabilities,
              label: "'distinctiveIdentifier' required"
            },
            { persistentState: "required",
              audioCapabilities: capabilities,
              label: "'persistentState' required"
            },
            { audioCapabilities: capabilities,
              label: "empty"
            },
            { label: "no capabilities" }
          ]
        ).then(
          function (mediaKeySystemAccess) {
            displayOutcome("eme", "success")(
              "Key System: " + keySystem,
              "Configuration: " + mediaKeySystemAccess.getConfiguration().label,
              mediaKeySystemAccess);
          },
          function (error) {
            if (knownKeySystems.length > 0)
              return tryKeySystem(knownKeySystems.shift());

            displayOutcome("eme", "error")(
              error,
              error.name == "NotSupportedError" ? "No known key systems supported or permitted." : "");
          }
        );
      };
      tryKeySystem(knownKeySystems.shift());
    },
    "copy": (function() {
      var interceptCopy = false;

      document.addEventListener("copy", function(e){
        if (interceptCopy) {
          // From http://www.w3.org/TR/clipboard-apis/#h4_the-copy-action
          e.clipboardData.setData("text/plain",
            "This text was copied from the permission.site clipboard example."
          );
          e.clipboardData.setData("text/html",
            "This text was copied from the " +
            "" +
            "permission.site clipboard example."
          );
          e.preventDefault();
        }
      });

      return function() {
        interceptCopy = true;
        document.execCommand("copy");
        interceptCopy = false;
      };
    }()),
    "popup": function() {
      var w = window.open(
        location.href,
        "Popup",
        "resizable,scrollbars,status"
      )
      displayOutcome("popup", w ? "success" : "error")(w);
    },
    "popup-delayed": function() {
      setTimeout(function() {
        var w = window.open(
          location.href,
          "Popup",
          "resizable,scrollbars,status"
        )
        displayOutcome("popup-delayed", w ? "success" : "error")(w);
      }, 2000);
    },
    "fullscreen": function() {
      // Note: As of 2014-12-16, fullscreen only allows "ask" and "allow" in Chrome.
      document.body.requestFullScreen(
        /* no callback */
      );
    },
    "pointerlock": function() {
      document.body.requestPointerLock(
        /* no callback */
      );
    },
    "download": function() {
      // Two downloads at the same time trigger a permission prompt in Chrome.
      triggerDownload();
      triggerDownload();
    },
    "keygen": function() {
      var keygen = document.createElement("keygen");
      document.getElementById("keygen-container").appendChild(keygen);
    },
    "persistent-storage": function() {
      // https://storage.spec.whatwg.org
      navigator.storage.persist().then(
        function(persisted) {
          displayOutcome("persistent-storage", persisted ? "success" : "default")(persisted);
        },
        displayOutcome("persistent-storage", "error")
      )
    },
    "quota-management": function() {
      // https://www.w3.org/TR/2012/WD-quota-api-20120703/
      navigator.webkitPersistentStorage.queryUsageAndQuota(
        function(currentUsageInBytes, currentQuotaInBytes) {
          var quota = currentQuotaInBytes + 1024 * 1024;
          navigator.webkitPersistentStorage.requestQuota(quota,
            function(newQuota) {
              displayOutcome("quota-management", (newQuota == quota) ? "success" : "default")(newQuota);
            },
            displayOutcome("quota-management", "error"));
        },
        displayOutcome("quota-management", "error")
      )
    },
    "protocol-handler": function() {
      // https://www.w3.org/TR/html5/webappapis.html#navigatorcontentutils
      var url = window.location + '%s';
      try {
        navigator.registerProtocolHandler('web+permission.site', url, 'title');
      } catch(e) {
        displayOutcome("protocol-handler", "error")(e);
      }
    }
  };

  for (var type in register) {
    document.getElementById(type).addEventListener('click',
      register[type]
    );
  }

});
<|endoftext|>